全包字符集,以避免;java.nio.charset.MalformedInputException:输入长度=1;?

全包字符集,以避免;java.nio.charset.MalformedInputException:输入长度=1;?,java,character-encoding,Java,Character Encoding,我正在用Java创建一个简单的wordcount程序,它可以读取目录中基于文本的文件 然而,我不断地发现错误: java.nio.charset.MalformedInputException: Input length = 1 从这一行代码: BufferedReader reader = Files.newBufferedReader(file,Charset.forName("UTF-8")); 我知道我可能会这样做,因为我使用了字符集,其中没有包含文本文件中的一些字符,其中一些包含其

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

然而,我不断地发现错误:

java.nio.charset.MalformedInputException: Input length = 1
从这一行代码:

BufferedReader reader = Files.newBufferedReader(file,Charset.forName("UTF-8"));
我知道我可能会这样做,因为我使用了
字符集
,其中没有包含文本文件中的一些字符,其中一些包含其他语言的字符。但我想包括这些角色

我后来在会议上了解到,
字符集
是可选的,仅用于更有效地读取文件,因此我将代码更改为:

BufferedReader reader = Files.newBufferedReader(file);
但是有些文件仍然抛出
格式错误的putException
。我不知道为什么

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


谢谢。

您可能想要一个支持的编码列表。对于每个文件,依次尝试每个编码,可能从UTF-8开始。每次捕捉到格式错误的异常时,请尝试下一次编码。

我也遇到了此异常并显示错误消息

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)
并发现在尝试使用时出现了一些奇怪的错误

BufferedWriter writer = Files.newBufferedWriter(Paths.get(filePath));
从类中的泛型类型编写字符串“orazg 54”强制转换

//key is of generic type <Key extends Comparable<Key>>
writer.write(item.getKey() + "\t" + item.getValue() + "\n");
它可以毫无例外地成功写入此字符串。此外,如果我从字符中创建相同的字符串,它仍然可以正常工作

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();

以前,在使用第一个BufferedWriter编写任何字符串时,我从未遇到过任何异常。从java.nio.file.Files.newBufferedWriter(路径,选项)创建的BufferedWriter出现了一个奇怪的错误。

问题是
文件。newBufferedWriter(路径)
的实现如下:

public static BufferedReader newBufferedReader(Path path) throws IOException {
    return newBufferedReader(path, StandardCharsets.UTF_8);
}
因此,基本上没有必要指定
UTF-8
,除非您希望在代码中具有描述性。
如果你想尝试一个“更广泛的”字符集,你可以尝试使用
StandardCharsets.UTF_16
,但你不能100%确定得到所有可能的字符。

你可以尝试类似的方法,或者只是复制并通过下面的部分

boolean exception = true;
Charset charset = Charset.defaultCharset(); //Try the default one first.        
int index = 0;

while(exception) {
    try {
        lines = Files.readAllLines(f.toPath(),charset);
          for (String line: lines) {
              line= line.trim();
              if(line.contains(keyword))
                  values.add(line);
              }           
        //No exception, just returns
        exception = false; 
    } catch (IOException e) {
        exception = true;
        //Try the next charset
        if(index<Charset.availableCharsets().values().size())
            charset = (Charset) Charset.availableCharsets().values().toArray()[index];
        index ++;
    }
}
布尔异常=true;
Charset Charset=Charset.defaultCharset()//先试试默认的。
int指数=0;
while(例外){
试一试{
lines=Files.readAllLines(f.toPath(),字符集);
用于(字符串行:行){
line=line.trim();
if(行包含(关键字))
值。添加(行);
}           
//没有例外,只是返回
异常=假;
}捕获(IOE异常){
异常=真;
//试试下一个字符集

如果(索引从文件创建BufferedReader.newBufferedReader

Files.newBufferedReader(Paths.get("a.txt"), StandardCharsets.UTF_8);
运行应用程序时,可能会引发以下异常:

java.nio.charset.MalformedInputException: Input length = 1
但是

效果很好

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

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

后者使用替换动作

cs.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE)

我编写以下内容是为了根据可用的字符集打印一个结果列表,以标准输出。请注意,它还可以告诉您,如果您正在对导致问题的字符进行故障排除,哪些行与基于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);
    }
}
publicstaticvoidtestcharset(字符串文件名){
SortedMap charsets=Charset.availableCharsets();
for(字符串k:charsets.keySet()){
内线=0;
布尔成功=真;
try(BufferedReader b=Files.newBufferedReader(path.get(文件名)、charset.get(k))){
while(b.ready()){
b、 readLine();
line++;
}
}捕获(IOE异常){
成功=错误;
系统输出打印项次(k+“第行+第行失败”);
}
如果(成功)
System.out.println(“******************************成功”+k);
}
}

ISO-8859-1是一个包罗万象的字符集,从某种意义上说,它保证不会引发格式错误的InputException。因此,即使您的输入不在此字符集中,它也有利于调试。因此:-

req.setCharacterEncoding("ISO-8859-1");

我的输入中有一些右双引号/左双引号字符,US-ASCII和UTF-8都对它们抛出了格式错误的PutException,但ISO-8859-1起了作用。

试试这个。.我也遇到了同样的问题,下面的实现对我有效

Reader reader = Files.newBufferedReader(Paths.get(<yourfilewithpath>), StandardCharsets.ISO_8859_1);
Reader-Reader=Files.newbuffereder(path.get(),StandardCharsets.ISO_8859_1);
然后在任何你想要的地方使用Reader

外汇:

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();
    }
CsvToBean CsvToBean=null;
试一试{
Reader Reader=Files.newbuffereder(path.get(csvFilePath)),
标准字符集(ISO_8859_1);
csvToBean=新的CsvToBeanBuilder(读卡器)
.withType(anyPojo.class)
.带忽略前导空格(true)
.基普林斯(1)
.build();
}捕获(IOE异常){
e、 printStackTrace();
}

ISO-8859\u 1对我有效!我正在阅读带有逗号分隔值的文本文件

UTF-8对波兰字符有效

我尝试了
ISO-8859-1
,效果很好。我认为它适用于欧洲字符,这很好。不过,我仍然不知道
UTF-16
为什么不起作用。如果你有记事本+,你可以尝试打开它文本文件,它将在菜单中告诉您文件的编码。然后,如果您总是从同一个源获取文件,您可以对代码进行修改。@JonathanLam很好,因为如果它是用
ISO-8859-1
编码的,那么它就不是
UTF-16
。这些编码完全不同。文件不能两者都是。@Dawoodsays我相信我是指nt我很惊讶UTF-16没有像ISO-8859-1那样对欧洲字符起到一应俱全的作用。但是感谢您提供的信息(即使六年后):PSure.UTF-16拥有所有欧洲字符
Reader reader = Files.newBufferedReader(Paths.get(<yourfilewithpath>), StandardCharsets.ISO_8859_1);
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();
    }