แยกสตริง Java ตามบรรทัดใหม่


389

ฉันพยายามแยกข้อความในการJTextAreaใช้ regex เพื่อแยกสตริงโดย\nอย่างไรก็ตามสิ่งนี้ไม่ทำงานและฉันก็ลองด้วย\r\n|\r|nและการรวมกันของ regexes อื่น ๆ รหัส:

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 กำลังทำการตัดบรรทัดหรือไม่ - ???
user85421

คำตอบ:


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: ความยาว (fn: แยก (ข้อมูล, '\\ r? \\ n'))} ไม่ทำงานใน jstl

4
@antak ใช่splitโดยค่าเริ่มต้นจะลบสตริงว่างต่อท้ายหากพวกเขาพัสดุผลของการแยก หากต้องการเปิดกลไกนี้ปิดที่คุณจำเป็นต้องใช้ overloaded รุ่นที่มีวงเงินเชิงลบเช่นsplit(regex, limit) text.split("\\r?\\n", -1)ข้อมูลเพิ่มเติม: การแยกสตริง Java ลบค่าว่าง
Pshemo

1
ความคิดเห็นโดย @stivlo เป็นข้อมูลที่ผิดและเป็นที่น่าเสียดายว่ามีอัปโหลดจำนวนมาก @ @ Raekye ชี้ให้เห็นว่า OS X (ปัจจุบันรู้จักกันในชื่อ macOS) ได้ใช้ \ n เป็นตัวคั่นบรรทัดตั้งแต่เปิดตัวในปี 2544 Mac OS 9 ได้รับการปล่อยตัวในปี 1999 และฉันไม่เคยเห็น Mac OS 9 หรือเครื่องที่ต่ำกว่ามาใช้ ในการผลิต ไม่มีระบบปฏิบัติการสมัยใหม่เดียวที่ใช้ \ r เป็นตัวคั่นบรรทัด ไม่เคยเขียนโค้ดที่คาดว่า \ r จะเป็นตัวแยกบรรทัดบน Mac เว้นแต่ a) คุณกำลังประมวลผลแบบย้อนยุคข) มีการหมุนของเครื่อง OS 9 และ c) สามารถระบุได้อย่างแม่นยำว่าเครื่องนั้นเป็นระบบปฏิบัติการจริง 9
James McLaughlin

132

String#split​(String regex)method กำลังใช้ regex (นิพจน์ทั่วไป) เนื่องจาก Java 8 regex สนับสนุน\Rสิ่งที่แสดงถึง (จากเอกสารของรูปแบบคลาส ):

Linebreak matcher
\ R ลำดับ Unicode ใด ๆ ที่เทียบเท่า \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

ดังนั้นเราสามารถใช้มันเพื่อจับคู่:

ตามที่คุณเห็น\r\nจะอยู่ที่จุดเริ่มต้นของ regex ซึ่งทำให้แน่ใจว่า regex จะพยายามจับคู่คู่นี้ก่อนและหากการจับคู่นั้นล้มเหลวจะพยายามจับคู่ตัวแยกบรรทัดอักขระเดี่ยว


split("\\R")ดังนั้นถ้าคุณต้องการที่จะแยกในการใช้คั่นบรรทัด

หากคุณไม่ต้องการที่จะลบออกจากที่เกิดอาร์เรย์ท้ายสตริงที่ว่างเปล่า""ใช้split(regex, limit)กับเชิงลบพารามิเตอร์เช่นlimitsplit("\\R", -1)

split("\\R+")หากคุณต้องการที่จะรักษาหนึ่งหรือมากกว่าหนึ่งยังคงบรรทัดว่างกับการใช้ตัวคั่นเดียว


4
ใช่มันเป็นคำตอบที่ดีที่สุด โชคไม่ดีที่คำถามนี้ถามมาหกปีเร็วเกินไปสำหรับคำตอบนี้
Dawood ibn Kareem

ฉันสิ้นสุดที่แยกบน\\R+เพื่อหลีกเลี่ยงตัวอักษรใดปลายของสายที่ไม่ได้รับการคุ้มครองโดย\\Rคนเดียว
SeverityOne

128

หากคุณไม่ต้องการบรรทัดว่าง:

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

4
แบ็กสแลชสองครั้งไม่จำเป็นดูหัวข้อ "แบ็กสแลช, Escape
angryITguy


1
สิ่งนี้ใช้ได้กับ Mac OSX เมื่อคำตอบข้างต้นไม่ได้
จอห์น

มันก็ใช้ได้กับฉันเช่นกัน ทางออกที่ดีเยี่ยม มันใช้ได้กับ 2 กรณีต่อไปนี้: 1) ฉันตื่นนอนเวลา 3 นาฬิกา \ r \ n \ r \ n ฉันหวัง 2) นี่คือชีวิตจริง \ r \ n ดังนั้นฉัน
logixplayer

2
@tresf คุณไม่สามารถใช้ตัวระบุปริมาณในวงเล็บเหลี่ยมได้
นักเล่นเกม CX

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

นี่ควรเป็นระบบที่เป็นอิสระ


41
เป็นแนวคิดที่น่าสนใจ แต่คุณควรระวังว่าข้อความใช้ตัวแยกบรรทัดของระบบจริงๆ ฉันมีไฟล์ข้อความมากมายภายใต้ยูนิกซ์ (เช่น XML) ที่ใช้ตัวคั่น "Windows" และค่อนข้างน้อยภายใต้ Windows ที่ใช้ตัวคั่น Unix
Maarten Bodewes

ทำงานได้แม้บน Android
ruX

6
ไฟล์ที่สร้างใน Windows OS และถ่ายโอนไปยัง Unix OS จะยังคงมีตัวคั่น \ r \ n ฉันคิดว่ามันจะดีกว่าถ้าเล่นอย่างปลอดภัยและคำนึงถึงผู้แบ่งแยกทั้งสอง
bvdb

17
นี่เป็นวิธีที่มีปัญหามาก! ไฟล์อาจไม่ได้มาจากระบบที่ใช้รหัส ฉันขอกีดกันการออกแบบ "ระบบที่เป็นอิสระ" ประเภทนี้ซึ่งจริง ๆ แล้วขึ้นอยู่กับระบบเฉพาะระบบรันไทม์
Martin

4
@ Shervin มันไม่เคยเป็นวิธีที่ดีที่สุดที่จะทำ ในความเป็นจริงมันเป็นวิธีปฏิบัติที่ไม่ดีมาก พิจารณาโปรแกรมเมอร์คนอื่น ๆ ที่เรียก System.setProperty ("line.separator", "คุณไม่มีประเด็น"); รหัสของคุณเสีย มันอาจถูกเรียกในทำนองเดียวกันโดยการพึ่งพาที่คุณไม่มีความรู้เกี่ยวกับ
Martin

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 หนึ่งตัวอาจยอมรับมันในขณะที่อีกอันจะทำให้หายใจไม่ออก ดังนั้นสิ่งที่สำคัญที่สุดคือถึงแม้ว่ารสชาติของ RegEx ของ Java ไม่ต้องการพวกเขาให้ใช้เครื่องหมายทับสองครั้งเพื่อความเข้ากันได้
nurchi

10

ในชั้นมีวิธีการ:JDK11Stringlines()

ส่งคืนสตรีมของบรรทัดที่แยกออกจากสตริงนี้คั่นด้วยตัวคั่นบรรทัด

นอกจากนี้เอกสารยังกล่าวต่อไปว่า:

ตัวยุติบรรทัดเป็นหนึ่งในสิ่งต่อไปนี้: อักขระตัวดึงข้อมูลบรรทัด "\ 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:

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

8
ไม่ได้จริงๆ เมื่อคุณเขียน regex ในรูปแบบของ Java String สัญพจน์คุณสามารถใช้ "\ n" เพื่อส่งผ่านสัญลักษณ์คอมไพเลอร์ regex สัญลักษณ์ linefeed หรือ "\\ n" เพื่อส่งผ่าน escape sequence สำหรับ linefeed เช่นเดียวกันกับช่องว่างอื่นทั้งหมดยกเว้น \ v ซึ่งไม่รองรับตัวอักษร Java
Alan Moore

3
@Yuval ขออภัยที่ไม่ถูกต้องคุณไม่จำเป็นต้องใช้ " Backslashes
angryITguy

7

คำตอบทั้งหมดที่ให้ไว้ที่นี่จริงไม่เคารพ Javas นิยามของบรรทัดใหม่ตามที่กำหนดในเช่น BufferedReader # readline Java คือการยอมรับ\n, \rและ\r\nเป็นบรรทัดใหม่ คำตอบบางคำตรงกับหลายบรรทัดว่างหรือไฟล์ที่มีรูปแบบไม่ถูกต้อง เช่น. <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());

ฉันรู้ว่านี่อาจเป็นวิธีแก้ปัญหามากเกินไป
Danilo Piazzalunga

3
หรือString[] lines = new BufferedReader(...).lines().toArray(String[]::new);สำหรับอาร์เรย์แทนรายการ สิ่งที่ดีเกี่ยวกับวิธีแก้ปัญหานี้ก็คือBufferedReaderรู้เกี่ยวกับตัวต่อแบบต่าง ๆ ทุกชนิดดังนั้นมันจึงสามารถจัดการข้อความในทุกรูปแบบได้ (ส่วนใหญ่โซลูชันที่อิงจาก regex ที่โพสต์ที่นี่จะสั้นในเรื่องนี้)
Ted Hopp

2
โซลูชันนี้เลิกใช้แล้วตั้งแต่ Java 11 และการแนะนำวิธี String.lines ()
leventov

4

สำหรับการรักษาบรรทัดว่างจากการใช้งานแบน:

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

3

รหัสข้างต้นไม่ได้ทำอะไรที่เห็นได้จริง - มันเป็นเพียงแค่ calcualtes แล้วทิ้งการคำนวณ เป็นรหัสที่คุณใช้หรือเป็นเพียงตัวอย่างสำหรับคำถามนี้

ลองทำ textAreaDoc.insertString (int, String, AttributeSet) ในตอนท้าย?


insertUpdate () เป็นวิธีการ DocumentListener สมมติว่า OP ใช้อย่างถูกต้องการพยายามแก้ไขเอกสารจากภายในเมธอด listener จะสร้างข้อยกเว้น แต่คุณพูดถูก: รหัสในคำถามนั้นไม่ได้ทำอะไรเลย
Alan Moore

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

ฉันทำซ้ำตัวอย่างที่ระบุในคำถามไม่ได้ แต่ฉันคิดว่าตรรกะนี้สามารถใช้ได้



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

ในโปรแกรมแก้ไขข้อความบางรายการเป็นไปได้ที่จะแลกเปลี่ยนหนึ่งสำหรับอีกอัน

Notepad ++

สิ่งที่ง่ายที่สุดคือการทำให้เป็นมาตรฐาน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 -features และ APIs ใน 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]);
        }
    }

}

หน้าซีดนี้เปรียบเทียบกับคำตอบอื่น ๆ ซึ่งเป็นคำอธิบายที่มากขึ้นและใช้รหัสน้อยลง คุณช่วยอธิบายสิ่งที่คุณทำกับรหัสนี้ได้อย่างไรและทำไมมันถึงได้รับคำตอบที่เหมาะสม?
Makoto

2
สิ่งนี้ไม่เกี่ยวข้องกับการแยกไฟล์ออกเป็นเส้น พิจารณาลบคำตอบของคุณ
Martin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.