Java-String nach neuer Zeile teilen

389

Ich versuche, Text in einem regulären Ausdruck JTextAreazu teilen, um den String nach zu teilen. \nDies funktioniert jedoch nicht und ich habe es auch mit \r\n|\r|nund vielen anderen Kombinationen von regulären Ausdrücken versucht . Code:

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");
}
Dr. Manhattan
quelle
7
Was ist der Fehler, den Sie bekommen? Sagen Sie nicht "funktioniert nicht", das bedeutet nichts. Teilen Sie uns den Fehler / das Ergebnis mit, das Sie erhalten. Dies ist der erste Schritt beim Debuggen von Code. Finden Sie heraus, was das falsche Ergebnis ist und wie Ihr Programm dazu gekommen ist.
Chii
Was möchten Sie wirklich tun? - Zeilen brechen, wenn sie in JTextArea eingegeben werden? - Finden Sie heraus, wo der JTextArea Zeilenumbrüche ausführt? - ???
user85421

Antworten:

732

Dies sollte Sie abdecken:

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

Es gibt wirklich nur zwei Zeilenumbrüche (UNIX und Windows), über die Sie sich Sorgen machen müssen.

Cletus
quelle
43
Ein JTextArea-Dokument sollte nur '\ n' verwenden. In seinen Ansichten wird '\ r' vollständig ignoriert. Wenn Sie jedoch nach mehr als einer Art von Trennzeichen suchen, können Sie auch nach allen drei suchen: "\ r? \ N | \ r".
Alan Moore
10
Mac 9 verwendet \ r. OSX 10 verwendet \ n
Raekye
$ {fn: length (fn: split (Daten, '\\ r? \\ n'))} funktioniert nicht in jstl
4
@antak Ja, splitstandardmäßig werden nachfolgende leere Zeichenfolgen entfernt, wenn sie das Ergebnis einer Teilung sind. Um diesen Mechanismus auszuschalten, müssen Sie eine überladene Version von split(regex, limit)mit einem negativen Grenzwert wie verwenden text.split("\\r?\\n", -1). Weitere Informationen: Java String Split entfernt leere Werte
Pshemo
1
Der Kommentar von @stivlo ist eine Fehlinformation und es ist bedauerlich, dass er so viele positive Stimmen hat. Wie @ Raekye hervorhob, hat OS X (jetzt als macOS bekannt) seit seiner Veröffentlichung im Jahr 2001 \ n als Zeilentrennzeichen verwendet. Mac OS 9 wurde 1999 veröffentlicht, und ich habe noch nie einen Mac OS 9 oder einen niedrigeren Computer gesehen in Produktion. Es gibt kein einziges modernes Betriebssystem, das \ r als Zeilentrennzeichen verwendet. Schreiben Sie NIEMALS Code, der erwartet, dass \ r das Zeilentrennzeichen auf dem Mac ist, es sei denn, a) Sie arbeiten mit Retro-Computing, b) haben einen OS 9-Computer hochgefahren und c) können zuverlässig feststellen, dass es sich bei dem Computer tatsächlich um OS 9 handelt.
James McLaughlin
132

String#split​(String regex)Methode verwendet Regex (reguläre Ausdrücke). Da Java 8 Regex unterstützt, \Rwas darstellt (aus der Dokumentation der Pattern-Klasse ):

Zeilenumbruch-Matcher
\ R Jede Unicode-Zeilenumbruchsequenz entspricht \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Wir können es also verwenden, um Folgendes abzugleichen:

Wie Sie sehen, \r\nwird es am Anfang von Regex platziert, wodurch sichergestellt wird, dass Regex zuerst versucht, mit diesem Paar übereinzustimmen , und nur wenn diese Übereinstimmung fehlschlägt, wird versucht, einzelne Zeichenzeilentrennzeichen abzugleichen.


Wenn Sie also das Zeilentrennzeichen aufteilen möchten, verwenden Sie split("\\R").

Wenn Sie keine leeren Zeichenfolgen aus dem resultierenden Array entfernen möchten,"" verwenden Sie split(regex, limit)mit negativen limitParametern wie split("\\R", -1).

Wenn Sie eine oder mehrere fortgesetzte Leerzeilen als einzelnes Trennzeichen behandeln möchten, verwenden Sie diese split("\\R+").

Pshemo
quelle
4
Ja, das ist die beste Antwort. Leider wurde die Frage sechs Jahre zu früh für diese Antwort gestellt.
Dawood ibn Kareem
Am \\R+Ende habe ich mich getrennt , um Zeilenendezeichen zu vermeiden, die nicht \\Ralleine abgedeckt wurden.
SeverityOne
128

Wenn Sie keine Leerzeilen möchten:

String.split("[\\r\\n]+")
Gumbo
quelle
4
Doppelte Backslashes sind nicht
erforderlich
1
Dies funktionierte unter Mac OS X, wenn die obige Antwort dies nicht tat.
John
Das hat auch bei mir funktioniert. Hervorragende Lösung. Es hat in den folgenden 2 Fällen funktioniert: 1) Ich bin um 3 Uhr aufgewacht. \ R \ n \ r \ nIch hoffe 2) das ist echtes Leben \ r \ nso I
Logixplayer
2
@tresf Sie können keine Quantifizierer in eckigen Klammern verwenden.
CX-Spieler
49
String.split(System.getProperty("line.separator"));

Dies sollte systemunabhängig sein

Shervin Asgari
quelle
41
Es ist eine interessante Idee, aber Sie sollten darauf achten, dass der Text tatsächlich das Zeilentrennzeichen des Systems verwendet. Ich habe viele, viele Textdateien unter Unix (z. B. XML), die "Windows" -Trennzeichen verwenden, und einige unter Windows, die Unix-Trennzeichen verwenden.
Maarten Bodewes
Funktioniert sogar auf Android
RuX
6
Dateien, die unter einem Windows-Betriebssystem erstellt und auf ein Unix-Betriebssystem übertragen wurden, enthalten weiterhin \ r \ n Trennzeichen. Ich denke, es ist besser, auf Nummer sicher zu gehen und beide Trennzeichen zu berücksichtigen.
Bvdb
17
Dies ist ein sehr problematischer Ansatz! Die Datei stammt möglicherweise nicht von dem System, auf dem der Code ausgeführt wird. Ich rate dringend von solchen "systemunabhängigen" Designs ab, die tatsächlich von einem bestimmten System, dem Laufzeitsystem, abhängen.
Martin
4
@Shervin Es ist nie der beste Weg, es zu tun. Es ist in der Tat eine sehr schlechte Praxis. Stellen Sie sich einen anderen Programmierer vor, der System.setProperty aufruft ("line.separator", "Sie haben keinen Sinn"). Ihr Code ist kaputt. Es könnte sogar ähnlich von einer Abhängigkeit aufgerufen werden, über die Sie nichts wissen.
Martin
14

Für linesden StringUnterricht in wurde eine neue Methode eingeführt, die zurückkehrt Stream<String>

Gibt einen Strom von Teilzeichenfolgen zurück, die aus dieser Zeichenfolge extrahiert wurden und durch Zeilenendezeichen unterteilt sind.

Als Endgeräte werden Zeilenvorschub "\ n" (U + 000A), Wagenrücklauf "\ r" (U + 000D) und ein Wagenrücklauf gefolgt von einem Zeilenvorschub "\ r \ n" (U + 000D U + 000A) erkannt ).

Hier einige Beispiele:

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

String # lines ()

Anton Balaniuc
quelle
12

Sie müssen Escapezeichen in Zeichengruppen nicht verdoppeln.

Verwenden Sie für alle nicht leeren Zeilen:

String.split("[\r\n]+")
Martin
quelle
Ja, das tust du. Wenn sie irgendwo doppelt entkommen müssen, brauchen sie es überall. Whitespace entweicht wie \rund \nkann ein oder zwei Backslashes haben; Sie arbeiten so oder so.
Alan Moore
2
Der doppelte Backslash '\\'im Code wird zu einem '\'Zeichen und wird dann an die RegEx-Engine übergeben, sodass der "[\\r\\n]"Code [\r\n]im Speicher gespeichert wird und RegEx dies verarbeitet. Ich weiß nicht, wie genau Java mit RegEx umgeht, aber es empfiehlt sich, ein "reines" ASCII-Zeichenfolgenmuster an die RegEx-Engine zu übergeben und es verarbeiten zu lassen, anstatt Binärzeichen zu übergeben. "[\r\n]"wird (hex) 0D0Aim Speicher und eine RegEx-Engine akzeptiert dies möglicherweise, während eine andere erstickt. Das Fazit ist also, dass selbst wenn Javas Geschmack von RegEx sie nicht benötigt, doppelte Schrägstriche aus Kompatibilitätsgründen
beibehalten werden
10

In JDK11der StringKlasse gibt es eine lines()Methode:

Rückgabe eines aus dieser Zeichenfolge extrahierten Zeilenstroms, getrennt durch Zeilenabschlusszeichen.

In der Dokumentation heißt es weiter:

Ein Zeilenabschluss ist eines der folgenden: ein Zeilenvorschubzeichen "\ n" (U + 000A), ein Wagenrücklaufzeichen "\ r" (U + 000D) oder ein Wagenrücklaufzeichen, unmittelbar gefolgt von einem Zeilenvorschub "\ r \ n "(U + 000D U + 000A). Eine Zeile ist entweder eine Folge von null oder mehr Zeichen, gefolgt von einem Zeilenabschluss, oder eine Folge von einem oder mehreren Zeichen, gefolgt vom Ende der Zeichenfolge. Eine Zeile enthält nicht den Zeilenabschluss.

Damit kann man einfach machen:

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

dann, wenn Sie ein Array wollen:

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

Wenn diese Methode einen Stream zurückgibt, stehen Ihnen viele Optionen zur Verfügung, da Sie einen präzisen und deklarativen Ausdruck möglicherweise paralleler Operationen schreiben können .

Ousmane D.
quelle
7

Vielleicht würde das funktionieren:

Entfernen Sie die doppelten Backslashes aus dem Parameter der Split-Methode:

split = docStr.split("\n");
Michael
quelle
8
Nicht wirklich. Wenn Sie einen Regex in Form eines Java-String-Literal schreiben, können Sie dem Regex-Compiler mit "\ n" ein Zeilenvorschub-Symbol oder mit "\\ n" die Escape-Sequenz für einen Zeilenvorschub übergeben. Das Gleiche gilt für alle anderen Leerzeichen-Escapezeichen mit Ausnahme von \ v, das in Java-Literalen nicht unterstützt wird.
Alan Moore
3
@ Yuval. Entschuldigung, das ist falsch, Sie brauchen es überhaupt nicht "Backslashes,
Escape
7

Alle hier gegebenen Antworten berücksichtigen nicht die Javas-Definition neuer Zeilen, wie sie beispielsweise in BufferedReader # readline angegeben ist. Java akzeptiert \n, \rund \r\nals neue Zeile. Einige der Antworten stimmen mit mehreren Leerzeilen oder fehlerhaften Dateien überein. Z.B. <sometext>\n\r\n<someothertext>bei Verwendung [\r\n]+würde in zwei Zeilen führen.

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

Im Gegensatz dazu hat die obige Antwort die folgenden Eigenschaften:

  • Es entspricht der Javas-Definition einer neuen Zeile, z. B. wenn der BufferedReader sie verwendet
  • Es stimmt nicht mit mehreren neuen Zeilen überein
  • Nachgestellte Leerzeilen werden nicht entfernt
Bis Schäfer
quelle
6

Wenn Sie aus irgendeinem Grund nicht verwenden möchten String.split(z. B. aufgrund regulärer Ausdrücke ) und die funktionale Programmierung unter Java 8 oder höher verwenden möchten:

List<String> lines = new BufferedReader(new StringReader(string))
        .lines()
        .collect(Collectors.toList());
Danilo Piazzalunga
quelle
Ich weiß, dass dies eine Overkill-Lösung sein kann.
Danilo Piazzalunga
3
Oder String[] lines = new BufferedReader(...).lines().toArray(String[]::new);für ein Array anstelle einer Liste. Das Schöne an dieser Lösung ist, BufferedReaderdass sie alle Arten von Terminatoren kennt, sodass sie Text in allen möglichen Formaten verarbeiten kann. (Die meisten der hier veröffentlichten Regex-basierten Lösungen sind in dieser Hinsicht unzureichend.)
Ted Hopp
2
Diese Lösung ist seit Java 11 und der Einführung der String.lines () -Methode veraltet.
Leventov
4

Um zu verhindern, dass leere Zeilen gequetscht werden, verwenden Sie:

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

Der obige Code macht eigentlich nichts Sichtbares - er berechnet nur die Daten und gibt dann die Berechnung aus. Ist es der Code, den Sie verwendet haben, oder nur ein Beispiel für diese Frage?

Versuchen Sie am Ende textAreaDoc.insertString (int, String, AttributeSet) auszuführen.

Chii
quelle
insertUpdate () ist eine DocumentListener-Methode. Angenommen, das OP verwendet es richtig, wird beim Versuch, das Dokument über die Listener-Methode zu ändern, eine Ausnahme generiert. Aber Sie haben Recht: Der Code in dieser Frage macht eigentlich nichts.
Alan Moore
2

Alternativ zu den vorherigen Antworten kann die Guava- SplitterAPI verwendet werden, wenn andere Operationen auf die resultierenden Zeilen angewendet werden sollen, z. B. das Trimmen von Zeilen oder das Filtern leerer Zeilen:

import com.google.common.base.Splitter;

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

Beachten Sie, dass das Ergebnis ein Iterableund kein Array ist.

Thomas Naskali
quelle
1

String lines[] =String.split( System.lineSeparator())

husayt
quelle
1

Nach fehlgeschlagenen Versuchen auf Basis aller gegebenen Lösungen. Ich ersetze \ndurch ein spezielles Wort und teile dann. Für mich hat folgendes den Trick gemacht:

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

Ich konnte das in der Frage angegebene Beispiel nicht wiederholen. Aber ich denke, diese Logik kann angewendet werden.

Kravi
quelle
1

Die obigen Antworten haben mir auf Android nicht geholfen, dank der Pshemo- Antwort, die auf Android für mich funktioniert hat. Ich werde hier einige Antworten von Pshemo hinterlassen :

split("\\\\n")
Clasher
quelle
0
  • Versuchen Sie diese Hoffnung, es war hilfreich für Sie

 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");
Vishal Yadav
quelle
0

Es gibt drei verschiedene Konventionen (man könnte sagen, dass dies de facto Standards sind), um einen Zeilenumbruch festzulegen und anzuzeigen:

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

In einigen Texteditoren ist es möglich, einen gegen den anderen auszutauschen:

Editor ++

Am einfachsten ist es, zu normalisieren line feedund dann zu teilen.

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

Es gibt einen neuen Jungen in der Stadt, so dass Sie sich nicht mit allen oben genannten Komplexitäten auseinandersetzen müssen. Ab JDK 11 müssen Sie nur noch als einzelne Codezeile schreiben. Dadurch werden die Zeilen geteilt und Sie erhalten einen Stream of String zurück.

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

Einige Referenzen. https://docs.oracle.com/de/java/javase/11/docs/api/java.base/java/lang/String.html#lines () https://www.azul.com/90-new -Funktionen-und-Apis-in-JDK-11 /

Ich hoffe, das wird jemandem helfen. Viel Spaß beim Codieren.

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

}
Naveen
quelle
Dies verblasst im Vergleich zu den anderen Antworten, die erklärender und weniger code-lastig sind. Können Sie erklären, was Sie mit diesem Code erreichen und warum er eine geeignete Antwort liefert?
Makoto
2
Dies hat nichts mit dem Aufteilen einer Datei in Zeilen zu tun. Ziehen Sie in Betracht, Ihre Antwort zu entfernen.
Martin