Ошибка в java.util.Scanner

1

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 не прерывается? Как я могу заставить его обрабатывать его как обычно?

  • 0
    from java docs docs.oracle.com/javase/7/docs/api/java/util/Scanner.html Разделитель пробелов по умолчанию, используемый сканером, распознается Character.isWhitespace. Метод reset () сбрасывает значение разделителя сканера в разделитель пробелов по умолчанию независимо от того, было ли оно ранее изменено.
  • 0
    Unicode-символ без пробелов, по-видимому, заставляет java.util.Scanner трактовать его как символ пробела или обычный символ. Это вызывает сбой сканера, и он сдается, и сканер говорит, что в файле больше нет строк. Это как если бы символ юникода интерпретировался как «конец файла», и он просто прекращал думать, что все в порядке.
Теги:
unicode
java.util.scanner

2 ответа

3
Лучший ответ

Если вы не скажете об этом иначе, Scanner примет системную кодировку по умолчанию. Я не уверен в других ОС, но в Windows это один из кодировок ISO 8859 по соображениям совместимости.

К счастью, вы можете сказать Scanner что CharSet вы хотите использовать, используя один из двух конструкторов аргументов, подобных этому.

  • 0
    На моем рабочем ПК (windows 7) Charset.defaultCharset() - это UTF-8 , что не работает, как в примере с OP. Если я создаю свой Scanner как new Scanner(f, "ISO-8859-1"); строка с неразрывным пробелом печатается нормально.
0

С помощью 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

Вы должны указать ту же кодировку, которая использовалась для кодирования символов, иначе Сканер проявит неопределенное поведение, если встретится с символом, который он не понимает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню