У меня возникла проблема с получением java.util.Scanner для чтения текстового файла, который я сохранил в "Блокноте", хотя он отлично работает с другими. В основном, когда он пытается прочитать файл проблемы, он появляется полностью с пустыми руками - hasNextLine() является ложным, буфер пуст и т.д. Я сузил его до того, что он даже не прочитает первую строку, если является фигурной цитатой в любом месте файла. Никакие исключения не выбрасываются. Обратите внимание, что 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 работает независимо?
EDIT:
Ссылки/комментарии ниже действительно помогли мне в правильном направлении! Кажется, я понял.
Прежде всего, в "Блокноте":
- "ANSI" - CP1252
- "Юникод" - это UTF-16LE
- "UTF-8" ... ну, UTF-8
В шестнадцатеричном виде фигурный апостроф представлен как:
- CP1252: 92
- UTF-16LE: 1920
- UTF-8: E2 80 99
Используемая по умолчанию кодировка Java в моей системе, в соответствии с Charset.defaultCharset(), является UTF-8. Поэтому, когда я сохранил файл в UTF-8, сканер знал, чего ожидать. Однако, когда я сохранил файл в CP1252, он задохнулся, как только он ударил "92", потому что это не допустимый способ представления символа в этой кодировке. Он отлично работает, если в файле нет таких градиентов - шестерка для "hello world" оказывается одинаковой как в CP1252, так и в UTF-8 и не вызывает проблем.
UTF-8 не работает с файлом UTF-16, потому что он не знает, что делать с отметкой байтового порядка ( "FFFE" ), независимо от того, какие символы находятся в файле.
С другой стороны, когда я устанавливаю сканер на CP1252 или ISO-8859-1, он гораздо более терпим. Он не обязательно правильно интерпретирует персонажей, заметьте, но нет ничего, что помешало бы ему распознавать строки в файле и зацикливаться.
Насколько у Сканера есть проблема, но FileReader/BufferedReader этого не делает, я собираюсь угадать, что это потому, что сканеру нужно токенизировать файл, т.е. интерпретировать символы, чтобы он мог идентифицировать пробелы и другие шаблоны, поэтому он задыхается, когда есть что-то неузнаваемое. Читателю это не нужно. Все, что нужно идентифицировать, это разрывы строк.