Javaで、ディレクトリのテキストベースのファイルを読み取る単純なワードカウントプログラムを作成しています。
しかし、私はエラーを取得し続けます:
Java.nio.charset.MalformedInputException: Input length = 1
このコード行から:
BufferedReader reader = Files.newBufferedReader(file,Charset.forName("UTF-8"));
テキストファイルに一部の文字が含まれておらず、一部には他の言語の文字が含まれていたCharset
を使用したため、おそらくこれが得られると思います。しかし、私はそれらのキャラクターを含めたいです。
後で JavaDocs でCharset
はオプションであり、ファイルのより効率的な読み取りにのみ使用されることを知ったため、コードを次のように変更しました。
BufferedReader reader = Files.newBufferedReader(file);
ただし、一部のファイルは依然としてMalformedInputException
をスローします。理由はわかりません。
多くの異なる種類の文字を含むテキストファイルを読み取ることができる包括的なCharset
があるかどうか疑問に思いました?
ありがとう。
おそらく、サポートされているエンコーディングのリストが必要でしょう。各ファイルについて、UTF-8から始めて、各エンコードを順番に試してください。 MalformedInputException
をキャッチするたびに、次のエンコーディングを試してください。
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)
ISO-8859-1は、MalformedInputExceptionをスローしないことが保証されているという意味で、すべてを含む文字セットです。したがって、入力がこの文字セットにない場合でも、デバッグに適しています。そう:-
req.setCharacterEncoding("ISO-8859-1");
入力に二重右引用符/二重左引用符の文字があり、US-ASCIIとUTF-8の両方でMalformedInputExceptionがスローされましたが、ISO-8859-1は機能しました。
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に発生する奇妙なバグです。
これを試してください..私は同じ問題を抱えていたので、実装は私のために働いた
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();
}
利用可能な文字セットに基づいて結果のリストを標準出力に出力するために、以下を書きました。また、どの文字が問題を引き起こしているのかをトラブルシューティングする場合に、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はポーランド語の文字で機能します
問題は、Files.newBufferedReader(Path path)
が次のように実装されていることです。
public static BufferedReader newBufferedReader(Path path) throws IOException {
return newBufferedReader(path, StandardCharsets.UTF_8);
}
したがって、基本的にUTF-8
を指定しても意味がありません。ただし、コードを記述したい場合を除きます。 「より広い」文字セットを試したい場合は、StandardCharsets.UTF_16
を試してみてください。しかし、とにかくすべての可能な文字を確実に取得することはできません。