Как заставить сканер правильно читать экранирующие символы?

Я читаю из файла, который читает что-то вроде всего в одной строке:

Hello World!\nI've been trying to get this to work for a while now.\nFrustrating.\n

И мой сканер считывает это из файла и помещает в строку:

Scanner input = new Scanner(new File(fileName));
String str = input.nextLine();
System.out.print(str);

Теперь я хочу, чтобы результат был следующим:

Hello World!
I've been trying to get this work for a while now.
Frustrating.

Но вместо этого я получаю то же самое, что и ввод. То есть каждый \n включается в вывод, и все находится в одной строке, а не в отдельных строках.

Я думал, что Scanner сможет правильно прочитать escape-символ, но вместо этого он копирует его в строку, как \\n.


person sangh    schedule 31.05.2012    source источник


Ответы (3)


Если написано \n, это файл, который вы не можете использовать nextLine(), потому что нет \n (конец строки), а вместо этого есть \\n (два символа).

Вместо этого попробуйте использовать разделитель:

    Scanner sc = new Scanner(new File("/home/alain/Bureau/ttt.txt"));
    sc.useDelimiter("\\\\n");
    while(sc.hasNext()){
        System.out.println(sc.next());
    }

Выход :

Привет, мир!

Я пытался заставить это работать какое-то время.

Раздражающий.

РЕДАКТИРОВАТЬ:

Если вы хотите прочитать файл и заменить \n в тексте фактическим EOL. Вы можете просто использовать:

Scanner sc = new Scanner(new File("/home/alain/Bureau/ttt.txt"));

//loop over real EOL
while(sc.hasNextLine()){

     //Replace the `\n` in the line with real EOL.
     System.out.println(sc.nextLine().replace("\\n", System.getProperty("line.separator")));
}
person alain.janinm    schedule 31.05.2012

Нет, Scanner не сделает этого за вас. Вам придется сделать перевод самостоятельно.

(Обратите внимание, что если вы используете что-то вроде sc.useDelimiter("\\\\n"), как предлагали другие, вы нарушаете функциональность обычного метода next(), а nextLine() может работать не так, как ожидалось.)

Вот набросок того, как я это решу:

Сдача

Scanner input = new Scanner(new FileReader(fileName));

to

Scanner input = new Scanner(new JavaEscapeReader(new FileReader(fileName)));
                            ^^^^^^^^^^^^^^^^^^^^^                        ^

где JavaEscapeReader будет расширять FilterReader следующим образом:

class JavaEscapeReader extends FilterReader {

    JavaEscapeReader(Reader in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        int ch = super.read();
        switch (ch) {
        case '\\':
            switch (super.read()) {
            case '\\': return '\\';
            case 'n': return '\n';
            case 't': return '\t';
            case 'f': return '\f';
            // ...
            default:
                throw new IOException("Invalid char sequence.");
            }
        default:
            return ch;
        }
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        int i = 0, ch;
        while (i < len && -1 != (ch = read()))
            cbuf[i++] = (char) ch;
        return i == 0 ? -1 : i;
    }
}

Дан входной файл с содержимым

Line1\nLine2
Line3\nLine3

программа

Scanner sc = new Scanner(new JavaEscapeReader(new FileReader("filename.txt")));
while (sc.hasNextLine())
    System.out.println(sc.nextLine());

отпечатки

Line1
Line2
Line3
Line4

Другой вариант — использовать StringEscapeUtils.unescapeJava и постобработайте прочитанные строки.

person aioobe    schedule 31.05.2012

Вы можете использовать Scanner.useDelimiter, чтобы установить собственный разделитель. В вашем случае использование двойных кавычек \\n:

s.useDelimiter("\\\\n");

Пример:

Scanner s = new Scanner("Hello World!\\nI've been trying to get this to " +
                        "work for a while now.\\nFrustrating.\\n");
s.useDelimiter("\\\\n");

System.out.println(s.next());
System.out.println(s.next());
System.out.println(s.next());

Выходы:

Hello World!
I've been trying to get this to work for a while now.
Frustrating.
person dacwe    schedule 31.05.2012
comment
Допустим, мне нужен ввод, хранящийся в строке, для удобного использования в будущем. Есть ли способ правильно сохранить escape-символы, просто перейдя прямо в System.out? - person sangh; 31.05.2012