我有一个程序可能需要处理可能包含多字节编码的大文件。我当前执行此操作的代码存在创建内存结构来保存整个文件的问题,如果文件很大,这可能会导致内存不足错误:
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();
问题是,如果我使用较小的缓冲区切碎文件字节内容并将其零碎地馈送到解码器,则缓冲区可能会在多字节序列的中间结束。我该如何应对这个问题?
就像使用一个一样简单Reader
.
A CharsetDecoder
确实是允许将字节解码为字符的底层机制。简而言之,你可以这样说:
// Extrapolation...
byte stream --> decoding --> char stream
InputStream --> CharsetDecoder --> Reader
鲜为人知的事实是,JDK 中的大多数(但不是全部......见下文)默认解码器(例如从FileReader
例如,或者InputStreamReader
只有一个字符集)将有一个政策CodingErrorAction.REPLACE
。效果是将输入中的任何无效字节序列替换为Unicode 替换字符 http://www.fileformat.info/info/unicode/char/fffd/index.htm(是的,那个臭名昭著的�)。
现在,如果您担心“坏人”溜进来,您还可以选择以下政策:REPORT
。您也可以在读取文件时执行此操作,如下所示;这将产生抛出一个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
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)