Domanda

Provenienti da Perl, sono sicuro che mi manca il "qui-documento" strumenti per la creazione di un multi-linea stringa di codice sorgente:

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

In Java, devo ingombrante preventivi e segni più su ogni linea di concatenare la mia stringa su più linee da zero.

Quali sono alcune alternative migliori?Definire la mia stringa in un file di proprietà?

Modifica:Due risposte dire StringBuilder.append() è preferibile il plus di notazione.Qualcuno potrebbe elaborare il perché la penso così?L'aspetto non è più preferibile per me a tutti.Sto cercando un modo per aggirare il fatto che su più righe stringhe non sono una di prima classe costrutto del linguaggio, il che significa che sicuramente non si desidera sostituire una prima classe di costrutto del linguaggio (concatenazione di stringhe con plus) con chiamate di metodo.

Modifica:Per chiarire la mia domanda ulteriore, io non sono preoccupato per le prestazioni a tutti.Sono preoccupato per la manutenzione e i problemi di progettazione.

È stato utile?

Altri suggerimenti

Sembra che si vuole fare una multilinea letterale, che non esiste in Java.

Il tuo migliore alternativa sta per essere stringhe che sono solo +'d insieme. Alcune altre opzioni persone hanno detto (StringBuilder, String.Format, string.join) sarebbe solo preferibile se si è iniziato con un array di stringhe.

Considerate questo:

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

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

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

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

Se si desidera che la nuova riga per il sistema particolare, vi sia bisogno di usare System.getProperty("line.separator"), oppure è possibile utilizzare %n in String.format.

Un'altra opzione è quella di mettere la risorsa in un file di testo, e basta leggere il contenuto di quel file. Questo sarebbe preferibile per molto stringhe di grandi dimensioni per evitare inutilmente gonfiore i file di classe.

In Eclipse, se si attiva l'opzione "Escape testo quando si incolla in una stringa letterale" (in Preferenze> Java> Editor> battitura) e incollare una stringa multi-foderato whithin citazioni, si aggiungerà automaticamente " e \n" + per tutti le linee.

String str = "paste your text here";

Questo è un vecchio thread, ma una nuova soluzione piuttosto elegante (con solo 4 forse 3 piccoli inconvenienti) è quello di utilizzare un'annotazione personalizzata.

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

Un progetto ispirato da quel lavoro è ospitato su GitHub:

https://github.com/benelog/multiline

Esempio di codice 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);
  }
}

Gli svantaggi sono

  1. che si deve attivare il corrispondente (in dotazione) annotazione processore.
  2. quella variabile stringa non può essere definita come controllare la variabile locale Raw stringa letterali progetto in cui è possibile definire variabili come variabili locali
  3. che stringa non può contenere altre variabili come in Visual Basic .NET con letterale XML (<%= variable %>): -)
  4. la stringa letterale è delimitato da un commento JavaDoc (/ **)

E probabilmente necessario configurare Eclipse / IntelliJ Idea di non riformattare automaticamente i commenti Javadoc.

Si può trovare questo strano (commenti Javadoc non sono progettati per incorporare qualcosa di diverso da commenti), ma come questa mancanza di stringa multilinea in Java è davvero fastidioso, alla fine, trovo che questa sia la soluzione meno peggiore.

Un'altra opzione potrebbe essere quella di memorizzare lunghe stringhe in un file esterno e leggere il file in una stringa.

Questo è qualcosa che si dovrebbe non uso senza pensare a quello che sta facendo. Ma per gli script una tantum Ho usato questo con grande successo:

Esempio:

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

Codice:

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

String.join

Java 8 ha aggiunto un nuovo metodo statico a java.lang.String che offre un po 'migliore alternativa:

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

Con esso:

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

Se si definiscono le stringhe in un file delle proprietà sembrerà molto peggio. IIRC, sembrerà come:

string:text\u000atext\u000atext\u000a

In generale è un'idea ragionevole non incorporare stringhe di grandi dimensioni per fonte. Si potrebbe desiderare di caricarli come risorse, magari in XML o un formato di testo leggibile. I file di testo possono essere lette sia in fase di esecuzione o compilate in sorgente Java. Se si finisce inserendoli nella fonte, vi suggerisco di mettere il + nella parte anteriore e omettendo nuove linee inutili:

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

Se si dispone di nuove linee, si potrebbe desiderare alcuni di aderire o metodo di formattazione:

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

Lati positivi vengono convertiti in StringBuilder.append, tranne quando entrambe le stringhe sono costanti in modo che il compilatore li può combinare in fase di compilazione. Almeno, è così che è in compilatore di Sun, e ho il sospetto maggior parte se non tutti gli altri compilatori avrebbero fatto lo stesso.

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

normalmente genera esattamente lo stesso codice:

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

D'altra parte:

String c="Hello"+"Goodbye";

è lo stesso:

String c="HelloGoodbye";

Cioè, non c'è nessuna penalità a rompere i tuoi letterali stringa su più righe con il segno più per migliorare la leggibilità.

Nel IntelliJ IDE è sufficiente digitare:

""

Poi posizionare il cursore all'interno delle virgolette e incollare la stringa. L'IDE si espanderà in più righe concatenate.

PEC 355: blocchi di testo (Anteprima) mira a coprire questa funzionalità, è attualmente mira JDK 13 come una caratteristica di anteprima. Permettendo di scrivere qualcosa di simile:

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

Prima di questo PEC, in JDK12, PEC 326: prime stringa letterali finalizzata a dare attuazione una funzionalità simile, ma è stato finalmente ritirato.

Purtroppo, Java non ha stringhe multilinea. O si deve concatenare le stringhe letterali (mediante + o StringBuilder essendo i due approcci più comuni a questo) o leggere la stringa in da un file separato.

Per le grandi stringhe multilinea Sarei propenso a utilizzare un file separato e leggerlo nel usando getResourceAsStream() (un metodo della classe Class). In questo modo è facile trovare il file come non si deve preoccupare della directory corrente contro cui è stato installato il codice. Inoltre rende più facile il confezionamento, perché si può effettivamente memorizzare il file nel file jar.

Supponiamo che sei in una classe chiamata Foo. Basta fare qualcosa di simile:

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

L'altro fastidio è che Java non ha uno standard di "leggere tutto il testo da questo lettore in una stringa" metodo. E 'abbastanza facile da scrivere se:

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();
}
String newline = System.getProperty ("line.separator");
string1 + newline + string2 + newline + string3

Ma, la migliore alternativa è quella di utilizzare String.Format

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

Dal momento che Java non (ancora) il supporto nativo stringhe multilinea, l'unico modo per ora è quello di incidere intorno ad esso utilizzando una delle tecniche di cui sopra. Ho costruito il seguente script Python utilizzando alcuni dei trucchi di cui sopra:

import sys
import string
import os

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

Metti che in un javastringify.py file di nome e la stringa in un file mystring.txt ed eseguirlo nel modo seguente:

cat mystring.txt | python javastringify.py

È possibile quindi copiare l'uscita e incollarlo nel vostro editor.

Modifica questo come necessaria per gestire eventuali casi particolari, ma questo funziona per le mie esigenze. Spero che questo aiuta!

È possibile utilizzare scala-codice, che è compatibile con Java e permette multilinea-Strings chiusa con "" ":

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

(notare le virgolette all'interno della stringa) e da Java:

String s2 = foobar.SWrap.bar ();

Se questo è più comodo ...?

Un altro approccio, se spesso gestire lungo testo, che dovrebbe essere collocato all'interno del tuo codice sorgente, potrebbe essere uno script, che prende il testo da un file esterno, e wrappes come una multilinea-java-String in questo modo:

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

in modo che si può tagliare e incollarlo facilmente nella vostra sorgente.

È possibile concatenare i tuoi accodamento in un metodo separato come:

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

In entrambi i casi, preferiscono StringBuilder alla notazione più.

In realtà, ciò che segue è l'attuazione pulito che abbia visto finora. Esso utilizza un'annotazione per convertire un commento in una variabile stringa ...

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

Quindi, il risultato finale è che il codice HTML variabile contiene la stringa multilinea. Non ci sono citazioni, senza vantaggi, senza virgole, proprio stringa pura.

Questa soluzione è disponibile al seguente URL ... http://www.adrianwalker.org/2011/12/java-multiline -string.html

Speranza che aiuta!

Java Stringfier . Trasforma il testo in un blocco StringBuilder java fuggire, se necessario.

Un'alternativa non ho visto come la risposta finora è il 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();

Anche il fatto che java.io.BufferedWriter ha un metodo newLine() è taciuta.

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

Se ti piace guava di Google tanto come faccio io, si può dare una rappresentazione abbastanza pulito e un bel modo, facile da non hardcode vostri caratteri di nuova riga troppo:

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

Usa Properties.loadFromXML(InputStream). Non c'è bisogno di librerie esterne.

Meglio di un codice disordinato (dal manutenibilità e il design sono la vostra preoccupazione), è preferibile non utilizzare stringhe lunghe.
Inizia con la lettura proprietà XML:

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


quindi è possibile utilizzare la stringa multilinea in un modo più gestibile ...

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


MultiLine.xml` ottiene trova nella stessa YourClass cartella:

<?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 .: È possibile utilizzare <![CDATA[" ... "]]> per la stringa xml-like.

Una soluzione molto efficiente e indipendente dalla piattaforma sarebbe utilizzando la proprietà di sistema per i separatori di linea e la classe StringBuilder per costruire le stringhe:

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

JDK / 12 accesso anticipato Build # 12 , si può ora utilizzare stringhe multilinea in Java come segue:

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

e questo si traduce nel seguente output:

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

Definisci la mia stringa in un file di proprietà?

stringhe più righe non sono ammessi nelle file di proprietà. È possibile utilizzare \ n nei file di proprietà, ma non credo che è molto più di una soluzione nel vostro caso.

Una buona opzione.

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

    }

So che questa è una vecchia questione, ma per gli sviluppatori intersted letterali multilinea Gonna Be a # java12

http://mail.openjdk.java .net / Pipermail / ambra-dev / 2018-luglio / 003254.html

Io suggerisco di usare un programma di utilità come suggerito da ThomasP, e poi il link che nel processo di build.Un file esterno è ancora presente per contenere il testo, ma il file non viene letto in fase di runtime.Il flusso di lavoro è quindi:

  1. Costruire un "file di testo per il codice java' utility e il check-in di controllo di versione
  2. In ogni generazione, eseguire l'utilità contro il file di risorse per creare una revisione sorgente java
  3. La sorgente Java contiene un header class TextBlock {... seguito da una stringa statica, che è auto-generato dal file di risorse
  4. Costruire generato un file java con il resto del codice

Quando si utilizzano una lunga serie di +, viene creato un solo StringBuilder, a meno che la stringa è determinato al momento della compilazione, nel qual caso non viene utilizzato alcun StringBuilder!

L'unica StringBuilder tempo è più efficace quando è più istruzioni vengono utilizzati per costruire la stringa.

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

. Nota: viene creato un solo StringBuilder

  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
  

Per chiarire ulteriormente la mia domanda, io non sono preoccupato per le prestazioni a tutti. Sono preoccupato per problemi di manutenibilità e di design.

Rendere il più chiaro e semplice possibile.

Un piccolo trucco. L'utilizzo di questo inietto javascript in una pagina HTML creata dinamicamente

StringBuilder builder = new StringBuilder();

public String getString()
{
    return builder.toString();
}
private DropdownContent _(String a)
{
    builder.append(a);
    return this;
}

public String funct_showhide()
{
   return
    _("function slidedown_showHide(boxId)").
    _("{").
    _("if(!slidedown_direction[boxId])slidedown_direction[boxId] = 1;").
    _("if(!slideDownInitHeight[boxId])slideDownInitHeight[boxId] = 0;").
    _("if(slideDownInitHeight[boxId]==0)slidedown_direction[boxId]=slidedownSpeed; ").
    _("else slidedown_direction[boxId] = slidedownSpeed*-1;").
    _("slidedownContentBox = document.getElementById(boxId);").
    _("var subDivs = slidedownContentBox.getElementsByTagName('DIV');").
    _("for(var no=0;no<subDivs.length;no++){").
    _(" if(subDivs[no].className=='dhtmlgoodies_content')slidedownContent = subDivs[no];").
    _("}").
    _("contentHeight = slidedownContent.offsetHeight;").
    _("slidedownContentBox.style.visibility='visible';").
    _("slidedownActive = true;").
    _("slidedown_showHide_start(slidedownContentBox,slidedownContent);").
    _("}").getString();

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top