web-dev-qa-db-ja.com

「Java.nio.charset.MalformedInputException:入力長= 1」を回避するための包括的な文字セット?

Javaで、ディレクトリのテキストベースのファイルを読み取る単純なワードカウントプログラムを作成しています。

しかし、私はエラーを取得し続けます:

Java.nio.charset.MalformedInputException: Input length = 1

このコード行から:

BufferedReader reader = Files.newBufferedReader(file,Charset.forName("UTF-8"));

テキストファイルに一部の文字が含まれておらず、一部には他の言語の文字が含まれていたCharsetを使用したため、おそらくこれが得られると思います。しかし、私はそれらのキャラクターを含めたいです。

後で JavaDocsCharsetはオプションであり、ファイルのより効率的な読み取りにのみ使用されることを知ったため、コードを次のように変更しました。

BufferedReader reader = Files.newBufferedReader(file);

ただし、一部のファイルは依然としてMalformedInputExceptionをスローします。理由はわかりません。

多くの異なる種類の文字を含むテキストファイルを読み取ることができる包括的なCharsetがあるかどうか疑問に思いました

ありがとう。

66
Jonathan Lam

おそらく、サポートされているエンコーディングのリストが必要でしょう。各ファイルについて、UTF-8から始めて、各エンコードを順番に試してください。 MalformedInputExceptionをキャッチするたびに、次のエンコーディングを試してください。

56

Files.newBufferedReaderからBufferedReaderを作成する

Files.newBufferedReader(Paths.get("a.txt"), StandardCharsets.UTF_8);

アプリケーションを実行すると、次の例外がスローされる場合があります。

Java.nio.charset.MalformedInputException: Input length = 1

しかし

new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"),"utf-8"));

うまくいきます。

違いは、前者はCharsetDecoderのデフォルトアクションを使用することです。

不正な形式の入力エラーおよびマップ不可文字エラーのデフォルトのアクションは、reportそれらです。

後者はREPLACEアクションを使用します。

cs.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE)
24
Xin Wang

ISO-8859-1は、MalformedInputExceptionをスローしないことが保証されているという意味で、すべてを含む文字セットです。したがって、入力がこの文字セットにない場合でも、デバッグに適しています。そう:-

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

入力に二重右引用符/二重左引用符の文字があり、US-ASCIIとUTF-8の両方でMalformedInputExceptionがスローされましたが、ISO-8859-1は機能しました。

19
Tim Cooper

ISO_8859_1私のために働いた!コンマ区切り値のテキストファイルを読んでいた

また、エラーメッセージでこの例外が発生しました。

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

この文字列は、次のコードポイントを持つ文字を含む長さ9です。

111 114 97 122 103 9 53 52 10

ただし、クラスのBufferedWriterが次のように置き換えられた場合:

FileOutputStream outputStream = new FileOutputStream(filePath);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));

この文字列を例外なく正常に書き込むことができます。さらに、文字から作成した同じ文字列を作成しても、引き続き機能します。

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(path、options)から作成されたBufferedWriterに発生する奇妙なバグです。

4
Tom

これを試してください..私は同じ問題を抱えていたので、実装は私のために働いた

Reader reader = Files.newBufferedReader(Paths.get(<yourfilewithpath>), 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();
    }
1
Vin

利用可能な文字セットに基づいて結果のリストを標準出力に出力するために、以下を書きました。また、どの文字が問題を引き起こしているのかをトラブルシューティングする場合に、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);
    }
}

UTF-8はポーランド語の文字で機能します

0
Adriano

問題は、Files.newBufferedReader(Path path)が次のように実装されていることです。

public static BufferedReader newBufferedReader(Path path) throws IOException {
    return newBufferedReader(path, StandardCharsets.UTF_8);
}

したがって、基本的にUTF-8を指定しても意味がありません。ただし、コードを記述したい場合を除きます。 「より広い」文字セットを試したい場合は、StandardCharsets.UTF_16を試してみてください。しかし、とにかくすべての可能な文字を確実に取得することはできません。

0