メモ帳に保存したテキスト ファイルを java.util.Scanner で読み取る際に問題が発生しましたが、他のファイルでは問題なく動作します。基本的に、問題のファイルを読み込もうとすると、完全に手ぶらで表示されます -- hasNextLine() が false である、バッファが空であるなどです。は、ファイル内の任意の場所で中引用符です。例外はスローされません。同じファイルの BufferedReader には問題がないことに注意してください。
try {
int count = 0;
Scanner scanner = new Scanner(new File("C:/myfile.txt"));
while (scanner.hasNextLine()) {
count++;
scanner.nextLine();
}
scanner.close();
System.out.print(count);
count = 0;
BufferedReader reader = new BufferedReader(new FileReader("C:/myfile.txt"));
while (reader.readLine() != null) {
count++;
}
reader.close();
System.out.print(count);
}
catch(IOException e) {
e.printStackTrace();
}
上記のコードは、単一のカーリー クォーテーションのみを含むファイルを読み取り、"01" を出力します。Googleで検索すると、これを試すようになりました:
Scanner scanner = new Scanner(new File("C:/myfile.txt"), "ISO-8859-1");
これで動作します (つまり、"11" が出力されます)。また、メモ帳を開いて名前を付けて保存すると、下部のデフォルトのエンコーディングが「ANSI」になっていることにも気付きました。これを「UTF-8」に変更してファイルを保存すると、スキャナー (エンコードなし) も機能します。スキャナーに「UTF-8」と指定すると、もちろん UTF-8 で保存した場合にのみ機能しますが、「ISO-8859-1」は「ANSI」として保存しても機能するようです。
したがって、ファイルのエンコーディングに関係があることはわかっていますが、問題は、ファイルのエンコーディングについて何も理解していないことです。「ISO-8859-1」が何を意味するかについての私の知識は非常に曖昧です。ファイルをどのように保存しても、なぜそれが機能するのですか? BufferedReader が関係なく動作するのはなぜですか?
編集:
以下のリンク/コメントは、私を正しい方向に導くのに本当に役立ちました! 私はそれを理解したと思います。
まず、メモ帳で:
- 「ANSI」はCP1252
- 「ユニコード」はUTF-16LE
- 「UTF-8」は…まあ、UTF-8
16 進数では、カーリー アポストロフィは次のように表されます。
- CP1252:92
- UTF-16LE: 1920年
- UTF-8: E2 80 99
Charset.defaultCharset() によると、私のシステムで Java が使用するデフォルトのエンコーディングは UTF-8 です。そのため、ファイルを UTF-8 で保存すると、スキャナーは何を期待すべきかを認識していました。ただし、ファイルを CP1252 で保存すると、その「92」に達すると、そのエンコーディングで文字を表現する有効な方法ではないため、チョークしました。ファイルにそのような文字が含まれていない限り、問題なく動作します。「hello world」の 16 進数は、たまたま CP1252 と UTF-8 の両方で同じであり、たまたま問題が発生することはありません。
UTF-8 は UTF-16 ファイルでは機能しません。これは、ファイル内の文字に関係なく、バイト オーダー マーク ("FFFE") をどう処理するかがわからないためです。
一方、スキャナーを CP1252 または ISO-8859-1 に設定すると、はるかに寛容になります。必ずしも文字を正しく解釈するとは限りませんが、ファイル内の行を認識してループすることを妨げるものは何もありません。
Scanner に問題があるのに FileReader/BufferedReader に問題がない理由については、スキャナがファイルをトークン化する必要があるためだと思います。空白やその他のパターンを識別できるように文字を解釈し、認識できないものがあるとチョークします。読者はその必要はありません。識別する必要があるのは改行だけです。