Разделить строку Java на новую строку

Я пытаюсь разделить текст в 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");
}

person dr.manhattan    schedule 18.01.2009    source источник
comment
в чем заключается ошибка? Не говори, что не работает, это ничего не значит. Сообщите нам полученную ошибку / результат. Это первый шаг в отладке кода - выясните, что является неправильным результатом и как ваша программа к этому пришла.   -  person Chii    schedule 18.01.2009
comment
Что ты действительно хочешь делать? - разрывать строки по мере их ввода в JTextArea? - найти, где JTextArea выполняет перенос строк? - ???   -  person user85421    schedule 29.04.2009


Ответы (19)


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

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

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

person cletus    schedule 18.01.2009
comment
Документ JTextArea ДОЛЖЕН использовать только '\ n'; его представления полностью игнорируют '\ r'. Но если вы собираетесь искать более одного вида разделителей, вы можете также искать все три: \ r? \ N | \ r. - person Alan Moore; 18.01.2009
comment
Mac 9 использует \ r. OSX 10 использует \ n - person Raekye; 06.05.2013
comment
$ {fn: length (fn: split (data, '\\ r? \\ n'))} не работает в jstl - person ; 17.06.2014
comment
Разве это не так: 'String [] lines = String.split (\\ r? \\ n);' ? - person FeinesFabi; 30.10.2014
comment
@antak да, split по умолчанию удаляет завершающие пустые строки, если они являются результатом разделения. Чтобы отключить этот механизм, вам нужно использовать перегруженную версию split(regex, limit) с отрицательным лимитом, например text.split("\\r?\\n", -1). Дополнительная информация: Разделение строки Java удалило пустые значения - person Pshemo; 19.07.2016
comment
String [] lines = string.split (System.getProperty (line.separator)); Это будет работать нормально, пока вы используете строки, сгенерированные в той же ОС / приложении, но если, например, вы запускаете свое Java-приложение под Linux и извлекаете текст из базы данных, который был сохранен как текст Windows, то это может привести к сбою. - person ibai; 25.03.2017
comment
Комментарий @stivlo является дезинформацией, и, к сожалению, он получил так много голосов. Как отметил @ Raekye, OS X (теперь известная как macOS) использовала \ n в качестве разделителя строк с момента ее выпуска в 2001 году. Mac OS 9 была выпущена в 1999 году, и я никогда не видел, чтобы использовалась машина с Mac OS 9 или ниже. в производстве. Ни одна современная операционная система не использует \ r в качестве разделителя строк. НИКОГДА не пишите код, который ожидает, что \ r будет разделителем строк на Mac, за исключением случаев, когда а) вы занимаетесь ретро-вычислениями, б) у вас развернута машина с OS 9 и в) может надежно определить, что машина на самом деле является OS 9. - person James McLaughlin; 04.05.2017
comment
А что это значит? - person Lealo; 09.08.2017
comment
Этот ответ не сработал для меня. Я просто использую элементы String [] = text.split (\ n) или String parts [] = text.split (System.getProperty (line.separator)) в java 8. - person Maykel Llanes Garcia; 05.12.2017
comment
А как насчет юникода ?? Символ следующей строки ('\ u0085'), символ-разделитель строк ('\ u2028') или символ-разделитель абзацев ('\ u2029). - person john ktejik; 11.11.2018
comment
как насчет этого: \ v + (один или несколько вертикальных пробелов) - person Ubeogesh; 14.01.2020

_1 _ метод использует регулярное выражение (регулярные выражения). Поскольку регулярное выражение Java 8 поддерживает \R, который представляет (из документации класса Pattern):

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

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

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


Поэтому, если вы хотите разделить по разделителю строк, используйте split("\\R").

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

Если вы хотите рассматривать одну или несколько продолжающихся пустых строк как один разделитель, используйте split("\\R+").

person Pshemo    schedule 25.06.2015
comment
Да, это лучший ответ. К сожалению, этот вопрос был задан на шесть лет раньше, чем был дан ответ. - person Dawood ibn Kareem; 22.11.2019
comment
В итоге я разделился на \\R+, чтобы избежать любых символов конца строки, которые не были охвачены одним \\R. - person SeverityOne; 21.01.2020
comment
ПРОБЛЕМА JAVA 9 с find matches. Java 9 неправильно позволяет регулярному выражению типа \R\R соответствовать последовательности \r\n, которая представляет одиночную разделительную последовательность. Чтобы решить такую ​​проблему, мы можем написать регулярное выражение типа (?>\u000D\u000A)|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029], которое благодаря атомарной группе (?>\u000D\u000A) предотвратит регулярное выражение, которое уже соответствует \r\n для возврата и пытается сопоставить \r и \n отдельно. - person Pshemo; 29.01.2021

Если вам не нужны пустые строки:

String.split("[\\r\\n]+")
person Gumbo    schedule 18.01.2009
comment
двойные обратные косые черты не нужны, см. раздел Обратные косые черты, экранирование и цитирование docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/ - person angryITguy; 06.12.2011
comment
Это сработало на Mac OSX, хотя приведенный выше ответ не работал. - person John; 02.11.2014
comment
Это тоже сработало для меня. Отличное решение. Это сработало в следующих двух случаях: 1) я проснулся в 3 часа. \ R \ n \ r \ nЯ надеюсь 2) это реальная жизнь \ r \ nтак что я - person logixplayer; 17.07.2015
comment
Это совершенно правильный ответ. Одно небольшое предложение могло бы быть полезным добавить почему он избавляется от пустых строк для людей, которые могут быть не так знакомы с регулярным выражением и как оно себя ведет. Для всех, кому может быть интересно, это потому, что + является жадным оператором и будет соответствовать хотя бы одному, но будет продолжать соответствовать символам '\ r \ n' до тех пор, пока он больше не сможет им соответствовать. См. Здесь: regular-expressions.info/repeat.html#greedy - person greyseal96; 08.04.2016
comment
Почему не [\\r?\\n]+? - person tresf; 21.02.2019
comment
@tresf Вы не можете использовать кванторы в квадратных скобках. - person Breina; 11.12.2019

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

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

person Shervin Asgari    schedule 04.07.2012
comment
Это интересная идея, но вы должны позаботиться о том, чтобы в тексте действительно использовался системный разделитель строк. У меня есть много текстовых файлов под unix (например, XML), которые используют разделители Windows, и довольно много под Windows, которые используют разделители unix. - person Maarten Bodewes; 31.07.2012
comment
Работает даже на android - person ruX; 07.03.2014
comment
Файлы, созданные в ОС Windows и переданные в ОС Unix, по-прежнему будут содержать разделители \ r \ n. Я думаю, что лучше перестраховаться и учитывать обоих разделителей. - person bvdb; 18.07.2014
comment
Это очень проблемный подход! Файл не может происходить из системы, в которой запущен код. Я категорически не одобряю такого рода системно-независимые конструкции, которые фактически зависят от конкретной системы, исполняемой системы. - person Martin; 11.12.2014
comment
@Martin, если у вас есть контроль над развернутой системой, это нормально. Однако, если вы развертываете свой код в облаке и не имеете никакого контроля, то это не лучший способ сделать это. - person Shervin Asgari; 11.12.2014
comment
@Shervin Это никогда не лучший способ. На самом деле это очень плохая практика. Представьте, что какой-то другой программист вызывает System.setProperty (line.separator, вам нет смысла); Ваш код не работает. Это может даже быть вызвано аналогичным образом зависимостью, о которой вы ничего не знаете. - person Martin; 16.12.2014
comment
Это не сработало, поскольку файл был создан в Unix и разделялся в Windows. - person Greg; 06.10.2015
comment
@Martin - какой-то другой программист вызывает System.setProperty (line.separator, вам нет смысла); --- Просто интересно, не нарушит ли такой идиотизм / саботаж многие ожидаемые поведения в библиотеках JDK? - person Rop; 13.07.2017
comment
@Rop Я не могу сразу вспомнить ни одного случая, но могут существовать зависимости от системных свойств, которые фактически нарушают код. Я настоятельно рекомендую настройку без использования системных свойств, когда это возможно. - person Martin; 15.08.2017

Новый метод lines был представлен String классу в java-11, который возвращает 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

Строка #lines ()

person Anton Balaniuc    schedule 28.06.2018

В 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, он предлагает вам множество вариантов, поскольку он позволяет писать краткое и декларативное выражение возможных параллельных операций.

person Ousmane D.    schedule 30.11.2018
comment
это работает для java8 и разбивает строку на поток строк строк: Arrays.stream (str.split (\\ n)) - person MichaelMoser; 04.01.2021

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

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

String.split("[\r\n]+")
person Martin    schedule 17.02.2012
comment
Да, конечно. Если им где-то нужно двойное спасение, им это нужно везде. Экраны пробелов, такие как \r и \n, могут иметь одну или две обратные косые черты; они работают в любом случае. - person Alan Moore; 06.06.2016
comment
Двойная обратная косая черта '\\' в коде становится символом '\' и затем передается механизму RegEx, поэтому "[\\r\\n]" в коде становится [\r\n] в памяти, и RegEx обработает это. Я не знаю, как именно Java обрабатывает RegEx, но рекомендуется передать чистый шаблон строки ASCII механизму RegEx и позволить ему обрабатывать, а не передавать двоичные символы. "[\r\n]" становится (шестнадцатеричным) 0D0A в памяти, и один механизм RegEx может его принять, в то время как другой подавится. Таким образом, суть в том, что даже если Java-версия RegEx не нуждается в них, оставьте двойные косые черты для совместимости. - person nurchi; 15.09.2016

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

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

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

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

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

List<String> lines = new BufferedReader(new StringReader(string))
        .lines()
        .collect(Collectors.toList());
person Danilo Piazzalunga    schedule 07.03.2018
comment
Я знаю, что это может быть излишним решением. - person Danilo Piazzalunga; 07.03.2018
comment
Или String[] lines = new BufferedReader(...).lines().toArray(String[]::new); для массива вместо списка. В этом решении хорошо то, что BufferedReader знает обо всех видах подобных терминаторов, поэтому может обрабатывать текст во всех форматах. (Большинство решений на основе регулярных выражений, размещенных здесь, в этом отношении не справляются.) - person Ted Hopp; 25.04.2018
comment
Это решение устарело с Java 11 и введения метода String.lines (). - person leventov; 04.10.2018

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

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

split = docStr.split("\n");
person Michael    schedule 18.01.2009
comment
Не совсем. Когда вы пишете регулярное выражение в виде строкового литерала Java, вы можете использовать \ n, чтобы передать компилятору регулярных выражений символ перевода строки, или \\ n, чтобы передать ему escape-последовательность для перевода строки. То же самое касается всех остальных экранированных пробелов, кроме \ v, который не поддерживается в литералах Java. - person Alan Moore; 18.01.2009
comment
@ Юваль. Извините, это неверно, вам вообще не нужны обратные косые черты, экранирование и цитирование docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/ - person angryITguy; 06.12.2011

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

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

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

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

person Chii    schedule 18.01.2009
comment
insertUpdate () - это метод DocumentListener. Предполагая, что OP использует его правильно, попытка изменить документ из метода прослушивателя вызовет исключение. Но вы правы: код в этом вопросе на самом деле ничего не делает. - person Alan Moore; 18.01.2009

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

import com.google.common.base.Splitter;

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

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

person Thomas Naskali    schedule 08.06.2017

Приведенные выше ответы не помогли мне на Android, благодаря ответу Pshemo, который работал у меня на Android. Я оставлю здесь часть ответа Pshemo:

split("\\\\n")
person clasher    schedule 19.06.2019

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

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

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

person kravi    schedule 11.04.2017

В городе появился новый мальчик, так что вам не придется сталкиваться со всеми вышеперечисленными сложностями. Начиная с 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-features-and-apis-in-jdk-11/

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

person Red Boy    schedule 23.11.2018

  • Попробуй, надеюсь, это было полезно для тебя

 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");
person Community    schedule 14.09.2017

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

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

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

Блокнот ++

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

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

person    schedule
comment
Это бледнеет по сравнению с другими ответами, которые являются более пояснительными и менее сложными. Не могли бы вы объяснить, чего вы добиваетесь с помощью этого кода, и почему он дает подходящий ответ? - person Makoto; 19.05.2014
comment
Это не имеет ничего общего с разбиением файла на строки. Попробуйте удалить свой ответ. - person Martin; 11.12.2014