проблема
Вы должны НЕ предполагать, что произвольный входной текстовый файл использует "правильный" специфичный для платформы разделитель newline . Это кажется источником вашей проблемы; это не имеет ничего общего с регулярным выражением.
Для иллюстрации на платформе Windows System.getProperty("line.separator")
равно "\r\n"
(CR + LF). Однако, когда вы запускаете свой Java-код на этой платформе, вам, вполне возможно, придется иметь дело с входным файлом, разделителем строк которого является просто "\n"
(LF). Возможно, этот файл изначально был создан на платформе Unix, а затем передан в бинарном (а не текстовом) режиме в Windows. Может быть много сценариев, в которых вы можете столкнуться с такими ситуациями, когда вы должны проанализировать текстовый файл как ввод, который не использует разделитель новой строки текущей платформы.
(Кстати, когда текстовый файл Windows переносится в Unix в двоичном режиме, многие редакторы отображают ^M
, что смущает некоторых людей, которые не понимают, что происходит).
Когда вы производите текстовый файл в качестве вывода, вам, вероятно, следует предпочесть платформенный разделитель новой строки, но когда вы используете текстовый файл в качестве ввода, это, вероятно, Можно с уверенностью предположить, что он правильно использует разделитель новой строки для конкретной платформы.
Решение
Один из способов решения проблемы - использовать, например, java.util.Scanner
. Он имеет метод nextLine()
, который может возвращать следующую строку (если она существует), корректно обрабатывая любые несоответствия между разделителем новой строки платформы и входным текстовым файлом.
Вы также можете комбинировать 2 Scanner
, один для сканирования файла строка за строкой, а другой для сканирования токенов каждой строки. Вот простой пример использования, который разбивает каждую строку на List<String>
. Таким образом, весь файл становится List<List<String>>
.
Это, вероятно, лучший подход, чем чтение всего файла в один огромный String
, а затем split
в строки (которые затем split
в части).
String text
= "row1\tblah\tblah\tblah\n"
+ "row2\t1\t2\t3\t4\r\n"
+ "row3\tA\tB\tC\r"
+ "row4";
System.out.println(text);
// row1 blah blah blah
// row2 1 2 3 4
// row3 A B C
// row4
List<List<String>> input = new ArrayList<List<String>>();
Scanner sc = new Scanner(text);
while (sc.hasNextLine()) {
Scanner lineSc = new Scanner(sc.nextLine()).useDelimiter("\t");
List<String> line = new ArrayList<String>();
while (lineSc.hasNext()) {
line.add(lineSc.next());
}
input.add(line);
}
System.out.println(input);
// [[row1, blah, blah, blah], [row2, 1, 2, 3, 4], [row3, A, B, C], [row4]]
Смотри также
- Effective Java 2nd Edition, Item 25: Предпочитать списки массивам
Смежные вопросы