Pisahkan String Java dengan Baris Baru

390

Saya mencoba untuk membagi teks dalam JTextAreamenggunakan regex untuk membagi String dengan \nNamun, ini tidak berhasil dan saya juga mencoba oleh \r\n|\r|ndan banyak kombinasi regex lainnya. Kode:

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
sumber
7
apa kesalahan yang Anda dapatkan? Jangan mengatakan "tidak bekerja", itu tidak berarti apa-apa. Beri tahu kami kesalahan / hasil yang Anda dapatkan. Itu adalah langkah pertama dalam kode debugging - cari tahu apa hasil yang salah, dan bagaimana program Anda mencapai itu.
Chii
Apa yang sebenarnya ingin Anda lakukan? - pecahkan garis saat dimasukkan di JTextArea? - menemukan di mana JTextArea melakukan pembungkus baris? - ???
user85421

Jawaban:

732

Ini harus melindungi Anda:

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

Hanya ada dua baris baru (UNIX dan Windows) yang perlu Anda khawatirkan.

cletus
sumber
43
Dokumen JTextArea HARUS hanya menggunakan '\ n'; Tampilannya sepenuhnya mengabaikan '\ r'. Tetapi jika Anda akan mencari lebih dari satu jenis pemisah, Anda mungkin juga mencari ketiganya: "\ r? \ N | \ r".
Alan Moore
10
Mac 9 menggunakan \ r. OSX 10 menggunakan \ n
Raekye
$ {fn: length (fn: split (data, '\\ r? \\ n'))} tidak berfungsi di jstl
4
@ antak ya, splitsecara default menghapus string kosong jika mereka hasil split. Untuk mematikan mekanisme ini, Anda perlu menggunakan versi overload split(regex, limit)dengan batas negatif seperti text.split("\\r?\\n", -1). Info selengkapnya: Java String split menghapus nilai kosong
Pshemo
1
Komentar oleh @stivlo adalah informasi yang salah, dan sangat disayangkan bahwa ia memiliki begitu banyak upvotes. Seperti yang ditunjukkan oleh @ Raekye, OS X (sekarang dikenal sebagai macOS) telah menggunakan \ n sebagai pemisah garisnya sejak dirilis pada tahun 2001. Mac OS 9 dirilis pada tahun 1999, dan saya belum pernah melihat Mac OS 9 atau di bawah mesin yang digunakan dalam produksi. Tidak ada sistem operasi modern tunggal yang menggunakan pemisah garis. JANGAN PERNAH menulis kode yang mengharapkan menjadi pemisah baris pada Mac, kecuali a) Anda memasuki komputasi retro, b) memiliki mesin OS 9 yang berputar, dan c) andal dapat menentukan bahwa mesin tersebut sebenarnya OS 9.
James McLaughlin
133

String#split​(String regex)Metode menggunakan regex (ekspresi reguler). Karena dukungan Java 8 regex \Ryang mewakili (dari dokumentasi kelas Pola ):

Linebreak matcher
\ R Urutan linebreak Unicode apa pun, setara dengan \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Jadi kita bisa menggunakannya untuk mencocokkan:

Seperti yang Anda lihat \r\nditempatkan pada awal regex yang memastikan bahwa regex akan mencoba untuk mencocokkan pasangan ini terlebih dahulu, dan hanya jika pertandingan itu gagal ia akan mencoba untuk mencocokkan pemisah garis karakter tunggal .


Jadi jika Anda ingin membagi menggunakan pemisah garis split("\\R").

Jika Anda tidak ingin menghapus dari array array dihasilkan string kosong"" gunakan split(regex, limit)dengan limitparameter negatif seperti split("\\R", -1).

Jika Anda ingin memperlakukan satu atau lebih lanjutkan baris kosong sebagai pembatas tunggal split("\\R+").

Pshemo
sumber
4
Ya, itu jawaban terbaik. Sayangnya pertanyaan itu diajukan enam tahun terlalu dini untuk jawaban ini.
Dawood ibn Kareem
Saya akhirnya berpisah \\R+, untuk menghindari karakter end-of-line yang tidak tercakup oleh \\Rsendirian.
SeverityOne
128

Jika Anda tidak ingin baris kosong:

String.split("[\\r\\n]+")
Gumbo
sumber
4
double backslash tidak diperlukan, lihat bagian "Backslash, lolos, dan mengutip" docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/…
angryITguy
1
Ini berfungsi pada Mac OSX ketika jawaban di atas tidak.
John
Ini juga bekerja untuk saya. Solusi yang sangat baik. Ini bekerja untuk 2 kasus berikut: 1) saya bangun jam 3 o. \ R \ n \ r \ nSaya harap 2) ini adalah kehidupan nyata \ r \ njadi saya
logixplayer
2
@tresf Anda tidak dapat menggunakan quantifiers dalam tanda kurung siku.
CX gamer
49
String.split(System.getProperty("line.separator"));

Ini harus independen dari sistem

Shervin Asgari
sumber
42
Ini ide yang menarik, tetapi Anda harus berhati-hati bahwa teks tersebut benar-benar menggunakan pemisah garis sistem. Saya memiliki banyak file teks di bawah unix (misalnya XML) yang menggunakan pemisah "Windows" dan beberapa di bawah Windows yang menggunakan pemisah unix.
Maarten Bodewes
Bekerja bahkan di android
ruX
7
File yang dibuat di OS Windows dan ditransfer ke OS Unix masih akan mengandung \ r \ n pemisah. Saya pikir lebih baik bermain aman dan mengambil kedua pemisah dalam akun.
bvdb
17
Ini adalah pendekatan yang sangat bermasalah! File mungkin tidak berasal dari sistem yang menjalankan kode. Saya sangat tidak menyarankan desain "sistem independen" semacam ini yang sebenarnya tergantung pada sistem tertentu, sistem runtime.
Martin
4
@ Shervin Ini tidak pernah cara terbaik untuk melakukannya. Ini sebenarnya praktik yang sangat buruk. Pertimbangkan beberapa pemrogram lain yang memanggil System.setProperty ("line.separator", "Anda tidak ada gunanya"); Kode Anda rusak. Bahkan mungkin disebut sama oleh dependensi yang tidak Anda ketahui.
Martin
14

Metode baru linestelah diperkenalkan ke Stringkelas di, yang kembali Stream<String>

Mengembalikan aliran substring yang diekstraksi dari string ini yang dipartisi oleh terminator garis.

Terminator garis yang dikenali adalah umpan baris "\ n" (U + 000A), carriage return "\ r" (U + 000D) dan carriage return segera diikuti oleh umpan baris "\ r \ n" (U + 000D U + 000A ).

Berikut ini beberapa contoh:

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
sumber
12

Anda tidak harus menggandakan karakter melarikan diri dalam grup karakter.

Untuk semua saluran yang tidak kosong gunakan:

String.split("[\r\n]+")
Martin
sumber
Ya, benar. Jika mereka perlu melarikan diri dua kali ke mana saja, mereka membutuhkannya di mana saja. Spasi melarikan diri seperti \rdan \ndapat memiliki satu atau dua garis miring terbalik; mereka bekerja dengan cara baik.
Alan Moore
2
Double backslash '\\'dalam kode menjadi '\'karakter dan kemudian diteruskan ke mesin RegEx, sehingga "[\\r\\n]"dalam kode menjadi [\r\n]dalam memori dan RegEx akan memprosesnya. Saya tidak tahu bagaimana tepatnya Java menangani RegEx, tetapi itu adalah praktik yang baik untuk meneruskan pola string ASCII "murni" ke mesin RegEx dan membiarkannya memproses daripada melewati karakter biner. "[\r\n]"menjadi (hex) 0D0Adalam memori dan satu mesin RegEx mungkin menerimanya sementara yang lain akan tersedak. Jadi intinya adalah bahwa walaupun rasa Java dari RegEx tidak membutuhkannya, tetap
gunakan
10

Dalam JDK11satu Stringkelas memiliki lines()metode:

Mengembalikan aliran garis yang diekstraksi dari string ini, dipisahkan oleh terminator garis.

Selanjutnya, dokumentasi selanjutnya mengatakan:

Terminator garis adalah salah satu dari yang berikut: karakter umpan baris "\ n" (U + 000A), karakter carriage return "\ r" (U + 000D), atau carriage return diikuti segera oleh feed baris "\ r \ n "(U + 000D U + 000A). Garis adalah urutan dari nol atau lebih karakter yang diikuti oleh terminator garis, atau itu adalah urutan dari satu atau lebih karakter diikuti oleh akhir string. Garis tidak termasuk terminator garis.

Dengan yang satu ini bisa dilakukan:

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

maka jika Anda menginginkan sebuah array:

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

Mengingat metode ini mengembalikan Stream pada banyak pilihan bagi Anda karena memungkinkan seseorang untuk menulis ekspresi singkat dan deklaratif dari operasi yang mungkin paralel.

Ousmane D.
sumber
7

Mungkin ini akan berhasil:

Hapus garis miring terbalik ganda dari parameter metode split:

split = docStr.split("\n");
Michael
sumber
8
Tidak juga. Saat Anda menulis regex dalam bentuk Java String literal, Anda dapat menggunakan "\ n" untuk meneruskan kompiler regex simbol linefeed, atau "\\ n" untuk memberikannya urutan escape untuk linefeed. Hal yang sama berlaku untuk semua spasi putih lainnya yang lolos kecuali \ v, yang tidak didukung dalam literal Java.
Alan Moore
3
@Yuval. Maaf itu tidak benar, Anda sama sekali tidak memerlukannya "Backslash, escapes, and quoting" docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/…
angryITguy
7

Semua jawaban yang diberikan di sini sebenarnya tidak menghormati definisi Javas dari baris baru seperti yang diberikan dalam contoh BufferedReader # readline. Java menerima \n, \rdan \r\nsebagai baris baru. Beberapa jawaban cocok dengan beberapa baris kosong atau file cacat. Misalnya. <sometext>\n\r\n<someothertext>saat menggunakan [\r\n]+akan menghasilkan dua baris.

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

Sebaliknya, jawaban di atas memiliki properti berikut:

  • itu sesuai dengan definisi Javas dari baris baru seperti misalnya BufferedReader menggunakannya
  • itu tidak cocok dengan beberapa baris baru
  • itu tidak menghapus trailing baris kosong
Sampai Schäfer
sumber
6

Jika, karena alasan tertentu, Anda tidak ingin menggunakan String.split(misalnya, karena ekspresi reguler ) dan Anda ingin menggunakan pemrograman fungsional pada Java 8 atau yang lebih baru:

List<String> lines = new BufferedReader(new StringReader(string))
        .lines()
        .collect(Collectors.toList());
Danilo Piazzalunga
sumber
Saya tahu ini mungkin solusi yang berlebihan.
Danilo Piazzalunga
3
Atau String[] lines = new BufferedReader(...).lines().toArray(String[]::new);untuk array, bukan daftar. Yang menyenangkan tentang solusi ini adalah yang BufferedReadermengetahui tentang semua jenis terminator yang sejenis, sehingga dapat menangani teks dalam semua jenis format. (Sebagian besar solusi berbasis regex yang diposting di sini gagal dalam hal ini.)
Ted Hopp
2
Solusi ini sudah usang sejak Java 11 dan pengenalan metode String.lines ().
leventov
4

Untuk menjaga agar baris kosong tidak tergencet gunakan:

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

Kode di atas tidak benar-benar melakukan apa pun yang terlihat - itu hanya perhitungan lalu dump perhitungan. Apakah kode yang Anda gunakan, atau hanya contoh untuk pertanyaan ini?

coba lakukan textAreaDoc.insertString (int, String, AttributeSet) di akhir?

Chii
sumber
insertUpdate () adalah metode DocumentListener. Dengan asumsi OP menggunakannya dengan benar, mencoba memodifikasi dokumen dari dalam metode pendengar akan menghasilkan pengecualian. Tapi Anda benar: kode dalam pertanyaan itu sebenarnya tidak melakukan apa-apa.
Alan Moore
2

Sebagai alternatif dari jawaban sebelumnya, SplitterAPI jambu biji dapat digunakan jika operasi lain diterapkan pada garis yang dihasilkan, seperti memotong garis atau menyaring garis kosong:

import com.google.common.base.Splitter;

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

Perhatikan bahwa hasilnya adalah Iterablebukan array.

Thomas Naskali
sumber
1

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

husayt
sumber
1

Setelah upaya yang gagal berdasarkan semua solusi yang diberikan. Saya ganti \ndengan beberapa kata khusus dan kemudian dibagi. Bagi saya mengikuti melakukan trik:

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

Saya tidak bisa meniru contoh yang diberikan dalam pertanyaan. Tapi, saya kira logika ini bisa diterapkan.

kravi
sumber
1

Jawaban di atas tidak membantu saya di Android, berkat respons Pshemo yang bekerja untuk saya di Android. Saya akan meninggalkan beberapa jawaban Pshemo di sini:

split("\\\\n")
Clasher
sumber
0
  • coba harapan ini itu membantu kamu

 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
sumber
0

Ada tiga konvensi yang berbeda (dapat dikatakan bahwa itu adalah standar de facto ) untuk menetapkan dan menampilkan jeda baris:

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

Di beberapa editor teks, dimungkinkan untuk bertukar satu dengan yang lain:

Notepad ++

Hal paling sederhana adalah menormalkan line feeddan kemudian membelah.

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

Ada anak baru di kota, jadi Anda tidak perlu berurusan dengan semua kompleksitas di atas. Dari JDK 11 dan seterusnya , hanya perlu menulis sebagai satu baris kode, itu akan memecah baris dan mengembalikan Anda 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
}}

Beberapa referensi. 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 /

Saya harap ini akan membantu seseorang. Selamat coding.

Bocah Merah
sumber
-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
sumber
Ini artinya jika dibandingkan dengan jawaban lain, yang lebih jelas dan kurang berat kode. Bisakah Anda menjelaskan apa yang Anda capai dengan kode ini, dan mengapa itu membuat jawaban yang cocok?
Makoto
2
Ini tidak ada hubungannya dengan memisahkan file menjadi beberapa baris. Pertimbangkan untuk menghapus jawaban Anda.
Martin