Java stringa su più righe
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.
Soluzione
Stephen Colebourne ha creato una proposta rel="noreferrer"> per l'aggiunta di stringhe multilinea in Java 7.
Inoltre, Groovy ha già il supporto per stringhe multilinea .
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
- che si deve attivare il corrispondente (in dotazione) annotazione processore.
- quella variabile stringa non può essere definita come controllare la variabile locale Raw stringa letterali progetto in cui è possibile definire variabili come variabili locali
- che stringa non può contenere altre variabili come in Visual Basic .NET
con letterale XML (
<%= variable %>
): -) - 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:
- Costruire un "file di testo per il codice java' utility e il check-in di controllo di versione
- In ogni generazione, eseguire l'utilità contro il file di risorse per creare una revisione sorgente java
- La sorgente Java contiene un header
class TextBlock {...
seguito da una stringa statica, che è auto-generato dal file di risorse - 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();
}