编程语言
首页 > 编程语言> > 如何使用Java逐步解码大的多字节字符串文件?

如何使用Java逐步解码大的多字节字符串文件?

作者:互联网

我有一个程序可能需要处理可能包含多字节编码的大文件.我当前执行此操作的代码存在一个问题,即创建一个存储整个文件的内存结构,如果文件很大,可能会导致内存不足错误:

Charset charset = Charset.forName( "UTF-8" );
CharsetDecoder decoder = charset.newDecoder();
FileInputStream fis = new FileInputStream( file );
FileChannel fc = fis.getChannel();
int lenFile = (int)fc.size();
MappedByteBuffer bufferFile = fc.map( FileChannel.MapMode.READ_ONLY, 0, lenFile );
CharBuffer cb = decoder.decode( bufferFile );
// process character buffer
fc.close();

问题是,如果我使用较小的缓冲区将文件字节的内容切碎,然后将其零碎地输入解码器,则缓冲区可能会在多字节序列的中间结束.我应该如何处理这个问题?

解决方法:

就像使用阅读器一样简单.

CharsetDecoder实际上是允许将字节解码为char的基本机制.简而言之,您可以这样说:

// Extrapolation...
byte stream --> decoding       --> char stream
InputStream --> CharsetDecoder --> Reader

鲜为人知的事实是,JDK中的大多数(但不是全部…请参见下文)默认解码器(例如,从FileReader创建的解码器,或仅具有字符集的InputStreamReader)将具有CodingErrorAction.REPLACE策略.效果是将输入中的任何无效字节序列替换为Unicode replacement character(是的,那是臭名昭著的“).

现在,如果您担心“坏字符”的插入能力,则还可以选择“报告”策略.您也可以在读取文件时执行以下操作:这将对任何格式错误的字节序列引发MalformedInputException的影响:

// This is 2015. File is obsolete.
final Path path = Paths.get(...);
final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder()
    .onMalformedInput(CodingErrorAction.REPORT);

try (
    final InputStream in = Files.newInputStream(path);
    final Reader reader = new InputStreamReader(in, decoder);
) {
    // use the reader
}

该默认替换操作的一种例外出现在Java 8中:Files.newBufferedReader(somePath)将始终尝试以UTF-8读取,并且默认操作为REPORT.

标签:decoding,unicode,string,java
来源: https://codeday.me/bug/20191027/1946067.html