Podziel ciąg Java według nowej linii


388

Próbuję podzielić tekst za JTextAreapomocą wyrażenia regularnego, aby podzielić ciąg według. \nJednak to nie działa, a także próbowałem przez \r\n|\r|ni wiele innych kombinacji wyrażeń regularnych. Kod:

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
jaki masz błąd? Nie mów „nie działa”, to nic nie znaczy. Poinformuj nas o otrzymanym błędzie / wyniku. To pierwszy krok do debugowania kodu - dowiedz się, jaki jest zły wynik i jak twój program do tego doszedł.
Chii

Co naprawdę chcesz zrobić? - przerywać linie, gdy są wprowadzane do JTextArea? - ustalenie, gdzie JTextArea wykonuje zawijanie linii? - ???
user85421,

Odpowiedzi:


731

Powinno to obejmować:

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

Tak naprawdę są tylko dwie nowe linie (UNIX i Windows), o które musisz się martwić.


43
Dokument JTextArea POWINIEN używać tylko „\ n”; jego widoki całkowicie ignorują „\ r”. Ale jeśli będziesz szukał więcej niż jednego rodzaju separatora, równie dobrze możesz poszukać wszystkich trzech: „\ r? \ N | \ r”.
Alan Moore

10
Mac 9 używa \ r. OSX 10 używa \ n
Raekye

$ {fn: length (fn: split (data, '\\ r? \\ n'))} nie działa w jstl

4
@antak tak, splitdomyślnie usuwa końcowe ciągi znaków, jeśli zawierają wynik podziału. Aby wyłączyć ten mechanizm, musisz użyć przeciążonej wersji split(regex, limit)z ujemnym limitem jak text.split("\\r?\\n", -1). Więcej informacji: Podział łańcucha Java usunął puste wartości
Pshemo

1
Komentarz @stivlo jest dezinformacją i szkoda, że ​​ma tak wiele pozytywnych opinii. Jak zauważył @ Raekye, OS X (obecnie znany jako macOS) używał \ n jako separatora linii od czasu wydania w 2001 roku. Mac OS 9 został wydany w 1999 roku i nigdy nie widziałem używanego komputera Mac OS 9 lub nowszego w produkcji. Nie ma jednego nowoczesnego systemu operacyjnego, który używa \ r jako separatora linii. NIGDY nie pisz kodu, który spodziewa się, że \ r będzie separatorem linii na komputerze Mac, chyba że: a) jesteś w trybie retro, b) masz podkręconą maszynę z systemem OS 9, i c) możesz wiarygodnie ustalić, że to komputer z systemem OS 9.
James McLaughlin

132

String#split​(String regex)Metoda używa wyrażeń regularnych (wyrażeń regularnych). Ponieważ regex Java 8 obsługuje to, \Rco reprezentuje (z dokumentacji klasy Pattern ):

Dopasowywanie podziału linii
\ R Każda sekwencja podziału linii kodu Unicode jest równoważna \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Możemy więc użyć go do dopasowania:

Jak widać, \r\numieszczany jest na początku wyrażenia regularnego, co zapewnia, że ​​wyrażenie regularne spróbuje najpierw dopasować tę parę , i tylko jeśli to dopasowanie się nie powiedzie, spróbuje dopasować separatory pojedynczych znaków .


Więc jeśli chcesz podzielić separator liniowy, użyj split("\\R").

Jeśli nie chcesz usuwać z wynikowej tablicy pustych ciągów znaków,"" użyj parametru split(regex, limit)ujemnego limit, takiego jak split("\\R", -1).

Jeśli chcesz traktować jedną lub więcej kontynuuj puste linie jako pojedynczy separator split("\\R+").


4
Tak, to najlepsza odpowiedź. Niestety, pytanie zostało zadane sześć lat za wcześnie na tę odpowiedź.
Dawood ibn Kareem

Skończyło się na podziale \\R+, aby uniknąć znaków końca linii, które nie byłyby objęte \\Rosobno.
SeverityOne

128

Jeśli nie chcesz pustych linii:

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

4
podwójne ukośniki odwrotne są niepotrzebne, patrz sekcja „ Ukośniki
odwrotne


1
Działa to w systemie Mac OSX, gdy powyższa odpowiedź nie.
Jan

To również działało dla mnie. Doskonałe rozwiązanie Działa w następujących 2 przypadkach: 1) obudziłem się o 3 godzinie. \ R \ n \ r \ n Mam nadzieję 2) to jest prawdziwe życie \ r \
nso

2
@tresf Nie można używać kwantyfikatorów w nawiasach kwadratowych.
Gracz CX,

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

Powinno to być niezależne od systemu


41
To ciekawy pomysł, ale powinieneś uważać, aby tekst faktycznie używał separatora linii w systemie. Mam wiele, wiele plików tekstowych w systemie Unix (np. XML), które używają separatorów „Windows”, oraz sporo plików w systemie Windows, które używają separatorów Unix.
Maarten Bodewes

Działa nawet na
Androidzie

6
Pliki utworzone w systemie operacyjnym Windows i przesłane do systemu operacyjnego Unix nadal będą zawierać \ r \ n separatory. Myślę, że lepiej jest grać bezpiecznie i wziąć pod uwagę oba rozdzielacze.
bvdb

17
To bardzo problematyczne podejście! Plik nie może pochodzić z systemu, w którym działa kod. Zdecydowanie odradzam tego rodzaju projekty „niezależne od systemu”, które faktycznie zależą od konkretnego systemu, systemu wykonawczego.
Martin

4
@Shervin To nigdy nie jest najlepszy sposób, aby to zrobić. Jest to w rzeczywistości bardzo zła praktyka. Zastanów się nad innym programistą wywołującym System.setProperty („line.separator”, „nie masz sensu”); Twój kod jest uszkodzony. Może być nawet nazwany podobnie przez zależność, o której nie masz wiedzy.
Martin

14

linesDo Stringklasy wprowadzono nową metodę, która zwraca Stream<String>

Zwraca strumień podciągów wyodrębniony z tego ciągu podzielonego przez terminatory linii.

Rozpoznawane terminatory linii to podawanie wiersza „\ n” (U + 000A), powrót karetki „\ r” (U + 000D) i powrót karetki, a następnie natychmiast przejście do wiersza „\ r \ n” (U + 000D U + 000A ).

Oto kilka przykładów:

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

Ciąg # linii ()


12

Nie musisz podwójnie uciekać postaci w grupach postaci.

Dla wszystkich niepustych linii użyj:

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

Tak Jeśli potrzebują gdziekolwiek podwójnej ucieczki, potrzebują jej wszędzie. Białe znaki uciekają jak \ri \nmogą mieć jeden lub dwa odwrotne ukośniki; działają tak czy inaczej.
Alan Moore

2
Podwójny ukośnik odwrotny '\\'w kodzie staje się '\'znakiem, a następnie jest przekazywany do silnika RegEx, więc "[\\r\\n]"kod zostaje [\r\n]w pamięci i RegEx to przetworzy. Nie wiem, jak dokładnie Java obsługuje RegEx, ale dobrą praktyką jest przekazywanie „czystego” wzorca łańcucha ASCII do silnika RegEx i pozwalanie mu przetwarzać, zamiast przekazywać znaki binarne. "[\r\n]"staje się (szesnastkowy) 0D0Aw pamięci i jeden silnik RegEx może go zaakceptować, podczas gdy inny będzie się dusić. Więc
sedno

10

W JDK11tej Stringklasie ma lines()metodę:

Zwracanie strumienia linii wyodrębnionych z tego ciągu, oddzielonych terminatorami linii.

Ponadto dokumentacja mówi dalej:

Terminator linii jest jednym z następujących: znak przejścia do wiersza „\ n” (U + 000A), znak powrotu karetki „\ r” (U + 000D) lub znak powrotu karetki, po którym następuje natychmiast przejście do wiersza „\ r \ n "(U + 000D U + 000A). Linia jest albo sekwencją zerową lub większą liczbą znaków, po której następuje terminator linii, albo sekwencją jednego lub więcej znaków, po której następuje koniec łańcucha. Linia nie zawiera terminatora linii.

Dzięki temu można po prostu:

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

to jeśli chcesz tablicę:

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

Biorąc pod uwagę, że ta metoda zwraca strumień, pojawia się wiele opcji, ponieważ umożliwia napisanie zwięzłego i deklaratywnego wyrażenia możliwych równoległych operacji.


7

Może to zadziała:

Usuń podwójne ukośniki odwrotne z parametru metody podziału:

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

8
Nie całkiem. Kiedy piszesz wyrażenie regularne w postaci literału Java String, możesz użyć „\ n”, aby przekazać kompilatorowi regularnemu symbol kanału liniowego, lub „\\ n”, aby przekazać sekwencję zmiany znaczenia dla kanału liniowego. To samo dotyczy wszystkich innych znaków białych znaków oprócz \ v, który nie jest obsługiwany w literałach Java.
Alan Moore,

3
@Yuval. Przykro nam, że jest to niepoprawne, nie potrzebujesz go wcale „Odwrotne ukośniki, ucieczki i cytowanie” docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/…
angryITguy

7

Wszystkie podane tutaj odpowiedzi faktycznie nie są zgodne z definicją nowych wierszy w języku JavaScript, jak podano np. W BufferedReader # readline. Java jest przyjęcie \n, \ra \r\njako nowej linii. Niektóre odpowiedzi pasują do wielu pustych linii lub zniekształconych plików. Na przykład. <sometext>\n\r\n<someothertext>przy użyciu [\r\n]+spowoduje dwa wiersze.

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

Natomiast powyższa odpowiedź ma następujące właściwości:

  • jest zgodny z definicją nowej linii w języku JavaScript, np. używa go BufferedReader
  • nie pasuje do wielu nowych linii
  • nie usuwa końcowych pustych linii

6

Jeśli z jakiegoś powodu nie chcesz używać String.split(na przykład z powodu wyrażeń regularnych ) i chcesz używać programowania funkcjonalnego w Javie 8 lub nowszej:

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

Wiem, że to może być rozwiązanie przesadne.
Danilo Piazzalunga

3
Lub String[] lines = new BufferedReader(...).lines().toArray(String[]::new);dla tablicy zamiast listy. Zaletą tego rozwiązania jest to, że BufferedReaderwie o wszelkiego rodzaju podobnych terminatorach, dzięki czemu może obsługiwać tekst we wszystkich formatach. (Większość opublikowanych tutaj rozwiązań opartych na wyrażeniach regularnych jest pod tym względem niewystarczająca.)
Ted Hopp,

2
To rozwiązanie jest przestarzałe od czasu Java 11 i wprowadzenia metody String.lines ().
leventov

4

Aby uchronić puste linie przed zgnieceniem, użyj:

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

3

Powyższy kod nie robi nic widocznego - po prostu calcualtes, a następnie zrzuca obliczenia. Czy to kod, którego użyłeś, czy tylko przykład tego pytania?

spróbować zrobić textAreaDoc.insertString (int, String, AttributeSet) na końcu?


insertUpdate () to metoda DocumentListener. Zakładając, że OP używa go poprawnie, próba zmodyfikowania dokumentu z poziomu metody detektora wygeneruje wyjątek. Ale masz rację: kod w tym pytaniu w rzeczywistości nic nie robi.
Alan Moore,

2

Alternatywnie do poprzednich odpowiedzi Splittermożna użyć interfejsu API guava, jeśli do linii wynikowych mają zostać zastosowane inne operacje, takie jak przycinanie linii lub filtrowanie pustych linii:

import com.google.common.base.Splitter;

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

Zauważ, że wynikiem jest Iterabletablica, a nie tablica.



1

Po nieudanych próbach na podstawie wszystkich podanych rozwiązań. Wymieniam\n specjalne słowo, a następnie dzielę. Dla mnie następowała sztuczka:

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

Nie mogłem powtórzyć przykładu podanego w pytaniu. Ale myślę, że tę logikę można zastosować.



0
  • wypróbuj tę nadzieję, że była dla Ciebie pomocna

 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

Istnieją trzy różne konwencje (można powiedzieć, że są to de facto standardy) do ustawiania i wyświetlania podziału linii:

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

W niektórych edytorach tekstu można wymienić jeden na drugi:

Notepad ++

Najprostszą rzeczą jest normalizacja, line feeda następnie podział.

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

0

W mieście jest nowy chłopiec, więc nie musisz zajmować się wszystkimi powyższymi złożonościami. Począwszy od JDK 11 , wystarczy pisać jako pojedynczy wiersz kodu, dzieli linie i zwraca Strumień ciągu.

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
}}

Niektóre referencje. 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 /

Mam nadzieję, że to będzie komuś pomocne. Szczęśliwego kodowania.


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

}

To blednie w porównaniu z innymi odpowiedziami, które są bardziej objaśniające i mniej obciążają kod. Czy możesz wyjaśnić, co osiągasz dzięki temu kodowi i dlaczego byłby to odpowiednia odpowiedź?
Makoto

2
Nie ma to nic wspólnego z dzieleniem pliku na linie. Rozważ usunięcie swojej odpowiedzi.
Martin
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.