使用 InputStreamReader 两次

Use InputStreamReader twice

我必须在读取文件之前检查文件的编码。要检查编码,我使用此方法:

        try {
            CharsetDecoder decoder= Charset.forName("UTF-8").newDecoder();
            decoder.onMalformedInput(CodingErrorAction.REPORT);
            decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
            final InputStreamReader input = new InputStreamReader(is, decoder);
            int data = input.read();
            while(data != -1){
                data = input.read();
            }
            input.close();
        } catch (MalformedInputException e) {
            LOGGER.error(The file encoding is wrong!");
            throw new MalformedInputException(Math.toIntExact(file.length()));
        }
    }

这里是调用它的代码:

    InputStream is = new FileInputStream(file);
    checkFileEncoding(is);

    List<MyObject> list = newArrayList();
    try(CSVReader reader = new CSVReader(new InputStreamReader(is), ';')) {
        list =  reader.readAll().stream()
                .skip(1) // 
                .map(myObjectMap)
                .filter(o -> o != null)
                .collect(toList());
    }

问题是,当我之前调用 checkFileEncoding 时,我的列表是空的。我认为这是因为我读了我的文件两次。我应该怎么做?

final InputStreamReader input = new InputStreamReader(is, decoder);

您的 InputStreamReader 将从输入流中读取所有数据。这意味着不再有可用数据。另外你已经关闭了。

您需要创建 InputStream 两次。 1次测试字符集,1次实际读取数据。

所以改变

InputStream is = new FileInputStream(file);
checkFileEncoding(is);

InputStream is = new FileInputStream(file);
checkFileEncoding(is);
is = new FileInputStream(file);

也在

之后
try(CSVReader reader ..
..
}

添加

is.close();

尝试 Guess Encoding 库。

Charset charset = CharsetToolkit.guessEncoding(file, 4096, StandardCharsets.UTF_8);

这应该 return 您的预期结果。

我针对 HTML 文件进行了尝试,结果是 US-ASCII 作为字符集。

你可以试试Any23图书馆

Charset charset = Charset.forName(new TikaEncodingDetector().guessEncoding(new FileInputStream(file)));