Розбийте рядок Java за новою лінією


389

Я намагаюся розділити текст за JTextAreaдопомогою регексу, щоб розділити String на. \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 робить обертання рядків? - ???
користувач85421

Відповіді:


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 (дані, '\\ r? \\ n'))} не працює у jstl

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

1
Коментар @stivlo - це дезінформація, і шкода, що в ньому стільки відгуків. Як зазначав @ Raekye, OS X (тепер відомий як macOS) використовував \ n як свій роздільник рядків з моменту виходу в 2001 році. Mac OS 9 був випущений у 1999 році, і я ніколи не бачив, щоб машина з Mac OS 9 або нижче використовувалася у виробництві. Не існує жодної сучасної операційної системи, яка використовує \ r як роздільник рядків. НІКОЛИ не пишіть код, який очікує, що буде роздільником рядків на Mac, якщо: a) ви не працюєте в ретро-обчисленнях; б) увімкнено машину ОС 9, і в) можна надійно визначити, що машина насправді ОС 9.
Джеймс Маклафлін

132

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

Контроль
рядків рядків \ R Будь-яка послідовність рядкових рядків Unicode еквівалентна \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Тож ми можемо використовувати його для відповідності:

Як ви бачите \r\n, розміщується на початку regex, що гарантує, що регулярний випробувач спробує спочатку зв'язати цю пару , і лише якщо ця збіг не вдасться, він спробує відповідати роздільникам рядків з одним символом .


Тож якщо ви хочете розділити на роздільник лінії, використовуйте split("\\R").

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

Якщо ви хочете розглянути одну чи більше продовжуваних порожніх рядків як використання окремого роздільника split("\\R+").


4
Так, це найкраща відповідь. Невдало, що на цю відповідь було задано шість років занадто рано.
Давуд ібн Карім

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

128

Якщо ви не хочете порожніх рядків:

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

4
подвійні нахили від
нахилу


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"));

Це має бути незалежним від системи


41
Це цікава ідея, але ви повинні подбати про те, щоб текст фактично використовував роздільник рядків системи. У мене дуже багато текстових файлів під unix (наприклад, XML), які використовують роздільники "Windows", і досить багато під Windows, які використовують роздільники unix.
Maarten Bodewes

Працює навіть на android
ruX

6
Файли, створені в ОС 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

Не потрібно подвоювати символи втечі в групах символів.

Для всіх не порожніх рядків використовуйте:

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);

Враховуючи цей метод, він повертає Потік до нього для багатьох варіантів, оскільки він дозволяє писати стисле та декларативне вираження можливо паралельних операцій.


7

Можливо, це спрацює:

Видаліть подвійні нахили нахилу від параметра методу розділення:

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

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

3
@Yuval. Вибачте, що це неправильно, вам це зовсім не потрібно " Зворотні
спалахи

7

Усі відповіді, наведені тут, насправді не відповідають визначенню Javas нових рядків, як наведено, наприклад, у BufferedReader # readline Java приймає \n, \rі в \r\nякості нового рядка. Деякі відповіді відповідають декільком порожнім рядкам або неправильним файлам. E..g. <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 ().
leventov

4

Для збереження порожніх рядків від розчарування:

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

3

Наведений вище код насправді нічого не бачить - він просто обчислює, а потім скидає обчислення. Це код, який ви використовували, чи просто приклад для цього питання?

спробуйте зробити textAreaDoc.insertString (int, String, AttributeSet) наприкінці?


insertUpdate () - метод DocumentListener. Якщо припустити, що ОП використовує це правильно, намагання змінити документ із методу слухача призведе до виключення. Але ви праві: код у цьому питанні насправді нічого не робить.
Алан Мур

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 ");

Я не міг повторити приклад, наведений у запитанні. Але, я думаю, цю логіку можна застосувати.


1

Наведені вище відповіді не допомогли мені на Android, завдяки відповіді Pshemo, яка працювала на мене на Android. Я залишу тут кілька відповідей Пшемо :

split("\\\\n")

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

У деяких текстових редакторах можливий обмін одним на інший:

Блокнот ++

Найпростіша річ - це нормалізуватися 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.