Java中如何不创建String对象返回Cp037字节数组?
如何不创建String对象返回Cp037编码的byte[]?
当然可以借助Charset和NIO的编码/解码API来实现,完全不需要创建中间String对象。首先得理清你现有方法的逻辑问题:你的当前方法其实是把输入的Cp037编码字节数组解码成String,再把String用默认字符集编码成字节数组——这和方法名encodeCp037的语义不符,也不是返回Cp037编码的结果。
下面分两种常见需求给出实现方案:
需求1:将字符数据编码为Cp037格式的字节数组
如果你的目标是把char数组或字符序列直接编码成Cp037字节数组,直接用CharsetEncoder就能完成,全程无需创建String:
import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; public byte[] encodeToCp037(char[] chars) { Charset cp037 = Charset.forName("Cp037"); CharsetEncoder encoder = cp037.newEncoder(); // 预估输出字节缓冲区大小,减少扩容开销 ByteBuffer outputBuffer = ByteBuffer.allocate((int) (chars.length * encoder.maxBytesPerChar())); CharBuffer inputBuffer = CharBuffer.wrap(chars); // 执行编码操作 CoderResult result = encoder.encode(inputBuffer, outputBuffer, true); if (result.isError()) { throw new UnsupportedOperationException("Failed to encode to Cp037: " + result.toString()); } // 刷新编码器,确保所有数据写入输出缓冲区 encoder.flush(outputBuffer); outputBuffer.flip(); // 复制有效结果到新数组(避免返回缓冲区的多余空间) byte[] resultBytes = new byte[outputBuffer.remaining()]; outputBuffer.get(resultBytes); return resultBytes; }
需求2:将其他编码的字节数组转成Cp037编码
如果你的输入是其他编码的字节数组,想要转换为Cp037编码,也可以全程不用String,先解码为字符再编码为Cp037:
import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; public byte[] convertToCp037(byte[] inputBytes, String inputCharsetName) { Charset inputCharset = Charset.forName(inputCharsetName); Charset cp037 = Charset.forName("Cp037"); CharsetDecoder decoder = inputCharset.newDecoder(); CharsetEncoder encoder = cp037.newEncoder(); ByteBuffer inputBuffer = ByteBuffer.wrap(inputBytes); // 预估字符缓冲区大小 CharBuffer charBuffer = CharBuffer.allocate((int) (inputBytes.length * decoder.maxCharsPerByte())); // 第一步:解码输入字节为字符 CoderResult decodeResult = decoder.decode(inputBuffer, charBuffer, true); if (decodeResult.isError()) { throw new UnsupportedOperationException("Failed to decode input with charset " + inputCharsetName + ": " + decodeResult.toString()); } decoder.flush(charBuffer); charBuffer.flip(); // 第二步:将字符编码为Cp037字节 ByteBuffer outputBuffer = ByteBuffer.allocate((int) (charBuffer.remaining() * encoder.maxBytesPerChar())); CoderResult encodeResult = encoder.encode(charBuffer, outputBuffer, true); if (encodeResult.isError()) { throw new UnsupportedOperationException("Failed to encode to Cp037: " + encodeResult.toString()); } encoder.flush(outputBuffer); outputBuffer.flip(); byte[] resultBytes = new byte[outputBuffer.remaining()]; outputBuffer.get(resultBytes); return resultBytes; }
这种实现的优势
- 避免了中间
String对象的创建,减少内存开销和GC压力,处理大数组时性能提升明显 - 能更精细地控制编码/解码流程,精准处理无效字节序列等异常情况
- 基于Java NIO的字符集API,是官方推荐的高效编码/解码方式
另外需要说明:Charset.forName("Cp037")是安全的,因为Cp037是Java内置支持的IBM EBCDIC类编码,几乎不会抛出UnsupportedEncodingException(除非JVM被特殊修改,这种情况极其罕见)。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

