全包Charset避免"java.nio.charset.MalformedInputException:输入长度= 1"?

Jon*_*Lam 72 java character-encoding

我正在用Java创建一个简单的wordcount程序,它读取目录的基于文本的文件.

但是,我继续得到错误:

java.nio.charset.MalformedInputException: Input length = 1
Run Code Online (Sandbox Code Playgroud)

从这行代码:

BufferedReader reader = Files.newBufferedReader(file,Charset.forName("UTF-8"));
Run Code Online (Sandbox Code Playgroud)

我知道我可能得到这个,因为我使用了一个Charset不包含文本文件中的一些字符,其中一些包括其他语言的字符.但我想包括那些角色.

我后来在JavaDocs上了解到它Charset是可选的,只用于更有效地读取文件,因此我将代码更改为:

BufferedReader reader = Files.newBufferedReader(file);
Run Code Online (Sandbox Code Playgroud)

但有些文件仍然存在MalformedInputException.我不知道为什么.

我想知道是否有一个包罗万象的Charset内容可以让我阅读包含许多不同类型字符的文本文件

谢谢.

Daw*_*ica 60

您可能希望获得支持的编码列表.对于每个文件,依次尝试每个编码,可能以UTF-8开头.每次捕获时MalformedInputException,请尝试下一个编码.

  • 我试过`ISO-8859-1`,效果很好.我认为这是欧洲人物,这很好.我仍然不知道为什么`UTF-16`不起作用. (31认同)
  • 如果你有Notepad++,你可以尝试打开文本文件,它会告诉你菜单中文件的编码。如果您始终从同一源获取文件,则可以相应地调整代码。 (2认同)

小智 26

从Files.newBufferedReader创建BufferedReader

Files.newBufferedReader(Paths.get("a.txt"), StandardCharsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)

运行应用程序时,它可能会抛出以下异常:

java.nio.charset.MalformedInputException: Input length = 1
Run Code Online (Sandbox Code Playgroud)

new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"),"utf-8"));
Run Code Online (Sandbox Code Playgroud)

效果很好.

不同的是,前者使用CharsetDecoder默认动作.

格式错误输入和不可映射字符错误的默认操作是报告它们.

而后者使用REPLACE动作.

cs.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE)
Run Code Online (Sandbox Code Playgroud)


Tim*_*per 19

ISO-8859-1是一个包罗万象的字符集,在某种意义上它保证不会抛出MalformedInputException.因此,即使您的输入不在此charset中,它也适用于调试.所以:-

req.setCharacterEncoding("ISO-8859-1");
Run Code Online (Sandbox Code Playgroud)

我的输入中有一些双右引号/双引号字符,US-ASCII和UTF-8都在它们上引发了MalformedInputException,但ISO-8859-1工作正常.


Tom*_*Tom 7

我也遇到了这个带有错误消息的异常,

java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(Unknown Source)
at sun.nio.cs.StreamEncoder.implWrite(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at java.io.OutputStreamWriter.write(Unknown Source)
at java.io.BufferedWriter.flushBuffer(Unknown Source)
at java.io.BufferedWriter.write(Unknown Source)
at java.io.Writer.write(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

并发现尝试使用时出现了一些奇怪的错误

BufferedWriter writer = Files.newBufferedWriter(Paths.get(filePath));
Run Code Online (Sandbox Code Playgroud)

编写从类中的泛型类型转换的字符串“orazg 54”。

//key is of generic type <Key extends Comparable<Key>>
writer.write(item.getKey() + "\t" + item.getValue() + "\n");
Run Code Online (Sandbox Code Playgroud)

此字符串的长度为 9,包含具有以下代码点的字符:

111 114 97 122 103 9 53 52 10

但是,如果将类中的 BufferedWriter 替换为:

FileOutputStream outputStream = new FileOutputStream(filePath);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
Run Code Online (Sandbox Code Playgroud)

它可以毫无例外地成功写入此字符串。此外,如果我从字符中编写相同的 String create ,它仍然可以正常工作。

String string = new String(new char[] {111, 114, 97, 122, 103, 9, 53, 52, 10});
BufferedWriter writer = Files.newBufferedWriter(Paths.get("a.txt"));
writer.write(string);
writer.close();
Run Code Online (Sandbox Code Playgroud)

以前我在使用第一个 BufferedWriter 写入任何字符串时从未遇到任何异常。从 java.nio.file.Files.newBufferedWriter(path, options) 创建的 BufferedWriter 发生了一个奇怪的错误


Eng*_*321 5

我编写了以下内容来根据可用字符集将结果列表打印到标准输出。请注意,它还会告诉您从基于 0 的行号开始哪一行失败,以便您在排除导致问题的字符时进行故障排除。

public static void testCharset(String fileName) {
    SortedMap<String, Charset> charsets = Charset.availableCharsets();
    for (String k : charsets.keySet()) {
        int line = 0;
        boolean success = true;
        try (BufferedReader b = Files.newBufferedReader(Paths.get(fileName),charsets.get(k))) {
            while (b.ready()) {
                b.readLine();
                line++;
            }
        } catch (IOException e) {
            success = false;
            System.out.println(k+" failed on line "+line);
        }
        if (success) 
            System.out.println("*************************  Successs "+k);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

试试这个..我有同样的问题,下面的实现对我有用

Reader reader = Files.newBufferedReader(Paths.get(<yourfilewithpath>), StandardCharsets.ISO_8859_1);
Run Code Online (Sandbox Code Playgroud)

然后在任何你想要的地方使用阅读器。

例如:

CsvToBean<anyPojo> csvToBean = null;
    try {
        Reader reader = Files.newBufferedReader(Paths.get(csvFilePath), 
                        StandardCharsets.ISO_8859_1);
        csvToBean = new CsvToBeanBuilder(reader)
                .withType(anyPojo.class)
                .withIgnoreLeadingWhiteSpace(true)
                .withSkipLines(1)
                .build();

    } catch (IOException e) {
        e.printStackTrace();
    }
Run Code Online (Sandbox Code Playgroud)


Sha*_*asi 5

ISO_8859_1 为我工作!我正在阅读带有逗号分隔值的文本文件