java.util.Scanner не может обрабатывать неразрывные пробелы в содержимом файла, который причудливо.
Вот входной текст, поместите его в файл asdf.txt
:
lines lines lines
asdf jkl
lines lines lines
Между asdf
и jkl
- нераспространяющееся пространство. В частности:
echo "asdf jkl" | od -c
0000000 a s d f 302 240 j k l \n
0000012
Вы можете скопировать/вставить его здесь и посмотреть: http://www.fontspace.com/unicode/analyzer/
Оскорбительный характер также известен как: 302 240
, U+00A0
,
,  
,  
, %C2%A0
Код:
import java.util.*;
import java.io.*;
public class Main{
public static void main(String args[]){
Scanner r = null;
try{
File f = new File("/home2/ericlesc/testfile/asdf.txt");
r = new Scanner(f);
while(r.hasNextLine()){
String line = r.nextLine();
System.out.println("line is: " + line);
}
System.out.println("done");
}
catch(Exception e){
e.printStackTrace();
}
}
}
java.util.Scanner pukes на этом контенте. Удивительно, но он НЕ выбрасывает исключение, говоря "не может обработать этот символ". Он не останавливается на оскорбительной линии, сканер разыгрывает примерно 30 символов перед оскорбительным персонажем.
Может быть, есть известная документация о том, как я могу использовать java.util.Scanner для чтения в нераспространяющемся пространстве без puking?
Почему процесс java.util.Scanner не прерывается? Как я могу заставить его обрабатывать его как обычно?
Если вы не скажете об этом иначе, Scanner примет системную кодировку по умолчанию. Я не уверен в других ОС, но в Windows это один из кодировок ISO 8859 по соображениям совместимости.
К счастью, вы можете сказать Scanner
что CharSet
вы хотите использовать, используя один из двух конструкторов аргументов, подобных этому.
Charset.defaultCharset()
- это UTF-8
, что не работает, как в примере с OP. Если я создаю свой Scanner
как new Scanner(f, "ISO-8859-1");
строка с неразрывным пробелом печатается нормально.
С помощью powerlord я смог использовать этот код для получения желаемого результата:
import java.util.*;
import java.io.*;
public class Main{
public static void main(String args[]){
Scanner r = null;
try{
File f = new File("/home2/ericlesc/testfile/asdf.txt");
r = new Scanner(f, "ISO-8859-1");
while(r.hasNextLine()){
String line = r.nextLine();
System.out.println("line is: " + line);
}
System.out.println("done");
}
catch(Exception e){
e.printStackTrace();
}
}
}
Печать программы:
javac Main.java && java Main
line is: lines lines lines
line is: asdf jkl
line is: lines lines lines
Вы должны указать ту же кодировку, которая использовалась для кодирования символов, иначе Сканер проявит неопределенное поведение, если встретится с символом, который он не понимает.