Tách chuỗi Java theo dòng mới


389

Tôi đang cố gắng phân tách văn bản JTextAreabằng cách sử dụng biểu thức chính quy để phân tách Chuỗi theo \nTuy nhiên, điều này không hoạt động và tôi cũng đã thử \r\n|\r|nvà nhiều tổ hợp biểu thức chính khác. Mã số:

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
lỗi mà bạn nhận được là gì? Đừng nói "không hoạt động", điều đó không có nghĩa gì cả. Hãy cho chúng tôi biết lỗi / kết quả mà bạn nhận được. Đó là bước đầu tiên trong việc gỡ lỗi mã - tìm ra kết quả sai là gì và chương trình của bạn đã đạt được điều đó như thế nào.
Chii

Bạn thực sự muốn làm gì? - ngắt dòng khi chúng được nhập vào JTextArea? - tìm nơi JTextArea đang thực hiện kết thúc dòng? - ???
dùng85421

Câu trả lời:


732

Điều này sẽ bao gồm bạn:

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

Thực sự chỉ có hai dòng mới (UNIX và Windows) mà bạn cần phải lo lắng.


43
Tài liệu JTextArea NÊN chỉ sử dụng '\ n'; Lượt xem của nó hoàn toàn bỏ qua '\ r'. Nhưng nếu bạn sẽ tìm kiếm nhiều hơn một loại dấu phân cách, bạn cũng có thể tìm cả ba loại: "\ r? \ N | \ r".
Alan Moore

10
Mac 9 sử dụng \ r. OSX 10 sử dụng \ n
Raekye

$ {fn: length (fn: split (data, '\\ r? \\ n'))} không hoạt động trong jstl

4
@antak có, splittheo mặc định sẽ loại bỏ các chuỗi trống theo sau nếu chúng lưu kết quả phân tách. Để tắt cơ chế này, bạn cần sử dụng phiên bản quá tải split(regex, limit)với giới hạn âm như thế nào text.split("\\r?\\n", -1). Thông tin thêm: Phân chia chuỗi Java đã xóa các giá trị trống
Pshemo

1
Nhận xét của @stivlo là thông tin sai lệch, và thật không may là nó có quá nhiều sự ủng hộ. Như @ Raekye đã chỉ ra, OS X (nay là macOS) đã sử dụng \ n làm trình phân tách dòng kể từ khi nó được phát hành vào năm 2001. Mac OS 9 được phát hành vào năm 1999 và tôi chưa bao giờ thấy máy Mac OS 9 trở xuống được sử dụng trong sản xuất. Không có một hệ điều hành hiện đại nào sử dụng \ r làm dấu tách dòng. KHÔNG BAO GIỜ viết mã dự kiến ​​là trình phân tách dòng trên Mac, trừ khi a) bạn đang sử dụng máy tính retro, b) có máy OS 9 xuất hiện và c) có thể xác định một cách đáng tin cậy rằng máy thực sự là OS 9.
James McLaughlin

132

String#split​(String regex)phương thức đang sử dụng regex (biểu thức chính quy). Do regex Java 8 hỗ trợ \Rđại diện (từ tài liệu của lớp Mẫu ):

Bộ so khớp linebreak
\ R Bất kỳ chuỗi ngắt dòng Unicode nào, tương đương với \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Vì vậy, chúng ta có thể sử dụng nó để phù hợp:

Như bạn thấy \r\nđược đặt ở đầu regex, điều này đảm bảo rằng regex sẽ cố gắng khớp cặp này trước, và chỉ khi trận đấu đó thất bại, nó sẽ cố gắng khớp với các dấu phân cách dòng ký tự đơn .


Vì vậy, nếu bạn muốn phân chia sử dụng phân cách dòng split("\\R").

Nếu bạn không muốn loại bỏ khỏi chuỗi kết quả, các chuỗi trống"" sử dụng split(regex, limit)với limittham số âm như thế nào split("\\R", -1).

Nếu bạn muốn coi một hoặc nhiều dòng tiếp tục là sử dụng dấu phân cách đơn split("\\R+").


4
Vâng, đó là câu trả lời tốt nhất. Thật không may rằng câu hỏi đã được hỏi sáu năm quá sớm cho câu trả lời này.
Dawood ibn Kareem

Tôi đã kết thúc việc chia tách \\R+, để tránh bất kỳ nhân vật cuối dòng nào không được bao phủ bởi \\Rmột mình.
SeverityOne

128

Nếu bạn không muốn dòng trống:

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

4
dấu gạch chéo kép là không cần thiết, xem phần "Dấu gạch chéo ngược, thoát và trích dẫn" docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/iêu
AngryITguy


1
Điều này hoạt động trên Mac OSX khi câu trả lời trên không có.
Giăng

Điều này cũng làm việc cho tôi. Giải pháp tuyệt vời. Nó làm việc cho 2 trường hợp sau: 1) tôi thức dậy lúc 3:00 \ r \ n \ r \ nTôi hy vọng 2) đây là cuộc sống thực \ r \ nso tôi.
logixplayer

2
@tresf Bạn không thể sử dụng bộ định lượng trong ngoặc vuông.
Game thủ CX

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

Điều này nên độc lập với hệ thống


41
Đó là một ý tưởng thú vị, nhưng bạn nên lưu ý rằng văn bản thực sự sử dụng dấu tách dòng của hệ thống. Tôi đã sử dụng nhiều tệp văn bản trong unix (ví dụ: XML) sử dụng các dấu tách "Windows" và một số ít trong Windows sử dụng các dấu tách unix.
Maarten Bodewes

Hoạt động ngay cả trên Android
ruX

6
Các tệp được tạo trong HĐH Windows và được chuyển sang HĐH Unix vẫn sẽ chứa các bộ tách biệt \ r \ n. Tôi nghĩ tốt hơn là chơi an toàn và sử dụng cả hai cách ly.
bvdb

17
Đây là một cách tiếp cận rất có vấn đề! Các tập tin có thể không bắt nguồn từ hệ thống chạy mã. Tôi đặc biệt không khuyến khích các loại thiết kế "độc lập hệ thống" này thực sự phụ thuộc vào một hệ thống cụ thể, hệ thống thời gian chạy.
Martin

4
@Shervin Nó không bao giờ là cách tốt nhất để làm điều đó. Đó là thực tế rất xấu. Hãy xem xét một số lập trình viên khác gọi System.setProperty ("line.separator", "bạn không có điểm nào"); Mã của bạn bị hỏng. Nó thậm chí có thể được gọi tương tự bởi một phụ thuộc mà bạn không có kiến ​​thức về.
Martin

14

Một phương thức mới linesđã được giới thiệu cho Stringlớp trong, trả lại Stream<String>

Trả về một luồng các chuỗi con được trích xuất từ ​​chuỗi này được phân vùng bởi các đầu cuối dòng.

Thiết bị đầu cuối dòng được nhận dạng là nguồn cấp dữ liệu "\ n" (U + 000A), trả lại vận chuyển "\ r" (U + 000D) và trả lại vận chuyển ngay sau nguồn cấp dữ liệu "\ r \ n" (U + 000D U + 000A ).

Đây là vài ví dụ:

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

Chuỗi # dòng ()


12

Bạn không phải nhân đôi lối thoát trong các nhóm nhân vật.

Đối với tất cả các dòng không trống sử dụng:

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

Vâng, bạn làm. Nếu họ cần thoát kép ở bất cứ đâu, họ cần nó ở mọi nơi. Khoảng trắng thoát như thế \r\ncó thể có một hoặc hai dấu gạch chéo ngược; họ làm việc một trong hai cách
Alan Moore

2
Dấu gạch chéo kép '\\'trong mã trở thành một '\'ký tự và sau đó được chuyển đến công cụ RegEx, do đó, "[\\r\\n]"mã trở thành [\r\n]trong bộ nhớ và RegEx sẽ xử lý điều đó. Tôi không biết chính xác Java xử lý RegEx như thế nào, nhưng cách tốt nhất là truyền mẫu chuỗi ASCII "thuần túy" cho công cụ RegEx và để nó xử lý thay vì chuyển các ký tự nhị phân. "[\r\n]"trở thành (hex) 0D0Atrong bộ nhớ và một công cụ RegEx có thể chấp nhận nó trong khi một công cụ khác sẽ bị nghẹt thở. Vì vậy, điểm mấu chốt là ngay cả khi hương vị RegEx của Java không cần đến chúng, hãy giữ hai dấu gạch chéo để tương thích
nicksi

10

Trong JDK11các Stringlớp học có một lines()phương pháp:

Trả về một dòng các dòng được trích xuất từ ​​chuỗi này, được phân tách bằng các đầu cuối dòng.

Hơn nữa, các tài liệu tiếp tục nói:

Bộ kết thúc dòng là một trong những điều sau đây: ký tự nguồn cấp dữ liệu "\ n" (U + 000A), ký tự trả về vận chuyển "\ r" (U + 000D) hoặc trả về vận chuyển ngay sau nguồn cấp dữ liệu dòng "\ r \ n "(U + 000D U + 000A). Một dòng là một chuỗi gồm 0 hoặc nhiều ký tự được theo sau bởi dấu kết thúc dòng hoặc nó là một chuỗi gồm một hoặc nhiều ký tự theo sau là cuối chuỗi. Một dòng không bao gồm dấu kết thúc dòng.

Với điều này chỉ có thể làm:

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

sau đó nếu bạn muốn một mảng:

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

Đưa ra phương thức này trả về một luồng cho nó rất nhiều tùy chọn cho bạn vì nó cho phép người ta viết biểu thức súc tích và khai báo của các hoạt động có thể song song.


7

Có lẽ điều này sẽ làm việc:

Xóa các dấu gạch chéo kép khỏi tham số của phương thức phân tách:

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

8
Không hẳn vậy. Khi bạn viết một biểu thức chính thức dưới dạng một chuỗi ký tự Java, bạn có thể sử dụng "\ n" để truyền cho trình biên dịch biểu thức chính một biểu tượng dòng cấp dữ liệu hoặc "\ n" để truyền chuỗi thoát cho một nguồn cấp dữ liệu. Điều tương tự cũng xảy ra với tất cả các khoảng trắng thoát khác ngoại trừ \ v, không được hỗ trợ trong các chữ Java.
Alan Moore

3
@Yuval. Xin lỗi đó là không chính xác, bạn không cần nó ở tất cả "Dấu gạch chéo ngược, thoát và trích dẫn" docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/ trộm
AngryITguy

7

Tất cả các câu trả lời được đưa ra ở đây thực sự không tôn trọng định nghĩa của Javas về các dòng mới như được đưa ra trong ví dụ: BufferedReader # readline. Java được chấp nhận \n, \r\r\nnhư dòng mới. Một số câu trả lời khớp với nhiều dòng trống hoặc tệp không đúng định dạng. Ví dụ. <sometext>\n\r\n<someothertext>khi sử dụng [\r\n]+sẽ dẫn đến hai dòng.

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

Ngược lại, câu trả lời ở trên có các thuộc tính sau:

  • nó tuân thủ định nghĩa của Javas về một dòng mới, ví dụ như BufferedReader đang sử dụng nó
  • nó không khớp với nhiều dòng mới
  • nó không xóa các dòng trống

6

Nếu, vì một số lý do, bạn không muốn sử dụng String.split(ví dụ: vì các biểu thức thông thường ) và bạn muốn sử dụng lập trình chức năng trên Java 8 hoặc mới hơn:

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

Tôi biết đây có thể là một giải pháp quá mức.
Danilo Piazzalunga

3
Hoặc String[] lines = new BufferedReader(...).lines().toArray(String[]::new);cho một mảng thay vì một danh sách. Điều thú vị về giải pháp này là BufferedReaderbiết về tất cả các loại thiết bị đầu cuối, vì vậy nó có thể xử lý văn bản ở tất cả các định dạng. (Hầu hết các giải pháp dựa trên regex được đăng ở đây đều thiếu về vấn đề này.)
Ted Hopp

2
Giải pháp này đã lỗi thời kể từ Java 11 và giới thiệu phương thức String.lines ().
leventov

4

Để bảo quản các dòng trống khỏi bị nghiền nát sử dụng:

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

3

Đoạn mã trên không thực sự làm bất cứ điều gì có thể nhìn thấy - nó chỉ là calcualte sau đó bỏ qua phép tính. Đây có phải là mã bạn đã sử dụng, hoặc chỉ là một ví dụ cho câu hỏi này?

thử làm textAreaDoc.insertString (int, String, Attributionset) ở cuối?


insertUpdate () là một phương thức DocumentListener. Giả sử OP đang sử dụng đúng, cố gắng sửa đổi tài liệu từ bên trong phương thức người nghe sẽ tạo ra một ngoại lệ. Nhưng bạn đã đúng: mã trong câu hỏi đó không thực sự làm gì cả.
Alan Moore

2

Thay thế cho các câu trả lời trước, SplitterAPI của ổi có thể được sử dụng nếu các hoạt động khác được áp dụng cho các dòng kết quả, như cắt các dòng hoặc lọc các dòng trống:

import com.google.common.base.Splitter;

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

Lưu ý rằng kết quả là một Iterablevà không phải là một mảng.


1

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


1

Sau những nỗ lực thất bại trên cơ sở của tất cả các giải pháp được đưa ra. Tôi thay thế \nbằng một số từ đặc biệt và sau đó chia tách. Đối với tôi sau đây đã thực hiện các mẹo:

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

Tôi không thể lặp lại ví dụ được đưa ra trong câu hỏi. Nhưng, tôi đoán logic này có thể được áp dụng.



0
  • Hãy thử hy vọng nó hữu ích cho bạn

 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

Có ba quy ước khác nhau (có thể nói rằng đó là những tiêu chuẩn thực tế ) để thiết lập và hiển thị ngắt dòng:

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

Trong một số trình soạn thảo văn bản, có thể trao đổi cái này với cái khác:

Notepad ++

Điều đơn giản nhất là bình thường hóa line feedvà sau đó phân chia.

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

0

Có một cậu bé mới trong thị trấn, vì vậy bạn không cần phải đối phó với tất cả những sự phức tạp ở trên. Từ JDK 11 trở đi , chỉ cần viết dưới dạng một dòng mã, nó sẽ phân chia các dòng và trả về cho bạn 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
}}

Một số tài liệu tham khảo. https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#lines () https://www.azul.com/90-new -features-và-apis-in-jdk-11 /

Tôi hy vọng điều này sẽ hữu ích cho ai đó. Chúc mừng mã hóa.


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

}

Điều này nhạt so với các câu trả lời khác, đó là giải thích nhiều hơn và ít mã hơn. Bạn có thể giải thích những gì bạn đang thực hiện với mã này và tại sao nó sẽ đưa ra một câu trả lời phù hợp?
Makoto

2
Điều này không có gì để làm với việc chia một tập tin thành dòng. Xem xét loại bỏ câu trả lời của bạn.
Martin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.