Java не может прочитать строку из файла - PullRequest
0 голосов
/ 01 октября 2018

Я читаю файл со следующим фрагментом кода:

 Scanner in = new Scanner(new File(fileName));
    while (in.hasNextLine()) {
        String[] line = in.nextLine().trim().split("[ \t]");
       .
       .
       .
    }

Когда я открываю файл с помощью vim, некоторые строки начинаются со следующего специального символа:

enter image description here

, но Java-код не может прочитать эти строки.Когда он достигает этих строк, он думает, что это конец файла, и функция hasNextLine () возвращает false !!

EDIT: это шестнадцатеричный дамп упомянутой (проблемной) строки:

0000000: e280 9c20 302e 3230 3133 3220 302e 3231 ... 0,20132 0,21 0000010: 3431 392d 302e 3034 0a 419-0,04.

1 Ответ

0 голосов
/ 02 октября 2018

@ VGR понял все правильно.

tl; dr: Use Scanner in = new Scanner(new File(fileName), "ISO-8859-1");

Похоже, что происходит:

  • Ваш файл не являетсядопустимый UTF-8 из-за этого одиночного символа 0x9C.
  • Сканер считывает файл как UTF-8, поскольку это системное значение по умолчанию
  • Базовые библиотеки выдают MalformedInputException
  • Сканер ловит и скрывает его (многозначное, но ошибочное дизайнерское решение)
  • Он начинает сообщать, что у него больше нет строк
  • Вы не узнаете, что все пошло не так, если вы на самом делеспросите сканер

Вот MCVE:

import java.io.*;
import java.util.*;

class Test {
  public static void main(String[] args) throws Exception {
    Scanner in = new Scanner(new File(args[0]), args[1]);
    while (in.hasNextLine()) {
      String line = in.nextLine();
      System.out.println("Line: " + line);
    }
    System.out.println("Exception if any: " + in.ioException());
  }
}

Вот пример обычного вызова:

$ printf 'Hello\nWorld\n' > myfile && java Test myfile UTF-8
Line: Hello
Line: World
Exception if any: null

Вот что вы видите (кромечто вы не получите и покажете скрытое исключение).Обратите внимание, в частности, на то, что строки не отображаются:

$ printf 'Hello\nWorld \234\n' > myfile && java Test myfile UTF-8
Exception if any: java.nio.charset.MalformedInputException: Input length = 1

И здесь, когда декодируется как ISO-8859-1, декодирование, в котором все последовательности байтов действительны (даже если 0x9C не имеет назначенного символа и поэтомуне отображается в терминале):

$ printf 'Hello\nWorld \234\n' > myfile && java Test myfile ISO-8859-1
Line: Hello
Line: World
Exception if any: null

Если вас интересуют только данные ASCII и у вас нет строк UTF-8, вы можете просто попросить сканер использовать ISO-8859-1передав его в качестве второго параметра конструктору Scanner:

Scanner in = new Scanner(new File(fileName), "ISO-8859-1");
...