Подтвердить что ты не робот

Как использовать System.getProperty( "line.separator" ). ToString()?

У меня есть строка с разделителями табуляции (представляющая таблицу), которая передается моему методу. Когда я печатаю его в командной строке, он выглядит как таблица со строками:

http://i.stack.imgur.com/2fAyq.gif

Командное окно правильно буферизовано. Я думаю, что перед или после каждой строки определенно есть новый символ строки.

Моя проблема в том, что я хочу разделить входящую строку на отдельные строки, представляющие строки таблицы. Пока что у меня есть:

private static final String newLine = System.getProperty("line.separator").toString();
private static final String tab = "\t";
private static String[] rows;
...

rows = tabDelimitedTable.split(newLine);    //problem is here

System.out.println();
System.out.println("################### start debug ####################");

System.out.println((tabDelimitedTable.contains(newLine)) ? "True" : "False");

System.out.println("#################### end debug###################");
System.out.println();

выход:

################### start debug ####################
False
#################### end debug###################

Очевидно, что в строке есть что-то, указывающее ОС начать новую строку. Тем не менее, он, очевидно, не содержит символов новой строки.

Запуск последней версии JDK в Windows XP SP3.

Есть идеи?

4b9b3361

Ответ 1

Try

rows = tabDelimitedTable.split("[" + newLine + "]");

Это должно решить проблему регулярное выражение.

Также не этот важный, но возвращаемый тип

System.getProperty("line.separator")

Строка, поэтому нет необходимости вызывать toString().

Ответ 2

Проблема

Вы НЕ должны предполагать, что в произвольном текстовом файле ввода используется "правильный" раздел 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]]

См. также

  • Эффективное Java 2nd Edition, пункт 25: Предпочтительные списки для массивов

Связанные вопросы

Ответ 3

В Windows, line.separator представляет собой комбинацию CR/LF (ссылка здесь).

Метод Java String.split() принимает регулярное выражение. Поэтому я думаю, что здесь есть путаница.

Ответ 4

Попробуйте BufferedReader.readLine() вместо всех этих осложнений. Он распознает все возможные терминаторы линий.

Ответ 5

Я думаю, ваша проблема в том, что String.split() рассматривает свой аргумент как регулярное выражение, а регулярные выражения обрабатывают новые строки специально. Возможно, вам нужно будет явно создать объект регулярного выражения для перехода к split() (есть другая перегрузка) и настроить это регулярное выражение, чтобы разрешить символы новой строки, передав MULTILINE в параме тлях Pattern.compile(). Docs

Ответ 6

Другие респонденты верны, что split() принимает в качестве аргумента регулярное выражение, поэтому сначала вам нужно исправить это. Другая проблема заключается в том, что вы предполагаете, что символы разрыва строки такие же, как и по умолчанию. В зависимости от того, откуда поступают данные и где работает программа, это предположение может быть неверным.

Ответ 7

Попробуйте следующее:

rows = tabDelimitedTable.split("[\\r\\n]+");

Это должно работать независимо от того, какие разделители строк находятся на входе, и будет игнорировать пустые строки.

Ответ 8

Вы также можете использовать writer.writeLine() Это напишет текст и добавит новую строку (используя конец строки платформы)