java - 如何在 Java 中逐步解码大型多字节字符串文件?

标签 java string unicode decoding

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

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 确实是允许将字节解码为字符的底层机制。简而言之,您可以这样说:

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

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

现在,如果您担心“坏字符”溜进来的能力,您还可以选择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
}

默认替换操作的一个异常(exception)出现在 Java 8 中:Files.newBufferedReader(somePath) 将始终尝试以 UTF-8 读取,并使用默认操作 REPORT.

关于java - 如何在 Java 中逐步解码大型多字节字符串文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33921379/

相关文章:

c# - 在多个文件中搜索多个字符串的 Grep 工具

java - 用同一索引中的不同字符替换特定索引字符

haskell - 这个 Haskell unicode 变量名有什么问题?

java - 如何根据用户输入的位字符串用 1's and 0' 填充数组

java - 使用 thymeleaf 碎片

java - 将维基百科页面的内容获取到 Android

java - 从 Android 网页获取 HTML 正文?

java - 主.java :9: error: variable letters might not have been initialized - Reversed string

java - 无法显示特定的unicode字符

delphi - Inno Setup Delphi DLL中的Unicode版本和字符串参数