Java çok satırlı dize


516

Perl geliyor, eminim kaynak kodunda çok satırlı bir dize oluşturma "here-document" araçlarını eksik:

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

Java'da, çok satırlı dizimi sıfırdan birleştirdiğim için her satırda hantal tırnaklar ve artı işaretlerim olması gerekiyor.

Daha iyi alternatifler nelerdir? Dizgimi özellikler dosyasında tanımla?

Düzenleme : İki cevap StringBuilder.append () artı gösterimi tercih söylüyorlar. Herkes neden böyle düşündüğünü açıklayabilir mi? Benim için daha fazla tercih edilmiyor. Ben çok yollu dizeleri birinci sınıf bir dil yapısı değil aslında etrafında bir yol arıyorum, kesinlikle yöntem çağrıları ile birinci sınıf bir dil yapısı (dize birleştirme artı) yerine istemiyorum anlamına gelir.

Edit : Sorum daha açıklamak için, ben hiç performans endişe değilim. Sürdürülebilirlik ve tasarım konularından endişeliyim.


12
StringBuilder.append (), bir dizeye art arda eklerken artı olarak tercih edilir, çünkü her yaptığınızda string1 + string2yeni bir dize nesnesi ayırırsınız ve her iki giriş dizesindeki karakterleri kopyalarsınız. N Dizeleri birlikte ekliyorsanız, n-1 ayırmaları ve yaklaşık olarak (n ^ 2) / 2 karakter kopyası yaparsınız. Öte yandan, StringBuilder daha az kopyalar ve yeniden tahsis eder (yine de dahili arabellek boyutunu aştığınızda yine de yapar). Teorik olarak, derleyicinin StringBuilder'ı kullanmak için + dönüştürebildiği ancak pratikte kimin bildiği durumlar vardır.
Laurence Gonsalves

5
Hata ayıklayıcıya her atladığımda, Java 1.5'te + bir StringBuilder.append () çağrısına dönüştürülür. Meslektaşlarım karıştı diyorum ki onlar çağırmak ve orada rüzgar görünmüyor kodu içine hata ayıklama beri StringBuilder bir hata var.
skiphoppy


61
"Abc \ n" + "def \ n" vb. 'Den oluşan bir dize değişmezinin StringBuilder kullanmadığını unutmayın: derleyici bunları birbirine yapıştırır ve .class dosyasına diğer türlerle aynı şekilde tek bir değişmez olarak koyar. sabit katlama.
araqnid

6
Çoğu IDE çok satırlı dizelerin girilmesini destekler. yani. İstediğiniz şeyi bir "" dizesine yazmanız veya yapıştırmanız yeterlidir. İsterseniz \ n ve "+" ekler. Örneğin 40 satırlık metni bir String'e yapıştırabilirim ve IDE bunu sizin için sıralar.
Peter Lawrey

Yanıtlar:


118

Stephen Colebourne, Java 7'de çok satırlı dizeler eklemek için bir teklif oluşturdu .

Ayrıca, Groovy zaten çok satırlı dizeleri destekliyor .


14
Java geliştirmeleri için Project Coin işlemi, mail.openjdk.java.net/pipermail/coin-dev/2009-February/… çok satırlı dizelerini içeriyordu . Oracle blogs.sun.com/darcy/entry/project_coin_final_five tarafından reddedildi .
JodaStephen

8
2012'de herhangi bir değişiklik var mı?
Ilia G

13
Ne yazık ki bu şartnameye yapmış gibi görünmüyor.
namuol

3
Blogs.sun.com bağlantısı koptu, ancak içeriğin şimdi blogs.oracle.com/darcy/entry/project_coin_final_five adresinde olduğunu düşünüyorum .
Donal Fellows

8
Ocak 2018'den itibaren topluluk çok satırlı dizeleri yeniden düşünüyor gibi görünüyor. openjdk.java.net/jeps/326
Shane Gannon

485

Java'da bulunmayan çok satırlı bir hazır bilgi yapmak istediğiniz gibi görünüyor.

En iyi alternatifiniz sadece bir +arada olan dizeler olacak . Kullanıcıların bahsettiği diğer bazı seçenekler (StringBuilder, String.format, String.join) yalnızca bir dizi dizeyle başlarsanız tercih edilir.

Bunu düşün:

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

Karşı 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();

Karşı 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"
);

Java8'e karşı 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"
);

Eğer kullanımına, ya gerek belli bir sistem için yeni satır istiyorsanız System.lineSeparator()veya kullanabilir %niçinde String.format.

Başka bir seçenek, kaynağı bir metin dosyasına koymak ve sadece dosyanın içeriğini okumaktır. Bu, sınıf dosyalarınızı gereksiz yere şişirmemek için çok büyük dizeler için tercih edilir.


246
Ayrıca, tüm dizeler derleme zamanında bilindiğinden, ilk sürüm derleyici tarafından otomatik olarak birleştirilecektir. Dizeler derleme zamanında bilinmese bile, StringBuilder veya String.format () 'dan daha yavaş değildir. + İle birleştirmeyi engellemenin tek nedeni, bunu bir döngü içinde yapmanızdır.
Michael Myers

23
Sürümle ilgili sorun String.format, formatın satır sayısı ile senkronize tutulması gerektiğidir.
Bart van Heukelom

4
String.format diğer iki örneğe göre verimli değildir
cmcginty

10
Bu cevap eldeki soruya çok uygun olmayan bir çözümdür. Kopyalamak ve yapıştırmak istediğimiz 2000 satır SAS makrosu veya 200 satır SQL sorgusu demetimiz var. Bu çok satırlı metni StringBuffer eklerine dönüştürmek için + "" concat kullandığımızı öne sürmek saçma.
Blessed Geek

21
@BlessedGeek: eldeki soru, Java dilinde hangi seçeneklerin mevcut olduğu hakkındaydı. Dizeye giren veri türü hakkında hiçbir şeyden bahsetmedi. Daha iyi bir çözüm varsa, bunu bir cevap olarak gönderebilirsiniz. Gibi geliyor Josh Curren çözümü sizin durumunuz için daha iyi olurdu. Dilin çok satırlı değişmezleri desteklememesi üzüldüyse, burası şikayet etmek için yanlış yerdir.
Kip

188

Eclipse'de "Bir dize hazır bilgisine yapıştırırken metinden kaç" seçeneğini açarsanız (Tercihler> Java> Editör> Yazma) ve tırnak işaretleri arasına çok çizgili bir dize yapıştırırsanız, otomatik olarak " ve \n" +tüm satırlarınız için .

String str = "paste your text here";

15
Yapıştırma işlemini intelij aynı zamanda "" s içine varsayılan olarak yapar
Bob B

Genelde \rEclipse'nin Windows'a koyduğu s'de mi kalıyorsunuz?
Noumenon

99

Bu eski bir iş parçacığıdır, ancak yeni bir zarif çözüm (sadece 4 belki 3 küçük dezavantajı olan) özel bir ek açıklama kullanmaktır.

Kontrol edin: http://www.adrianwalker.org/2011/12/java-multiline-string.html

Bu çalışmadan esinlenen bir proje GitHub'da barındırılıyor:

https://github.com/benelog/multiline

Java kodu örneği:

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

Dezavantajları

  1. karşılık gelen (sağlanan) ek açıklama işlemcisini etkinleştirmeniz gerekir.
  2. Dize değişkeni yerel değişken olarak tanımlanamıyor Ham Dize Değişmezlerini Denetle projesi değişken olarak tanımlanamıyor Değişkenleri yerel değişkenler olarak tanımlayabileceğiniz
  3. Bu String XML değişmezine sahip Visual Basic .Net'teki diğer değişkenleri içeremez<%= variable %> ) :-) içeremez
  4. Dize değişmezinin JavaDoc yorumu tarafından sınırlandırıldığı (/ **)

Ve muhtemelen Eclipse / Intellij-Idea'yı Javadoc yorumlarınızı otomatik olarak yeniden biçimlendirmeyecek şekilde yapılandırmanız gerekir.

Biri bu garip bulabilir (Javadoc yorumları yorumlardan başka bir şey gömmek için tasarlanmamıştır), ancak Java'daki çok satırlı dize eksikliği sonunda gerçekten can sıkıcı olduğundan, bunu en kötü çözüm olarak görüyorum.


Bu, çok satırlı dizeyi kullanan sınıfın final olmasını gerektiriyor mu? Ayrıca, Eclipse'den kod geliştirirken ve çalıştırırken herhangi bir kurulum gerekli mi? Referans URL, ek açıklama işleme için Maven için kurulum gereksinimlerinden bahsediyor. Eclipse'de neye ihtiyaç duyulabileceğini bulamıyorum.
David

Ek açıklama yaşanabilir - ancak maven'e de sert bir bağımlılık olduğu anlaşılıyor mu? Bu bölüm, küçük metin parçalarının yönetimini basitleştirecek olan yorumlu metinlerin değerini büyük ölçüde ortadan kaldırır.
javadba

3
Bunu tamamen tutulma ile yapabilirsiniz. @SRG'nin yukarıda yayınladığı bağlantı sizi bu bağlantıya yönlendirir . Tutulma kullanıyorsanız, bir dakikalık kurulum ve çalışıyor.
Michael Plautz

4
Bu muhtemelen şimdiye kadar gördüğüm en büyük kesmek. EDIT: Boşver ... bkz. Bob Albrights cevap.
Llew Vallis

1
Bu projenin bir uzantısını yerel değişkenlerin desteklendiği yeni bir tane oluşturdum , projeye bir göz atın
deFreitas

62

Başka bir seçenek, uzun dizeleri harici bir dosyada saklamak ve dosyayı bir dizeye okumak olabilir.


13
Kesinlikle. Büyük miktarda metin Java kaynağına ait değildir; Class.getResource (String) çağrısı yoluyla yüklenen uygun bir biçimdeki kaynak dosyasını kullanın.
erickson

5
Sağ! I18N metnini kolayca yüklemek için Locale + ResourceBundle öğelerini de kullanabilirsiniz ve sonra String.format () çağrısı "\ n" 'ları yeni satırlar olarak ayrıştırır. Örnek: String readyStr = String.parse (resourceBundle.getString (" Giriş"));
ATorras

62
Bir dizgiyi çok satırlı olduğu için harici hale getirmeniz gerekmez. Yorumları içeren birden çok satıra ayrılmak istediğim bir normal ifadem varsa ne olur? Java'da çirkin görünüyor. @C # sözdizimi daha temiz.
Jeremy Stein

8
Skiphoppy sadece bir paragraf uzunluğu dize sabiti kullanmak için dosyalar ile uğraşma yükü ile uğraşmak istemiyor. İstediğim kaynak koduma gömülü C ++ 'da çok satırlı dizeler kullanıyorum.
Tim Cooper

9
Vay. C ++ bu konuda Java aslında daha iyi olduğuna inanamıyorum! Çok satırlı dize sabitlerini seviyorum ve bazı durumlarda kaynaklara aitler.
Kullanıcı1

59

Bu, ne yaptığını düşünmeden asla kullanmamanız gereken bir şey . Ancak bir kerelik komut dosyaları için bunu büyük bir başarıyla kullandım:

Misal:

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

Kod:

// 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
Sınıf için Java kodunun son ikili dosya ile gönderilmesini gerektirir. Hmm.
Thorbjørn Ravn Andersen

23
Ben böyle bir şey kontrol etmeye çalışırken iş arkadaşlarım tepki hayal edebiliyorum ...
Landon Kuhn

15
+1. Oy kullanan kişilerin hayal gücü eksikliği var. Bu, küçük yardımcı programları, test senaryolarını ve hatta kontrollü ürün ortamlarını yazmak için yararlı bir yapıdır. Bu java ruby ​​/ python / etc içine bırakarak veya burada kalıyorum arasında bir fark üreticisi.
javadba

1
Harika bir çözüm, ancak ne yazık ki android için çalışmayacak çünkü emülatör veya gerçek cihazda yürütülecek ve orada kaynak kodu yok.
evgeny.myasishchev

Belki bir Java 8 prob, ya da başka bir şey, ama örnekteki classLoader mevcut değil. MyClass.class.getResourceAsStream (...) kullanarak denedim, ama her zaman null döndürür. Test için harika bir hızlı çözüm olurdu!
Nick

54

String.join

Java 8 java.lang.String, biraz daha iyi bir alternatif sunan yeni bir statik yöntem ekledi :

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

Kullanma:

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

5
Düzgün ve temiz bir çözüm! IDE ve önişlemciye bağımlılık yok! Hiçbir kılavuza "\n"gerek yoktur ve taşınabilirliğin farkındadır!
Siu Ching Pong -Asuka Kenji-

1
Yorumumun işe yaramaz olduğunu anlıyorum, ancak çok satırlı bir dize hazır bilgisi gibi temel bir şey için hack aramak çok geciktirildi. Neden hala java bunu spesifikasyona ekleyemiyor?
dmitry


19

Dizelerinizi bir özellikler dosyasında tanımlarsanız çok daha kötü görünür. IIRC, şöyle görünecektir:

string:text\u000atext\u000atext\u000a

Genelde büyük dizeleri kaynağa yerleştirmemek makul bir fikirdir. Bunları kaynak olarak, belki XML veya okunabilir bir metin biçiminde yüklemek isteyebilirsiniz. Metin dosyaları çalışma zamanında okunabilir veya Java kaynağında derlenebilir. Eğer onları kaynağa yerleştirirseniz +, ön tarafa koymanızı ve gereksiz yeni satırları atlamayı öneririm :

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

Yeni satırlarınız varsa, birleştirme veya biçimlendirme yönteminden bazılarını isteyebilirsiniz:

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

17

Artılar, her iki dizenin de sabit olması dışında derleyicinin bunları derleme zamanında birleştirebilmesi dışında StringBuilder.append biçimine dönüştürülür. En azından, Sun'ın derleyicisinde böyle ve diğer tüm derleyiciler de aynısını yapmasa bile çoğundan şüphelenirim.

Yani:

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

normalde tam olarak aynı kodu üretir:

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

Diğer yandan:

String c="Hello"+"Goodbye";

aynıdır:

String c="HelloGoodbye";

Yani, dize değişmezlerinizi birden fazla satır boyunca okunabilirlik için artı işaretleriyle kırmanın herhangi bir cezası yoktur.


4
teknik olarak, ilk örnekte daha çok benzer bir şey üretir: String c = new StringBuilder (). append (a) .append (b) .toString (); Aradaki fark, geçici dize oluşturucunun kapsam dışında olması ve String c = ... satırından hemen sonra çöp toplama için uygun olması, "temp" string oluşturucusunun biraz daha uzun süre kalmasıdır.
Kip

Doğru. Demek istediğim, bir fonksiyonun çalışma zamanında çağrılması ile işin derleme zamanında ne zaman yapılabileceğini ayırt etmektir. Ama haklısın.
Jay

15

IntelliJ IDE'de şunları yazmanız gerekir:

""

Ardından imlecinizi tırnak işaretleri içine alın ve dizenizi yapıştırın. IDE bunu birden çok birleştirilmiş satıra genişletir.


11

Ne yazık ki Java'nın çok satırlı dize değişmez değerleri yok. Dize değişmezlerini birleştirmelisiniz (+ veya StringBuilder kullanarak bunun en yaygın iki yaklaşımıdır) veya dizeyi ayrı bir dosyadan okumalısınız.

Büyük çok satırlı dize değişmezleri için, ayrı bir dosya kullanmaya ve bunu kullanırken okumaya meyilli olurum getResourceAsStream() (Class sınıfın . Bu, kodun kurulu olduğu yere karşı geçerli dizin hakkında endişelenmenize gerek olmadığından dosyayı bulmanızı kolaylaştırır. Aynı zamanda ambalajı da kolaylaştırır, çünkü dosyayı jar dosyanızda saklayabilirsiniz.

Diyelim ki Foo adında bir sınıftasınız. Sadece böyle bir şey yapın:

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

Diğer bir sıkıntı, Java'nın standart bir "bu Reader'daki metnin tamamını bir String'e oku" yöntemine sahip olmamasıdır. Yine de yazmak oldukça kolay:

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

Ben de aynısını yaparım. Commons-io dosyasını dosyanın içeriğini daha kolay okumak için kullanabilirsiniz ("FileUtils.readFileToString (Dosya dosyası)" ile).
SRG

Java hakkında artık standart değil tüm metin yöntemini okumak için doğru değil ... - Java 7'den beri Files.readAllLines (Yol)
ccpizza

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

Ancak, en iyi alternatif String.format kullanmaktır

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

Benim düşüncem, artı işaretlerini ve tırnak işaretlerini kaldırması, özellikle sadece 3 satırdan fazla olduğunda daha okunabilir hale getirmesidir. Ama String.format kadar iyi değil.
Tom,

2
Stringbuilder örneği en azından okunamıyor. Ayrıca, "\ n" nin her zaman yeni satır olmadığını, ancak linux ve unix makineleri için iyi olduğunu unutmayın.
Stefan Thyberg

Ayrıca, StringBuilder'ın varlığından bahsetmek istedim.
Tom,

4
Bir artı işaretini altı karakterli bir yöntem adı ve parantez ile değiştirmek benim için daha okunabilir görünmüyor, ancak görünüşe göre bu şekilde düşünen tek kişi sen değilsin. Yine de tırnak işaretleri kaldırmaz. Hala oradalar.
skiphoppy

9

Java çok satırlı dizeleri yerel olarak desteklemediğinden (şimdilik), şimdilik tek yol, yukarıda belirtilen tekniklerden birini kullanarak onu kesmek. Yukarıda belirtilen püf noktaları kullanarak aşağıdaki Python betiğini oluşturdum:

import sys
import string
import os

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

Bunu javastringify.py adlı bir dosyaya ve dizenizi mystring.txt dosyasına koyun ve aşağıdaki gibi çalıştırın:

cat mystring.txt | python javastringify.py

Daha sonra çıktıyı kopyalayıp düzenleyicinize yapıştırabilirsiniz.

Herhangi bir özel durumla başa çıkmak için bunu gerektiği gibi değiştirin, ancak bu benim ihtiyaçlarım için işe yarıyor. Bu yardımcı olur umarım!


9

Java ile uyumlu olan ve "" "ile çevrili çok satırlı Dizelere izin veren scala kodunu kullanabilirsiniz:

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

(dizenin içindeki tırnaklara dikkat edin) ve java:

String s2 = foobar.SWrap.bar ();

Bunun daha rahat olup olmadığı ...?

Kaynak kodunuza yerleştirilmesi gereken uzun metinleri sık sık ele alıyorsanız, başka bir yaklaşım, metni harici bir dosyadan alan ve böyle bir çok satırlı java-String olarak saran bir komut dosyası olabilir:

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

böylece kaynağınıza kolayca kesip yapıştırabilirsiniz.


8

Eklerinizi aşağıdaki gibi ayrı bir yöntemle birleştirebilirsiniz:

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

Her iki durumda StringBuilderda, artı gösterimi tercih edin.


5
Neden artı gösterime StringBuilder tercih ederim?
skiphoppy

10
Verimlilik veya daha sıklıkla yanlış yönlendirilen bir girişim.
Michael Myers

2
Verimlilik girişimi, sanırım, Java derleyicisi StringBuilder (1.5 öncesi derleyicilerde StringBuffer) kullanarak dize birleştirme operatörü uyguladığı gerçeğine dayanmaktadır. StringBuffer'ı (veya şimdi StringBuilder) kullanmanın belirli durumlarda performans avantajları olduğunu belirten eski ama iyi bilinen bir makale var. İşte link: java.sun.com/developer/JDCTechTips/2002/tt0305.html
Paul Morie

4
Sadece derleyici bunu yapamadığı zaman. Değişmez değerler ve sabitler için, artı işareti kullanırsanız, derleme sırasında derleme yapılır. Bir StringBuilder kullanmak onu çalışma zamanında olmaya zorlar, bu yüzden sadece daha fazla iş değil, daha yavaştır.
johncip

7

Aslında, şu ana kadar gördüğüm en temiz uygulama. Bir açıklamayı dize değişkenine dönüştürmek için bir ek açıklama kullanır ...

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

Sonuç olarak, html değişkeni çok satırlı dizeyi içerir. Tırnak yok, artı yok, virgül yok, sadece saf dize.

Bu çözüme aşağıdaki URL'den ulaşabilirsiniz ... http://www.adrianwalker.org/2011/12/java-multiline-string.html

Umarım yardımcı olur!


Bu ek açıklama işlemcisinin daha sağlam
Tripp Kinetics

Bunu severim. Dışarı çalışılıyor
javadba

7

Bkz. Java Stringfier . Metninizi gerekirse bir StringBuilder java bloğuna dönüştürür.


1
Evet, çünkü hayatımı kopyalayıp bu siteye yapıştırarak harcayabilirim. Ben de sadece bir dosyada saklamak ve yükleyebilirsiniz ama bu da ideal bir çözüm değil.
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

Henüz cevap olarak görmediğim bir alternatif 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();

Ayrıca java.io.BufferedWriterbir newLine()yönteme sahip olduğu gerçeği de belirtilmemiş.


5

Google'ın guava'sını benim kadar beğendiyseniz, oldukça temiz bir temsil ve yeni satır karakterlerinizi de kodlamamak için güzel ve kolay bir yol sağlayabilir:

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

5

kullanım Properties.loadFromXML(InputStream) . Dış kütüphanelere ihtiyaç yoktur.

Dağınık bir koddan daha iyi (sürdürülebilirlik ve tasarım endişeniz olduğundan) uzun dizeler kullanmamanız tercih edilir.

Xml özelliklerini okuyarak başlayın:

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


çok satırlı dizenizi daha sürdürülebilir bir şekilde kullanabilirsiniz ...

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


MultiLine.xml` aynı klasörde bulunur

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

Not: xml benzeri dize için <![CDATA["... kullanabilirsiniz "]]>.


Evet, kullandığım da bu, harika bir çözüm! SQL veya XML'i harici bir XML özellik dosyasına taşıyın. Kodu bozmaz. :)
Laszlo Lugosi

Bu soruya cevap vermiyor. heredoc dosyaları tanım gereğidir . Mesele, onu tek bir yerde tutmak.
javadba

5

İle JDK / 12 erken erişim yapı # 12 aşağıdaki gibi, bir anda Java satırlı dizeleri kullanabilirsiniz:

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

ve bu aşağıdaki çıktı ile sonuçlanır:

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

Düzenleme: Java 13'e ertelendi



2
Cybersoft'un diğer yorumda söylediği gibi, ham dize değişmez değerleri (JEP326) son JDK12'den kaldırıldı, ancak JDK 13
Manuel Romeiro

4

Oldukça verimli ve platformdan bağımsız bir çözüm, satır ayırıcılar için system özelliğini ve dizeleri oluşturmak için StringBuilder sınıfını kullanmak olacaktır:

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

İyi bir seçenek.

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

Bu çok yaygın bir soru, bu yüzden bu yanıtı bir makaleye dönüştürmeye karar verdim .

Java 13 ve sonrası

Çok Satırlı Dizeler artık Metin Blokları aracılığıyla Java'da desteklenmektedir . Java 13 ve 14'te, bu özellik ––enable–previewprojenizi oluştururken ve çalıştırırken seçeneği belirlemenizi gerektirir . Bu Java belgelerine göz atın fazla ayrıntı için.

Java 13'ten önce, şu şekilde bir sorgu yazarsınız:

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

Java 13 Metin Blokları sayesinde, bu sorguyu aşağıdaki gibi yeniden yazabilirsiniz:

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

Çok daha okunabilir değil mi?

IDE desteği

IntelliJ IDEA, eski Stringbirleştirme bloklarını yeni çok satırlı Stringformata dönüştürmek için destek sağlar :

IntelliJ IDEA Metin Blokları desteği

JSON, HTML, XML

Çok satırlı String özellikle JSON, HTML veya XML yazarken kullanışlıdır.

StringJSON dizgi değişmezi oluşturmak için birleştirme kullanarak bu örneği düşünün :

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

Kaçan karakterler ve çift tırnak ve artı işaretlerinin bolluğu nedeniyle JSON'u zar zor okuyabilirsiniz.

Java Metin Blokları ile JSON nesnesi şu şekilde yazılabilir:

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

2004'te C # kullandığımdan beri, Java'da bu özelliğe sahip olmak istiyordum ve şimdi de sahip olduk.


3

Dizem bir özellikler dosyasında tanımlansın mı?

Özellikler dosyalarında çok satırlı dizelere izin verilmez. Özellikler dosyalarında \ n kullanabilirsiniz, ancak durumunuzda bunun bir çözüm olduğunu düşünmüyorum.


Özellikler dosyasındaki değer birden çok satıra yayılabilir: Son satır hariç tüm satırları ters eğik çizgi ile sonlandırın. Bu, platforma özgü olduğu için hat ayırıcı olarak kullandığınız şeyin sorununu ortadan kaldırır. Basit bir \ n kullanabilirsiniz ve sonra kodunuzda, özelliği okuduktan sonra, line.separator için \ n arama ve değiştirme yapın. Bu biraz kludgey gibi görünüyor, ama sanırım bir özelliği alan ve aynı zamanda bu manipülasyonu yapan bir fonksiyon yazabilirsiniz. Tüm bunlar, bu dizeleri bir dosyaya yazacağınızı varsayar ki bu büyük bir varsayımdır.
Jay


3

ThomasP tarafından önerilen bir yardımcı program kullanmanızı ve ardından bunu oluşturma işleminize bağlamanızı öneririm. Metni içerecek harici bir dosya hala var, ancak dosya çalışma zamanında okunmuyor. Bu durumda iş akışı:

  1. Bir 'java koduna textfile' yardımcı programı oluşturun ve sürüm kontrolüne bakın
  2. Her derlemede, düzeltilmiş bir java kaynağı oluşturmak için yardımcı programı kaynak dosyasına karşı çalıştırın
  3. Java kaynağı aşağıdaki gibi bir başlık içerir class TextBlock {... , kaynak dosyadan otomatik olarak oluşturulan statik bir dize
  4. Kodunuzun geri kalanıyla oluşturulan java dosyasını oluşturun

2

Uzun bir + serisi kullanıldığında, String derleme zamanında belirlenmediği sürece yalnızca bir StringBuilder oluşturulur; bu durumda hiçbir StringBuilder kullanılmaz!

StringBuilder'ın daha verimli olduğu tek zaman, String'i oluşturmak için birden fazla ifade kullanılmasıdır.

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

Not: Yalnızca bir StringBuilder oluşturulur.

  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

Sorumu daha da netleştirmek için performanstan hiç endişe duymuyorum. Sürdürülebilirlik ve tasarım konularından endişeliyim.

Olabildiğince açık ve basit hale getirin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.