Chuỗi đa dòng Java


516

Đến từ Perl, tôi chắc chắn đang thiếu phương tiện "tài liệu ở đây" để tạo chuỗi nhiều dòng trong mã nguồn:

$string = <<"EOF"  # create a three-line string
text
text
text
EOF

Trong Java, tôi phải có các trích dẫn rườm rà và các dấu cộng trên mỗi dòng khi tôi nối chuỗi đa dòng của mình từ đầu.

Một số lựa chọn thay thế tốt hơn là gì? Xác định chuỗi của tôi trong một tệp thuộc tính?

Chỉnh sửa : Hai câu trả lời cho biết StringBuilder.append () thích hợp hơn với ký hiệu cộng. Bất cứ ai có thể giải thích tại sao họ nghĩ như vậy? Nó không có vẻ tốt hơn đối với tôi cả. Tôi đang tìm cách khắc phục sự thật rằng các chuỗi đa dòng không phải là cấu trúc ngôn ngữ hạng nhất, điều đó có nghĩa là tôi chắc chắn không muốn thay thế cấu trúc ngôn ngữ hạng nhất (nối chuỗi bằng dấu cộng) bằng các lệnh gọi phương thức.

Chỉnh sửa : Để làm rõ hơn câu hỏi của tôi, tôi không quan tâm đến hiệu suất. Tôi quan tâm đến vấn đề bảo trì và thiết kế.


12
StringBuilder.append () được ưu tiên cộng thêm khi liên tục thêm vào chuỗi bởi vì mỗi khi bạn thực hiện string1 + string2việc phân bổ một đối tượng chuỗi mới và sao chép các ký tự từ cả hai chuỗi đầu vào. Nếu bạn thêm n Chuỗi với nhau, bạn sẽ thực hiện phân bổ n-1 và khoảng (n ^ 2) / 2 bản sao ký tự. StringBuilder, mặt khác, sao chép và phân bổ lại ít thường xuyên hơn (mặc dù nó vẫn làm cả khi bạn vượt quá kích thước của bộ đệm bên trong của nó). Về mặt lý thuyết, có những trường hợp trình biên dịch có thể chuyển đổi + để sử dụng StringBuilder nhưng trong thực tế ai biết được.
Laurence Gonsalves

5
Mỗi lần tôi nhảy vào trình gỡ lỗi, + được chuyển đổi thành lệnh gọi StringBuilder.append (), trên Java 1.5. Tôi đã có các đồng nghiệp bối rối nói với tôi rằng StringBuilder có một lỗi do họ gỡ lỗi thành mã không xuất hiện để gọi nó và kết thúc ở đó.
Skiphoppy


61
Lưu ý rằng một chuỗi ký tự được tạo thành từ "abc \ n" + "def \ n", v.v. không sử dụng StringBuilder: trình biên dịch sẽ dán chúng lại với nhau và đặt chúng vào tệp. Class dưới dạng một chữ duy nhất, giống như với các loại khác của gấp liên tục.
araqnid

6
Hầu hết các IDE đều hỗ trợ nhập chuỗi nhiều dòng. I E. bạn chỉ cần nhập hoặc dán những gì bạn muốn vào chuỗi "" và nó sẽ thêm \ n và "+" theo yêu cầu. ví dụ: tôi có thể dán 40 dòng văn bản vào Chuỗi và IDE sắp xếp nó cho bạn.
Peter Lawrey

Câu trả lời:


118

Stephen Colebourne đã tạo một đề xuất để thêm các chuỗi nhiều dòng trong Java 7.

Ngoài ra, Groovy đã hỗ trợ các chuỗi nhiều dòng .


14
Quá trình Project Coin để cải tiến Java bao gồm các chuỗi nhiều dòng mail.openjdk.java.net/pipermail/coin-dev/2009-F / 2 / . Nó đã bị từ chối bởi các blog của Oracle.sun.com/darcy/entry/project_coin_final_five .
JodaStephen

8
có sự thay đổi nào trong năm 2012 không?
Ilia G

13
Thật không may, điều này dường như không làm cho nó vào spec.
namuol

3
Liên kết blog.sun.com bị hỏng, nhưng tôi nghĩ nội dung hiện có tại blog.oracle.com/darcy/entry/project_coin_final_five ngay bây giờ.
Donal Fellows

8
Có vẻ, kể từ tháng 1 năm 2018, cộng đồng đang xem xét lại các chuỗi nhiều dòng. openjdk.java.net/jeps/326
Shane Gannon

485

Có vẻ như bạn muốn thực hiện một nghĩa đen nhiều dòng, không tồn tại trong Java.

Sự thay thế tốt nhất của bạn sẽ là các chuỗi chỉ là +cùng nhau. Một số tùy chọn khác mà mọi người đã đề cập (StringBuilder, String.format, String.join) sẽ chỉ thích hợp hơn nếu bạn bắt đầu với một chuỗi các chuỗi.

Xem xét điều này:

String s = "It was the best of times, it was the worst of times,\n"
         + "it was the age of wisdom, it was the age of foolishness,\n"
         + "it was the epoch of belief, it was the epoch of incredulity,\n"
         + "it was the season of Light, it was the season of Darkness,\n"
         + "it was the spring of hope, it was the winter of despair,\n"
         + "we had everything before us, we had nothing before us";

Phiên bản StringBuilder:

String s = new StringBuilder()
           .append("It was the best of times, it was the worst of times,\n")
           .append("it was the age of wisdom, it was the age of foolishness,\n")
           .append("it was the epoch of belief, it was the epoch of incredulity,\n")
           .append("it was the season of Light, it was the season of Darkness,\n")
           .append("it was the spring of hope, it was the winter of despair,\n")
           .append("we had everything before us, we had nothing before us")
           .toString();

Phiên bản String.format():

String s = String.format("%s\n%s\n%s\n%s\n%s\n%s"
         , "It was the best of times, it was the worst of times,"
         , "it was the age of wisdom, it was the age of foolishness,"
         , "it was the epoch of belief, it was the epoch of incredulity,"
         , "it was the season of Light, it was the season of Darkness,"
         , "it was the spring of hope, it was the winter of despair,"
         , "we had everything before us, we had nothing before us"
);

Phiên bản Java8 String.join():

String s = String.join("\n"
         , "It was the best of times, it was the worst of times,"
         , "it was the age of wisdom, it was the age of foolishness,"
         , "it was the epoch of belief, it was the epoch of incredulity,"
         , "it was the season of Light, it was the season of Darkness,"
         , "it was the spring of hope, it was the winter of despair,"
         , "we had everything before us, we had nothing before us"
);

Nếu bạn muốn xuống dòng cho hệ thống cụ thể của bạn, bạn có nhu cầu sử dụng System.lineSeparator(), hoặc bạn có thể sử dụng %ntrong String.format.

Một tùy chọn khác là đặt tài nguyên vào một tệp văn bản và chỉ cần đọc nội dung của tệp đó. Điều này sẽ thích hợp hơn cho các chuỗi rất lớn để tránh làm đầy các tệp lớp của bạn một cách không cần thiết.


246
Hơn nữa, phiên bản đầu tiên sẽ được trình biên dịch tự động nối, vì tất cả các chuỗi được biết đến tại thời điểm biên dịch. Ngay cả khi các chuỗi không được biết đến trong thời gian biên dịch, nó cũng không chậm hơn StringBuilder hoặc String.format (). Lý do duy nhất để tránh ghép nối với + là nếu bạn thực hiện theo vòng lặp.
Michael Myers

23
Vấn đề với String.formatphiên bản là bạn phải giữ định dạng đồng bộ với số lượng dòng.
Bart van Heukelom

4
String.format không hiệu quả so với hai ví dụ khác
cmcginty

10
Câu trả lời này là một giải pháp rất không phù hợp cho câu hỏi trong tầm tay. Chúng tôi có 2000 macro dòng SAS hoặc bó 200 truy vấn SQL dòng mà chúng tôi muốn sao chép và dán. Để đề xuất rằng chúng tôi sử dụng concat + "" để chuyển đổi các văn bản đa dòng đó thành các phần bổ sung StringBuffer là vô lý.
Phước lành Geek

21
@BlessedGeek: câu hỏi trong tầm tay là về các tùy chọn có sẵn trong ngôn ngữ Java. Nó không đề cập bất cứ điều gì về loại dữ liệu đi vào chuỗi. Nếu có một giải pháp tốt hơn thì bạn có thể đăng nó như một câu trả lời. Có vẻ như giải pháp của Josh Curren sẽ tốt hơn cho tình huống của bạn. Nếu bạn cảm thấy buồn vì ngôn ngữ này không hỗ trợ cho những người theo nghĩa đen thì đây là nơi sai lầm để phàn nàn về nó.
Kip

188

Trong Eclipse nếu bạn bật tùy chọn "Thoát văn bản khi dán vào một chuỗi ký tự" (trong Preferences> Java> Editor> Typing) và dán một trích dẫn chuỗi nhiều dòng, nó sẽ tự động thêm "\n" +cho tất cả các dòng của bạn.

String str = "paste your text here";

15
intelij cũng thực hiện điều này theo mặc định khi bạn dán vào "" s
Bob B

Bạn có thường để lại trong \rs mà Eclipse đưa vào Windows không?
Noumenon

99

Đây là một chủ đề cũ, nhưng một giải pháp khá thanh lịch mới (chỉ có 4 nhược điểm nhỏ có thể là 3) là sử dụng một chú thích tùy chỉnh.

Kiểm tra: http://www.adrianwalker.org/2011/12/java-multiline-opes.html

Một dự án lấy cảm hứng từ công việc đó được lưu trữ trên GitHub:

https://github.com/benelog/multiline

Ví dụ về mã Java:

import org.adrianwalker.multilinestring.Multiline;
...
public final class MultilineStringUsage {

  /**
  <html>
    <head/>
    <body>
      <p>
        Hello<br/>
        Multiline<br/>
        World<br/>
      </p>
    </body>
  </html>
  */
  @Multiline
  private static String html;

  public static void main(final String[] args) {
    System.out.println(html);
  }
}

Hạn chế là

  1. rằng bạn phải kích hoạt bộ xử lý chú thích (được cung cấp) tương ứng.
  2. biến chuỗi đó không thể được định nghĩa là biến cục bộ Kiểm tra dự án Chuỗi ký tự thô trong đó bạn có thể xác định biến là biến cục bộ
  3. Chuỗi đó không thể chứa các biến khác như trong Visual Basic .Net với XML bằng chữ ( <%= variable %>) :-)
  4. chuỗi ký tự đó được phân cách bằng nhận xét JavaDoc (/ **)

Và bạn có thể phải định cấu hình Eclipse / Intellij-Idea để không tự động định dạng lại các bình luận Javadoc của bạn.

Người ta có thể thấy điều này kỳ lạ (các bình luận Javadoc không được thiết kế để nhúng bất cứ thứ gì ngoài các bình luận), nhưng vì việc thiếu chuỗi đa dòng này trong Java thực sự gây phiền nhiễu, cuối cùng tôi thấy đây là giải pháp tồi tệ nhất.


Điều đó có yêu cầu lớp sử dụng chuỗi multiline là cuối cùng không? Ngoài ra, có bất kỳ thiết lập nào được yêu cầu khi phát triển và thực thi mã từ Eclipse không? URL tham chiếu đề cập đến các yêu cầu thiết lập cho Maven để xử lý chú thích. Tôi không thể tìm ra những gì có thể cần thiết, nếu có trong Eclipse.
David

Chú thích là có thể sống được - nhưng dường như cũng có một sự phụ thuộc cứng rắn vào maven? Phần đó lấy đi phần lớn giá trị của di truyền nhằm đơn giản hóa việc quản lý các đoạn văn bản nhỏ.
javadba

3
Bạn có thể làm điều này hoàn toàn trong nhật thực. Liên kết mà @SRG đã đăng ở trên chỉ cho bạn liên kết này . Nếu bạn đang sử dụng nhật thực, thì một phút thiết lập và nó đang hoạt động.
Michael Plautz

4
Đây có lẽ là vụ hack lớn nhất tôi từng thấy. EDIT: Nevermind ... xem câu trả lời của Bob Albrights.
Llew Vallis

1
Tôi đã thực hiện một phần mở rộng của dự án này, một phần mới được tạo ra mà các biến cục bộ được hỗ trợ, hãy xem dự án
deFreitas

62

Một tùy chọn khác có thể là lưu trữ các chuỗi dài trong một tệp bên ngoài và đọc tệp thành một chuỗi.


13
Chính xác. Một lượng lớn văn bản không thuộc về nguồn Java; thay vào đó, hãy sử dụng tệp tài nguyên có định dạng phù hợp, được tải thông qua lệnh gọi Class.getResource (Chuỗi).
erickson

5
Đúng! Bạn cũng có thể sử dụng Locale + ResourceBundle để dễ dàng tải văn bản I18N và sau đó, lệnh gọi String.format () sẽ phân tích cú pháp của "\ n" dưới dạng dòng mới :) Ví dụ: String readyStr = String.parse (resourceBundle.getString (" Giới thiệu"));
ATorras

62
Bạn không cần phải ra bên ngoài một Chuỗi chỉ vì nó là nhiều dòng. Điều gì xảy ra nếu tôi có một regex mà tôi muốn chia thành nhiều dòng với các bình luận? Nó trông xấu xí trong Java. Các @cú pháp cho C # là nhiều bụi.
Jeremy Stein

8
Skiphoppy không muốn bận tâm đến việc xử lý các tệp chỉ để sử dụng hằng chuỗi có độ dài đoạn. Tôi sử dụng các chuỗi đa dòng mọi lúc trong C ++, được nhúng trong mã nguồn của tôi, nơi tôi muốn chúng.
Tim Cooper

9
Ồ Tôi không thể tin C ++ thực sự tốt hơn Java về vấn đề này! Tôi yêu các hằng chuỗi nhiều dòng và chúng thuộc về nguồn trong một số trường hợp.
dùng1

59

Đây là thứ mà bạn không bao giờ nên sử dụng mà không nghĩ về những gì nó đang làm. Nhưng đối với các kịch bản một lần tôi đã sử dụng điều này rất thành công:

Thí dụ:

    System.out.println(S(/*
This is a CRAZY " ' ' " multiline string with all sorts of strange 
   characters!
*/));

Mã số:

// From: http://blog.efftinge.de/2008/10/multi-line-string-literals-in-java.html
// Takes a comment (/**/) and turns everything inside the comment to a string that is returned from S()
public static String S() {
    StackTraceElement element = new RuntimeException().getStackTrace()[1];
    String name = element.getClassName().replace('.', '/') + ".java";
    StringBuilder sb = new StringBuilder();
    String line = null;
    InputStream in = classLoader.getResourceAsStream(name);
    String s = convertStreamToString(in, element.getLineNumber());
    return s.substring(s.indexOf("/*")+2, s.indexOf("*/"));
}

// From http://www.kodejava.org/examples/266.html
private static String convertStreamToString(InputStream is, int lineNum) {
    /*
     * To convert the InputStream to String we use the BufferedReader.readLine()
     * method. We iterate until the BufferedReader return null which means
     * there's no more data to read. Each line will appended to a StringBuilder
     * and returned as String.
     */
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null; int i = 1;
    try {
        while ((line = reader.readLine()) != null) {
            if (i++ >= lineNum) {
                sb.append(line + "\n");
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return sb.toString();
}

15
Yêu cầu vận chuyển mã Java cho lớp với nhị phân cuối cùng. Hừm.
Thorbjørn Ravn Andersen

23
tôi có thể tưởng tượng phản ứng của đồng nghiệp khi tôi cố kiểm tra thứ gì đó như thế này trong ...
Landon Kuhn

15
+1. Một số thiếu trí tưởng tượng của những người bỏ phiếu xuống. Đây là một cấu trúc hữu ích để viết các tiện ích nhỏ, các trường hợp thử nghiệm và thậm chí trong các môi trường prod được kiểm soát. Đây là một nhà sản xuất khác biệt giữa việc bỏ java vào ruby ​​/ python / etc hoặc ở lại đây.
javadba

1
Giải pháp tuyệt vời, nhưng không may là sẽ không hoạt động cho Android vì nó sẽ được thực thi trên trình giả lập hoặc thiết bị thực và không có mã nguồn ở đó.
evgeny.myasishchev

Có thể đó là một trình thăm dò Java 8 hoặc một cái gì đó khác, nhưng trình tải lớp trong ví dụ không tồn tại. Tôi đã thử sử dụng MyClass. Class.getResourceAsStream (...), nhưng nó luôn trả về null. Sẽ là một giải pháp nhanh chóng tuyệt vời để thử nghiệm!
Nick

54

String.join

Java 8 đã thêm một phương thức tĩnh mới để java.lang.Stringcung cấp một sự thay thế tốt hơn một chút:

String.join( CharSequence delimiter , CharSequence... elements )

Sử dụng nó:

String s = String.join(
    System.getProperty("line.separator"),
    "First line.",
    "Second line.",
    "The rest.",
    "And the last!"
);

5
Giải pháp gọn gàng và sạch sẽ! Không phụ thuộc vào IDE và tiền xử lý! Không có hướng dẫn "\n"là cần thiết, và nhận thức được tính di động!
Siu Ching Pong -Asuka Kenji-

1
Tôi hiểu rằng nhận xét của tôi là vô ích, nhưng nó đã bị loại bỏ để tìm kiếm hack cho một điều cơ bản như một chuỗi nhiều chữ. Tại sao java không thể vẫn thêm điều này vào spec?
dmitry

22

JEP 355: Khối văn bản (Bản xem trước) nhằm mục đích bao hàm chức năng này, hiện tại nó đang nhắm mục tiêu JDK 13 như một tính năng xem trước. Cho phép viết một cái gì đó như:

String s = """
    text
    text
    text
  """;

Trước JEP này, trong JDK12, JEP 326: Các chuỗi ký tự thô nhằm thực hiện một tính năng tương tự, nhưng cuối cùng nó đã bị rút lại.


2
Họ đã bỏ hỗ trợ này
deFreitas

2
Các khối văn bản hiện là một phần của Java 13.
ZhekaKozlov

19

Nếu bạn xác định chuỗi của mình trong tệp thuộc tính, nó sẽ trông tệ hơn nhiều. IIRC, nó sẽ giống như:

string:text\u000atext\u000atext\u000a

Nói chung, đó là một ý tưởng hợp lý để không nhúng các chuỗi lớn vào nguồn. Bạn có thể muốn tải chúng dưới dạng tài nguyên, có thể ở dạng XML hoặc định dạng văn bản có thể đọc được. Các tệp văn bản có thể được đọc trong thời gian chạy hoặc được biên dịch thành nguồn Java. Nếu bạn cuối cùng đặt chúng vào nguồn, tôi khuyên bạn nên đặt+ ở phía trước và bỏ qua các dòng mới không cần thiết:

final String text = ""
    +"text "
    +"text "
    +"text"
;

Nếu bạn có dòng mới, bạn có thể muốn một số phương thức tham gia hoặc định dạng:

final String text = join("\r\n"
    ,"text"
    ,"text"
    ,"text"
);

17

Các cộng được chuyển đổi thành StringBuilder.append, ngoại trừ khi cả hai chuỗi là hằng số để trình biên dịch có thể kết hợp chúng tại thời gian biên dịch. Ít nhất, đó là cách nó nằm trong trình biên dịch của Sun và tôi sẽ nghi ngờ nhất nếu không phải tất cả các trình biên dịch khác sẽ làm như vậy.

Vì thế:

String a="Hello";
String b="Goodbye";
String c=a+b;

thường tạo chính xác mã giống như:

String a="Hello";
String b="Goodbye":
StringBuilder temp=new StringBuilder();
temp.append(a).append(b);
String c=temp.toString();

Mặt khác:

String c="Hello"+"Goodbye";

giống như:

String c="HelloGoodbye";

Đó là, không có hình phạt nào trong việc phá vỡ chuỗi ký tự của bạn trên nhiều dòng có dấu cộng để dễ đọc.


4
về mặt kỹ thuật, trong ví dụ đầu tiên của bạn, nó tạo ra một cái gì đó giống như: String c = new StringBuilder (). append (a) .append (b) .toString (); Sự khác biệt là trình tạo chuỗi tạm thời nằm ngoài phạm vi và đủ điều kiện để thu gom rác ngay sau dòng Chuỗi c = ..., trong khi đó, trình tạo chuỗi "tạm thời" sẽ tồn tại lâu hơn một chút.
Kip

Thật. Tất nhiên, quan điểm của tôi là phân biệt khi nào một hàm được gọi vào thời gian chạy so với khi công việc có thể được thực hiện vào thời gian biên dịch. Nhưng bạn đã đúng.
Jay

15

Trong IntelliJ IDE bạn chỉ cần gõ:

""

Sau đó định vị con trỏ của bạn bên trong dấu ngoặc kép và dán chuỗi của bạn. IDE sẽ mở rộng nó thành nhiều đường nối.


11

Đáng buồn thay, Java không có chuỗi ký tự nhiều dòng. Bạn có thể ghép nối các chuỗi ký tự (sử dụng + hoặc StringBuilder là hai cách tiếp cận phổ biến nhất cho việc này) hoặc đọc chuỗi trong một tệp riêng biệt.

Đối với các chuỗi ký tự nhiều dòng lớn, tôi có xu hướng sử dụng một tệp riêng và đọc nó bằng cách sử dụng getResourceAsStream()(một phương pháp củaClass lớp). Điều này giúp bạn dễ dàng tìm thấy tệp vì bạn không phải lo lắng về thư mục hiện tại so với nơi mã của bạn được cài đặt. Nó cũng làm cho việc đóng gói dễ dàng hơn, bởi vì bạn thực sự có thể lưu trữ tệp trong tệp jar của bạn.

Giả sử bạn đang ở trong một lớp gọi là Foo. Chỉ cần làm một cái gì đó như thế này:

Reader r = new InputStreamReader(Foo.class.getResourceAsStream("filename"), "UTF-8");
String s = Utils.readAll(r);

Một điều khó chịu khác là Java không có phương thức "đọc tất cả văn bản từ Trình đọc này thành Chuỗi" tiêu chuẩn. Nó khá dễ để viết mặc dù:

public static String readAll(Reader input) {
    StringBuilder sb = new StringBuilder();
    char[] buffer = new char[4096];
    int charsRead;
    while ((charsRead = input.read(buffer)) >= 0) {
        sb.append(buffer, 0, charsRead);
    }
    input.close();
    return sb.toString();
}

Tôi cũng làm như vậy. Bạn có thể sử dụng commons-io để dễ dàng đọc nội dung của tệp hơn (với "FileUtils.readFileToString (Tệp tệp)").
SRG

Không còn đúng nữa về java không có tiêu chuẩn đọc tất cả phương thức văn bản ... - vì Java 7 bạn có thể sử dụng Files.read ALLLines (Đường dẫn)
ccpizza

10
String newline = System.getProperty ("line.separator");
string1 + newline + string2 + newline + string3

Nhưng, cách thay thế tốt nhất là sử dụng String.format

String multilineString = String.format("%s\n%s\n%s\n",line1,line2,line3);

Ý kiến ​​của tôi là nó loại bỏ các dấu cộng và dấu ngoặc kép, làm cho nó dễ đọc hơn, đặc biệt khi có nhiều hơn chỉ 3 dòng. Không tốt như String.format.
Tom

2
Ví dụ Stringbuilder ít nhất là không thể đọc được. Ngoài ra, đừng quên rằng "\ n" không phải lúc nào cũng là một dòng mới, nhưng nó tốt cho máy linux và unix.
Stefan Thyberg

Thêm vào đó, chỉ muốn đề cập đến sự tồn tại của StringBuilder.
Tom

4
Thay thế một dấu cộng bằng tên phương thức gồm sáu ký tự và dấu ngoặc đơn trông không dễ đọc hơn đối với tôi, mặc dù rõ ràng bạn không phải là người duy nhất nghĩ như vậy. Nó không loại bỏ các trích dẫn, mặc dù. Họ vẫn ở đó.
Skiphoppy

9

Do Java chưa (chưa) hỗ trợ các chuỗi nhiều dòng riêng, nên cách duy nhất bây giờ là hack xung quanh nó bằng một trong các kỹ thuật đã nói ở trên. Tôi đã xây dựng tập lệnh Python sau bằng một số thủ thuật được đề cập ở trên:

import sys
import string
import os

print 'new String('
for line in sys.stdin:
    one = string.replace(line, '"', '\\"').rstrip(os.linesep)
    print '  + "' + one + ' "'
print ')'

Đặt nó trong một tệp có tên javastringify.py và chuỗi của bạn trong một tệp mystring.txt và chạy nó như sau:

cat mystring.txt | python javastringify.py

Sau đó, bạn có thể sao chép đầu ra và dán nó vào trình soạn thảo của mình.

Sửa đổi điều này khi cần thiết để xử lý bất kỳ trường hợp đặc biệt nào nhưng điều này hoạt động cho nhu cầu của tôi. Hi vọng điêu nay co ich!


9

Bạn có thể sử dụng mã scala, tương thích với java và cho phép các chuỗi đa dòng kèm theo "" ":

package foobar
object SWrap {
  def bar = """John said: "This is
  a test
  a bloody test,
  my dear." and closed the door.""" 
}

(lưu ý các trích dẫn bên trong chuỗi) và từ java:

String s2 = foobar.SWrap.bar ();

Liệu điều này có thoải mái hơn không ...?

Một cách tiếp cận khác, nếu bạn thường xử lý văn bản dài, được đặt trong mã nguồn của bạn, có thể là một tập lệnh, lấy văn bản từ một tệp bên ngoài và bao bọc nó dưới dạng một chuỗi nhiều dòng như thế này:

sed '1s/^/String s = \"/;2,$s/^/\t+ "/;2,$s/$/"/' file > file.java

để bạn có thể cắt và dán nó dễ dàng vào nguồn của mình.


8

Bạn có thể nối các phần phụ của mình theo một phương thức riêng như:

public static String multilineString(String... lines){
   StringBuilder sb = new StringBuilder();
   for(String s : lines){
     sb.append(s);
     sb.append ('\n');
   }
   return sb.toString();
}

Dù bằng cách nào, thích StringBuilderký hiệu cộng.


5
Tại sao tôi thích StringBuilder hơn ký hiệu cộng?
Skiphoppy

10
Hiệu quả, hay đúng hơn là một nỗ lực thường xuyên sai lầm về nó.
Michael Myers

2
Tôi nghĩ rằng nỗ lực về hiệu quả dựa trên thực tế là trình biên dịch Java thực hiện toán tử nối chuỗi bằng StringBuilder (StringBuffer trong trình biên dịch trước 1.5). Có một bài viết cũ, nhưng nổi tiếng nói rằng có những lợi ích về hiệu suất trong các tình huống nhất định để sử dụng StringBuffer (hoặc StringBuilder, bây giờ). Đây là liên kết: java.sun.com/developer/JDCTechTips/2002/tt0305.html
Paul Morie

4
Chỉ khi trình biên dịch không thể làm điều đó. Đối với chữ và hằng, nếu bạn sử dụng dấu cộng, việc ghép được thực hiện tại thời gian biên dịch. Việc sử dụng StringBuilder buộc nó xảy ra trong thời gian chạy, do đó, nó không chỉ làm việc nhiều hơn mà còn chậm hơn.
johncip

7

Trên thực tế, sau đây là thực hiện sạch nhất tôi đã thấy cho đến nay. Nó sử dụng một chú thích để chuyển đổi một nhận xét thành một biến chuỗi ...

/**
  <html>
    <head/>
    <body>
      <p>
        Hello<br/>
        Multiline<br/>
        World<br/>
      </p>
    </body>
  </html>
  */
  @Multiline
  private static String html;

Vì vậy, kết quả cuối cùng là html biến chứa chuỗi multiline. Không dấu ngoặc kép, không dấu cộng, không dấu phẩy, chỉ là chuỗi thuần túy.

Giải pháp này có sẵn tại URL sau ... http://www.adrianwalker.org/2011/12/java-multiline-opes.html

Mong rằng sẽ giúp!


Bộ xử lý chú thích đó cần kiểm tra mạnh mẽ hơn,
Tripp Kinetic

tôi thích điều này. Cố gắng nó ra
javadba

7

Xem Stringfier Java . Biến văn bản của bạn thành một khối java StringBuilder thoát nếu cần.


1
Có, bởi vì tôi có thể dành cả đời để sao chép và dán vào trang web đó. Tôi cũng có thể lưu trữ chúng trong một tệp và tải nó nhưng đó cũng không phải là một giải pháp lý tưởng.
mmm

7
    import org.apache.commons.lang3.StringUtils;

    String multiline = StringUtils.join(new String[] {
        "It was the best of times, it was the worst of times ", 
        "it was the age of wisdom, it was the age of foolishness",
        "it was the epoch of belief, it was the epoch of incredulity",
        "it was the season of Light, it was the season of Darkness",
        "it was the spring of hope, it was the winter of despair",
        "we had everything before us, we had nothing before us",
        }, "\n");

6

Một thay thế tôi chưa thấy là câu trả lời là java.io.PrintWriter.

StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
writer.println("It was the best of times, it was the worst of times");
writer.println("it was the age of wisdom, it was the age of foolishness,");
writer.println("it was the epoch of belief, it was the epoch of incredulity,");
writer.println("it was the season of Light, it was the season of Darkness,");
writer.println("it was the spring of hope, it was the winter of despair,");
writer.println("we had everything before us, we had nothing before us");
String string = stringWriter.toString();

Ngoài ra thực tế java.io.BufferedWritercó một newLine()phương pháp là không đề cập.


5

Nếu bạn thích ổi của google nhiều như tôi, nó có thể mang lại một đại diện khá sạch sẽ và một cách dễ dàng, dễ dàng để không mã hóa các ký tự dòng mới của bạn:

String out = Joiner.on(newline).join(ImmutableList.of(
    "line1",
    "line2",
    "line3"));

5

Sử dụng Properties.loadFromXML(InputStream) . Không cần libs bên ngoài.

Tốt hơn là một mã lộn xộn (vì khả năng bảo trì và thiết kế là mối quan tâm của bạn), tốt nhất không nên sử dụng các chuỗi dài.

Bắt đầu bằng cách đọc thuộc tính xml:

 InputStream fileIS = YourClass.class.getResourceAsStream("MultiLine.xml");
 Properties prop = new Properies();
 prop.loadFromXML(fileIS);


sau đó bạn có thể sử dụng chuỗi đa dòng của mình theo cách dễ bảo trì hơn ...

static final String UNIQUE_MEANINGFUL_KEY = "Super Duper UNIQUE Key";
prop.getProperty(UNIQUE_MEANINGFUL_KEY) // "\n    MEGA\n   LONG\n..."


MultiLine.xml` được đặt trong cùng thư mục YourClass:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<properties>
    <entry key="Super Duper UNIQUE Key">
       MEGA
       LONG
       MULTILINE
    </entry>
</properties>

PS.: Bạn có thể sử dụng <![CDATA["... "]]>cho chuỗi giống xml.


Vâng, đây là những gì tôi sử dụng là tốt, giải pháp tuyệt vời! Di chuyển SQL hoặc XML vào một tệp thuộc tính XML bên ngoài. Nó không làm rối mã lên. :)
Laszlo Lugosi

Điều này không trả lời câu hỏi. theo định nghĩa của heredoc là trong tập tin . Vấn đề là giữ nó ở một nơi.
javadba

5

Với bản dựng truy cập sớm JDK / 12 # 12 , giờ đây người ta có thể sử dụng các chuỗi đa dòng trong Java như sau:

String multiLine = `First line
    Second line with indentation
Third line
and so on...`; // the formatting as desired
System.out.println(multiLine);

và kết quả này trong đầu ra sau:

First line
    Second line with indentation
Third line
and so on...

Chỉnh sửa: Đã hoãn lên java 13


1
Đây là một cách để dùng thử bằng cách sử dụng maven
Naman

2
Như cybersoft nói trên bình luận khác, chuỗi ký tự thô (JEP326) đã bị xóa khỏi JDK12 cuối cùng, nhưng một JEP khác đã được tạo để thêm "Khối văn bản" có thể được thực hiện dưới dạng xem trước trong JDK 13
Manuel Romeiro

4

Một giải pháp độc lập nền tảng và hiệu quả sẽ sử dụng thuộc tính hệ thống cho các dấu tách dòng và lớp StringBuilder để xây dựng chuỗi:

String separator = System.getProperty("line.separator");
String[] lines = {"Line 1", "Line 2" /*, ... */};

StringBuilder builder = new StringBuilder(lines[0]);
for (int i = 1; i < lines.length(); i++) {
    builder.append(separator).append(lines[i]);
}
String multiLine = builder.toString();

4

Một lựa chọn tốt.

import static some.Util.*;

    public class Java {

        public static void main(String[] args) {

            String sql = $(
              "Select * from java",
              "join some on ",
              "group by"        
            );

            System.out.println(sql);
        }

    }


    public class Util {

        public static String $(String ...sql){
            return String.join(System.getProperty("line.separator"),sql);
        }

    }

4

Đây là một câu hỏi rất phổ biến, vì vậy tôi quyết định biến câu trả lời này thành một bài viết .

Java 13 và hơn thế nữa

Chuỗi Multiline hiện được hỗ trợ trong Java thông qua Khối văn bản . Trong Java 13 và 14, tính năng này yêu cầu bạn đặt ––enable–previewtùy chọn khi xây dựng và chạy dự án của bạn. Kiểm tra tài liệu Java này để biết thêm chi tiết.

Bây giờ, trước Java 13, đây là cách bạn viết truy vấn:

List<Tuple> posts = entityManager
.createNativeQuery(
    "SELECT *\n" +
    "FROM (\n" +
    "    SELECT *,\n" +
    "           dense_rank() OVER (\n" +
    "               ORDER BY \"p.created_on\", \"p.id\"\n" +
    "           ) rank\n" +
    "    FROM (\n" +
    "        SELECT p.id AS \"p.id\",\n" +
    "               p.created_on AS \"p.created_on\",\n" +
    "               p.title AS \"p.title\",\n" +
    "               pc.id as \"pc.id\",\n" +
    "               pc.created_on AS \"pc.created_on\",\n" +
    "               pc.review AS \"pc.review\",\n" +
    "               pc.post_id AS \"pc.post_id\"\n" +
    "        FROM post p\n" +
    "        LEFT JOIN post_comment pc ON p.id = pc.post_id\n" +
    "        WHERE p.title LIKE :titlePattern\n" +
    "        ORDER BY p.created_on\n" +
    "    ) p_pc\n" +
    ") p_pc_r\n" +
    "WHERE p_pc_r.rank <= :rank\n",
    Tuple.class)
.setParameter("titlePattern", "High-Performance Java Persistence %")
.setParameter("rank", 5)
.getResultList();

Nhờ Khối văn bản Java 13, bạn có thể viết lại truy vấn này như sau:

List<Tuple> posts = entityManager
.createNativeQuery("""
    SELECT *
    FROM (
        SELECT *,
               dense_rank() OVER (
                   ORDER BY "p.created_on", "p.id"
               ) rank
        FROM (
            SELECT p.id AS "p.id",
                   p.created_on AS "p.created_on",
                   p.title AS "p.title",
                   pc.id as "pc.id",
                   pc.created_on AS "pc.created_on",
                   pc.review AS "pc.review",
                   pc.post_id AS "pc.post_id"
            FROM post p
            LEFT JOIN post_comment pc ON p.id = pc.post_id
            WHERE p.title LIKE :titlePattern
            ORDER BY p.created_on
        ) p_pc
    ) p_pc_r
    WHERE p_pc_r.rank <= :rank
    """,
    Tuple.class)
.setParameter("titlePattern", "High-Performance Java Persistence %")
.setParameter("rank", 5)
.getResultList();

Dễ đọc hơn nhiều, phải không?

Hỗ trợ IDE

IntelliJ IDEA cung cấp hỗ trợ để chuyển đổi các Stringkhối kết nối kế thừa sang Stringđịnh dạng đa dòng mới :

Hỗ trợ khối văn bản IntelliJ IDEA

JSON, HTML, XML

Đa dòng String đặc biệt hữu ích khi viết JSON, HTML hoặc XML.

Xem xét ví dụ này bằng cách sử dụng Stringphép nối để xây dựng chuỗi JSON bằng chữ:

entityManager.persist(
    new Book()
    .setId(1L)
    .setIsbn("978-9730228236")
    .setProperties(
        "{" +
        "   \"title\": \"High-Performance Java Persistence\"," +
        "   \"author\": \"Vlad Mihalcea\"," +
        "   \"publisher\": \"Amazon\"," +
        "   \"price\": 44.99," +
        "   \"reviews\": [" +
        "       {" +
        "           \"reviewer\": \"Cristiano\", " +
        "           \"review\": \"Excellent book to understand Java Persistence\", " +
        "           \"date\": \"2017-11-14\", " +
        "           \"rating\": 5" +
        "       }," +
        "       {" +
        "           \"reviewer\": \"T.W\", " +
        "           \"review\": \"The best JPA ORM book out there\", " +
        "           \"date\": \"2019-01-27\", " +
        "           \"rating\": 5" +
        "       }," +
        "       {" +
        "           \"reviewer\": \"Shaikh\", " +
        "           \"review\": \"The most informative book\", " +
        "           \"date\": \"2016-12-24\", " +
        "           \"rating\": 4" +
        "       }" +
        "   ]" +
        "}"
    )
);

Bạn hầu như không thể đọc JSON do các ký tự thoát và sự phong phú của dấu ngoặc kép và dấu cộng.

Với Khối văn bản Java, đối tượng JSON có thể được viết như thế này:

entityManager.persist(
    new Book()
    .setId(1L)
    .setIsbn("978-9730228236")
    .setProperties("""
        {
           "title": "High-Performance Java Persistence",
           "author": "Vlad Mihalcea",
           "publisher": "Amazon",
           "price": 44.99,
           "reviews": [
               {
                   "reviewer": "Cristiano",
                   "review": "Excellent book to understand Java Persistence",
                   "date": "2017-11-14",
                   "rating": 5
               },
               {
                   "reviewer": "T.W",
                   "review": "The best JPA ORM book out there",
                   "date": "2019-01-27",
                   "rating": 5
               },
               {
                   "reviewer": "Shaikh",
                   "review": "The most informative book",
                   "date": "2016-12-24",
                   "rating": 4
               }
           ]
        }
        """
    )
);

Kể từ khi tôi sử dụng C # vào năm 2004, tôi đã muốn có tính năng này trong Java và cuối cùng chúng tôi đã có nó.


3

Xác định chuỗi của tôi trong một tệp thuộc tính?

Chuỗi đa dòng không được phép trong các tệp thuộc tính. Bạn có thể sử dụng \ n trong các tệp thuộc tính, nhưng tôi không nghĩ đó là một giải pháp trong trường hợp của bạn.


Giá trị trong tệp thuộc tính có thể trải rộng trên nhiều dòng: Chỉ cần kết thúc tất cả các dòng nhưng cuối cùng bằng dấu gạch chéo ngược. Điều này không để lại vấn đề về những gì bạn sử dụng làm dấu tách dòng, vì đây là nền tảng cụ thể. Tôi cho rằng bạn có thể sử dụng một \ n đơn giản và sau đó trong mã của bạn, sau khi đọc thuộc tính, hãy thực hiện tìm kiếm và thay thế \ n thành line.separator. Điều đó có vẻ hơi ít, nhưng tôi đoán bạn có thể viết một hàm lấy một thuộc tính và thực hiện thao tác này cùng một lúc. Chà, tất cả những gì giả định rằng bạn sẽ viết những chuỗi này vào một tệp, đó là một giả định lớn.
Jay


3

Tôi đề nghị sử dụng một tiện ích theo đề xuất của ThomasP, và sau đó liên kết nó vào quá trình xây dựng của bạn. Một tệp bên ngoài vẫn có mặt để chứa văn bản, nhưng tệp không được đọc khi chạy. Quy trình làm việc là:

  1. Xây dựng tiện ích 'textfile to java code' và kiểm tra phiên bản
  2. Trên mỗi bản dựng, hãy chạy tiện ích đối với tệp tài nguyên để tạo nguồn java đã sửa đổi
  3. Nguồn Java chứa một tiêu đề như class TextBlock {... theo sau bởi một chuỗi tĩnh được tạo tự động từ tệp tài nguyên
  4. Xây dựng tệp java được tạo với phần còn lại của mã của bạn

2

Khi một chuỗi dài + được sử dụng, chỉ có một StringBuilder được tạo, trừ khi String được xác định tại thời điểm biên dịch trong trường hợp không sử dụng StringBuilder!

Thời gian duy nhất StringBuilder hiệu quả hơn là khi nhiều câu lệnh được sử dụng để xây dựng Chuỗi.

String a = "a\n";
String b = "b\n";
String c = "c\n";
String d = "d\n";

String abcd = a + b + c + d;
System.out.println(abcd);

String abcd2 = "a\n" +
        "b\n" +
        "c\n" +
        "d\n";
System.out.println(abcd2);

Lưu ý: Chỉ có một StringBuilder được tạo.

  Code:
   0:   ldc     #2; //String a\n
   2:   astore_1
   3:   ldc     #3; //String b\n
   5:   astore_2
   6:   ldc     #4; //String c\n
   8:   astore_3
   9:   ldc     #5; //String d\n
   11:  astore  4
   13:  new     #6; //class java/lang/StringBuilder
   16:  dup
   17:  invokespecial   #7; //Method java/lang/StringBuilder."<init>":()V
   20:  aload_1
   21:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   24:  aload_2
   25:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   28:  aload_3
   29:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   32:  aload   4
   34:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   37:  invokevirtual   #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   40:  astore  5
   42:  getstatic       #10; //Field java/lang/System.out:Ljava/io/PrintStream;
   45:  aload   5
   47:  invokevirtual   #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   50:  ldc     #12; //String a\nb\nc\nd\n
   52:  astore  6
   54:  getstatic       #10; //Field java/lang/System.out:Ljava/io/PrintStream;
   57:  aload   6
   59:  invokevirtual   #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   62:  return

Để làm rõ hơn câu hỏi của tôi, tôi không quan tâm đến hiệu suất. Tôi quan tâm đến vấn đề bảo trì và thiết kế.

Làm cho nó rõ ràng và đơn giản như bạn có thể.

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.