Разделенная строка Java новой строкой


390

Я пытаюсь разделить текст с JTextAreaпомощью регулярных выражений, чтобы разделить строку, \nоднако, это не работает, и я также пробовал \r\n|\r|nи многие другие комбинации регулярных выражений. Код:

public void insertUpdate(DocumentEvent e) {
    String split[], docStr = null;
    Document textAreaDoc = (Document)e.getDocument();

    try {
        docStr = textAreaDoc.getText(textAreaDoc.getStartPosition().getOffset(), textAreaDoc.getEndPosition().getOffset());
    } catch (BadLocationException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    split = docStr.split("\\n");
}

7
какую ошибку вы получаете? Не говори "не работает", это ничего не значит. Сообщите нам ошибку / результат, который вы получите. Это первый шаг в отладке кода - выясните, что является неправильным результатом, и как ваша программа достигла этого.
Chii

Что вы действительно хотите сделать? - разрыв строки, как они введены в JTextArea? найти, где JTextArea делает переносы строк? - ???
user85421

Ответы:


732

Это должно охватывать вас:

String lines[] = string.split("\\r?\\n");

На самом деле вам нужно беспокоиться только о двух новых строках (UNIX и Windows).


43
Документ JTextArea ДОЛЖЕН использовать только '\ n'; его взгляды полностью игнорируют '\ r'. Но если вы собираетесь искать более одного вида разделителя, вы можете также искать все три: "\ r? \ N | \ r".
Алан Мур

10
Mac 9 использует \ r. OSX 10 использует \ n
Raekye

$ {fn: length (fn: split (data, '\\ r? \\ n'))} не работает в jstl

4
@antak yes, splitпо умолчанию удаляет завершающие пустые строки, если они имеют результат разделения. Чтобы отключить этот механизм, вам нужно использовать перегруженную версию split(regex, limit)с отрицательным пределом вроде text.split("\\r?\\n", -1). Дополнительная информация: Java String split
удаляет

1
Комментарий @stivlo является дезинформацией, и, к сожалению, у него так много откликов. Как отметил @ Raekye, OS X (теперь известная как macOS) использовала \ n в качестве разделителя строк с момента выпуска в 2001 году. Mac OS 9 была выпущена в 1999 году, и я никогда не видел, чтобы Mac OS 9 или ниже использовала машину в производстве. Нет ни одной современной операционной системы, которая использует \ r в качестве разделителя строк. НИКОГДА не пишите код, который ожидает, что \ r будет разделителем строк на Mac, если только a) вы не любите ретро-вычисления, b) не запускаете машину с OS 9 и c) не можете надежно определить, что машина на самом деле является OS 9.
Джеймс Маклафлин

133

String#split​(String regex)Метод использует регулярные выражения (регулярные выражения). Поскольку Java 8 поддерживает регулярные выражения, \Rкоторые представляют (из документации класса Pattern ):

Соответствие переводу строки
\ R Любая последовательность перевода строки Unicode, эквивалентна \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Таким образом, мы можем использовать его для соответствия:

Как вы видите, \r\nон помещается в начало регулярного выражения, что гарантирует, что регулярное выражение будет сначала пытаться сопоставить эту пару , и только в случае неудачного совпадения оно попытается сопоставить разделители строк из одного символа .


Так что, если вы хотите разделить на разделители, используйте split("\\R").

Если вы не хотите удалять из результирующего массива завершающие пустые строки,"" используйте split(regex, limit)с отрицательным limitпараметром вроде split("\\R", -1).

Если вы хотите обработать одну или несколько непрерывных пустых строк как использование одного разделителя split("\\R+").


4
Да, это лучший ответ. К сожалению, этот вопрос был задан на шесть лет раньше для этого ответа.
Дауд ибн Карим

Я закончил тем, что разделился \\R+, чтобы избежать любых символов конца строки, которые не были покрыты \\Rодним.
SeverityOne

128

Если вы не хотите пустых строк:

String.split("[\\r\\n]+")

4
двойная обратная косая черта не нужна, см. раздел «Обратная косая черта, экранирование и цитирование» docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/…
angryITguy


1
Это работало на Mac OSX, когда вышеупомянутый ответ не сделал.
Джон

Это также сработало для меня. Отличное решение. Это сработало в следующих 2 случаях: 1) я проснулся в 3 часа. \ R \ n \ r \ nЯ надеюсь 2) это реальная жизнь \ r \ nso I
logixplayer

2
@tresf Нельзя использовать квантификаторы в квадратных скобках.
CX gamer

49
String.split(System.getProperty("line.separator"));

Это должно быть системно-независимым


42
Это интересная идея, но вы должны позаботиться о том, чтобы текст действительно использовал системный разделитель строк. У меня есть много текстовых файлов в Unix (например, XML), которые используют разделители «Windows», и довольно много в Windows, которые используют разделители Unix.
Maarten Bodewes

Работает даже на
андроиде

7
Файлы, созданные в ОС Windows и переданные в ОС Unix, по-прежнему будут содержать разделители \ r \ n. Я думаю, что лучше быть осторожным и учитывать обоих сепараторов.
bvdb

17
Это очень проблемный подход! Файл может не происходить из системы, в которой выполняется код. Я настоятельно не рекомендую подобные «независимые от системы» проекты, которые на самом деле зависят от конкретной системы, системы времени выполнения.
Мартин

4
@Shervin Это никогда не лучший способ сделать это. Это на самом деле очень плохая практика. Представьте, что какой-то другой программист вызывает System.setProperty («line.separator», «у вас нет смысла»); Ваш код не работает. Это может даже вызываться аналогичным образом зависимостью, о которой вы ничего не знаете.
Мартин

14

Новый метод linesбыл введен в Stringкласс в, который возвращает Stream<String>

Возвращает поток подстрок, извлеченных из этой строки, разделенных разделителями строк.

Распознавателями конца строки являются перевод строки "\ n" (U + 000A), возврат каретки "\ r" (U + 000D) и возврат каретки, за которым сразу следует перевод строки "\ r \ n" (U + 000D U + 000A) ).

Вот несколько примеров:

jshell> "lorem \n ipusm \n sit".lines().forEach(System.out::println)
lorem
 ipusm
 sit

jshell> "lorem \n ipusm \r  sit".lines().forEach(System.out::println)
lorem
 ipusm
  sit

jshell> "lorem \n ipusm \r\n  sit".lines().forEach(System.out::println)
lorem
 ipusm
  sit

Строка # строки ()


12

Вам не нужно удваивать escape-символы в группах символов.

Для всех непустых строк используйте:

String.split("[\r\n]+")

Да, вы делаете. Если им нужно куда-то сбежать, им это нужно везде. Пробельные символы как \rи \nмогут иметь один или два обратных слэша; они работают в любом случае.
Алан Мур

2
Двойная обратная косая черта '\\'в коде становится '\'символом и затем передается в механизм RegEx, поэтому "[\\r\\n]"код становится [\r\n]в памяти, и RegEx будет обрабатывать это. Я не знаю, как именно Java обрабатывает RegEx, но хорошей практикой является передача «чистого» строкового шаблона ASCII в движок RegEx и его обработка, а не передача двоичных символов. "[\r\n]"становится (шестнадцатеричным) 0D0Aв памяти, и один механизм RegEx может принять его, в то время как другой задохнется. Таким образом, суть в том, что даже если Java-
версия RegEx

10

В JDK11в Stringклассе есть lines()метод:

Возвращает поток строк, извлеченных из этой строки, разделенных разделителями строк.

Далее документация продолжает:

Терминатор строки может быть одним из следующих: символ перевода строки "\ n" (U + 000A), символ возврата каретки "\ r" (U + 000D) или возврат каретки, за которым сразу следует перевод строки "\ r \ n "(U + 000D U + 000A). Строка - это либо последовательность из нуля или более символов, за которой следует разделитель строки, либо последовательность из одного или нескольких символов, за которой следует конец строки. Строка не включает в себя терминатор строки.

С этим можно просто сделать:

Stream<String> stream = str.lines();

тогда, если вы хотите массив:

String[] array = str.lines().toArray(String[]::new);

Учитывая, что этот метод возвращает Stream, он открывает множество вариантов для вас, поскольку он позволяет написать краткое и декларативное выражение возможных параллельных операций.


7

Может быть, это будет работать:

Удалите двойную обратную косую черту из параметра метода split:

split = docStr.split("\n");

8
На самом деле, нет. Когда вы пишете регулярное выражение в форме литерала Java String, вы можете использовать "\ n", чтобы передать компилятору регулярного выражения символ перевода строки, или "\\ n", чтобы передать ему escape-последовательность для перевода строки. То же самое касается всех других пробелов, кроме \ v, что не поддерживается в литералах Java.
Алан Мур

3
@Yuval. К сожалению , что это неправильно, это не нужно на всех «побегах обратных косых черты, и со ссылкой на » docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/...
angryITguy

7

Все ответы, приведенные здесь, на самом деле не соответствуют определению Javas новых строк, как, например, в BufferedReader # readline. Java принимает \n, \rи в \r\nкачестве новой строки. Некоторые ответы соответствуют нескольким пустым строкам или искаженным файлам. Например. <sometext>\n\r\n<someothertext>при использовании [\r\n]+приведет к двум строкам.

String lines[] = string.split("(\r\n|\r|\n)", -1);

Напротив, ответ выше имеет следующие свойства:

  • он соответствует определению Javas новой строки, например, например, BufferedReader использует его
  • он не соответствует нескольким новым строкам
  • не удаляет завершающие пустые строки

6

Если по какой-то причине вы не хотите использовать String.split(например, из-за регулярных выражений ) и хотите использовать функциональное программирование на Java 8 или новее:

List<String> lines = new BufferedReader(new StringReader(string))
        .lines()
        .collect(Collectors.toList());

Я знаю, что это может быть излишним решением.
Данило Пьяццалунга

3
Или String[] lines = new BufferedReader(...).lines().toArray(String[]::new);для массива вместо списка. Хорошая особенность этого решения в том, что он BufferedReaderзнает обо всех подобных терминаторах, поэтому он может обрабатывать текст во всех видах форматов. (Большинство решений на основе регулярных выражений, размещенных здесь, в этом отношении не дотягивают.)
Тед Хопп,

2
Это решение устарело после Java 11 и введения метода String.lines ().
Левентов

4

Для сохранения пустых строк от сдавливания используйте:

String lines[] = String.split("\\r?\\n", -1);

3

Приведенный выше код на самом деле не делает ничего видимого - он просто вычисляет, а затем выводит вычисления. Это код, который вы использовали, или просто пример для этого вопроса?

попробуйте сделать textAreaDoc.insertString (int, String, AttributeSet) в конце?


insertUpdate () является методом DocumentListener. Предполагая, что OP использует его правильно, попытка изменить документ из метода слушателя вызовет исключение. Но вы правы: код в этом вопросе на самом деле ничего не делает.
Алан Мур

2

В качестве альтернативы предыдущим ответам, SplitterAPI-интерфейс guava можно использовать, если к результирующим строкам должны применяться другие операции, такие как обрезка или фильтрация пустых строк:

import com.google.common.base.Splitter;

Iterable<String> split = Splitter.onPattern("\r?\n").trimResults().omitEmptyStrings().split(docStr);

Обратите внимание, что результатом является Iterableмассив, а не массив.



1

После неудачных попыток на основе всех приведенных решений. Я заменяю \nспециальным словом, а затем разделяю. Для меня следующие сделали свое дело:

article = "Alice phoned\n bob.";
article = article.replace("\\n", " NEWLINE ");
String sen [] = article.split(" NEWLINE ");

Я не мог повторить пример, приведенный в вопросе. Но, я думаю, эта логика может быть применена.



0
  • попробуйте эту надежду, это было полезно для вас

 String split[], docStr = null;
Document textAreaDoc = (Document)e.getDocument();

try {
    docStr = textAreaDoc.getText(textAreaDoc.getStartPosition().getOffset(), textAreaDoc.getEndPosition().getOffset());
} catch (BadLocationException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

split = docStr.split("\n");

0

Существует три различных соглашения (можно сказать, что это стандарты де-факто ) для установки и отображения переноса строки:

  • carriage return + line feed
  • line feed
  • carriage return

В некоторых текстовых редакторах можно заменить один на другой:

Notepad ++

Самое простое - нормализовать, line feedа затем разделить.

final String[] lines = contents.replace("\r\n", "\n")
                               .replace("\r", "\n")
                               .split("\n", -1);

0

В городе появился новый мальчик, поэтому вам не нужно разбираться со всеми вышеперечисленными сложностями. Начиная с JDK 11 , просто нужно писать как одну строку кода, он разделит строки и вернет вам Stream of String.

public class MyClass {
public static void main(String args[]) {
   Stream<String> lines="foo \n bar \n baz".lines();
   //Do whatever you want to do with lines
}}

Некоторые ссылки. https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#lines () https://www.azul.com/90-new -Особенности-и-АПИС-в-JDK-11 /

Я надеюсь, что это будет полезно для кого-то. Удачного кодирования.


-1
package in.javadomain;

public class JavaSplit {

    public static void main(String[] args) {
        String input = "chennai\nvellore\ncoimbatore\nbangalore\narcot";
        System.out.println("Before split:\n");
        System.out.println(input);

        String[] inputSplitNewLine = input.split("\\n");
        System.out.println("\n After split:\n");
        for(int i=0; i<inputSplitNewLine.length; i++){
            System.out.println(inputSplitNewLine[i]);
        }
    }

}

Это бледнеет по сравнению с другими ответами, которые более понятны и менее трудоемки. Не могли бы вы объяснить, что вы делаете с этим кодом, и почему он может дать подходящий ответ?
Макото

2
Это не имеет ничего общего с разбиением файла на строки. Попробуйте удалить свой ответ.
Мартин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.