Question

En venant de Perl, je manque que le « ici-document » de la création d'une chaîne de plusieurs lignes dans le code source:

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

En Java, je dois avoir des citations lourdes et signes plus sur chaque ligne que je concaténer ma chaîne multiligne à partir de zéro.

Quelles sont meilleures alternatives? Define ma chaîne dans un fichier de propriétés?

Modifier : Deux réponses disent StringBuilder.append () est préférable à la notation plus. Quelqu'un pourrait-il expliquer pourquoi ils pensent ainsi? Il ne semble pas plus préférable de moi du tout. Je cherche un moyen de contourner le fait que les chaînes multilignes ne sont pas une construction linguistique de première classe, ce qui signifie que je ne veux certainement pas remplacer une construction linguistique de première classe (concaténation de chaîne avec plus) avec des appels de méthode.

Modifier : Pour clarifier ma question plus loin, je ne suis pas préoccupé par la performance du tout. Je suis préoccupé par les problèmes de maintenabilité et de conception.

Était-ce utile?

La solution

Stephen Colebourne a créé une pour ajouter des chaînes multi-lignes en Java 7.

En outre, Groovy a déjà le support pour chaînes multilignes .

Autres conseils

On dirait que vous voulez faire un multiligne littéral, qui n'existe pas en Java.

Votre meilleure alternative va être des chaînes qui sont juste +'d ensemble. D'autres personnes ont mentionné les options (StringBuilder, String.format, string.join) ne serait préférable que vous avez commencé avec un tableau de chaînes.

Considérez ceci:

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

Si vous voulez que la nouvelle ligne pour votre système particulier, vous devez soit utiliser System.getProperty("line.separator"), ou vous pouvez utiliser %n dans String.format.

Une autre option est de mettre la ressource dans un fichier texte, et de lire le contenu de ce fichier. Ce serait préférable pour les chaînes très grandes pour éviter les ballonnements inutilement vos fichiers de classe.

Dans Eclipse si vous activez l'option « Escape texte lors du collage dans une chaîne » (dans les Préférences> Java> Editeur> Taper) et coller une chaîne de plusieurs lignes ESSOR guillemets, il ajoutera automatiquement " et \n" + pour tous vos lignes.

String str = "paste your text here";

Ceci est un vieux fil, mais une nouvelle solution tout à fait élégante (avec seulement 4 peut-être 3 petits inconvénients) est d'utiliser une annotation personnalisée.

Vérifier: http://www.adrianwalker.org/2011 /12/java-multiline-string.html

Un projet inspiré de ce travail est hébergé sur GitHub:

https://github.com/benelog/multiline

Exemple de code 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);
  }
}

Les inconvénients sont

  1. que vous devez activer l'annotation (fournie) correspondant processeur.
  2. cette variable chaîne ne peut pas être définie comme variable locale Vérifiez projet Raw littéraux de chaîne où vous pouvez définir des variables comme des variables locales
  3. cette chaîne ne peut contenir d'autres variables comme dans Visual Basic .Net XML littérale (<%= variable %>): -)
  4. cette chaîne est délimitée par JavaDoc commentaire littéral (/ **)

Et vous avez probablement configurer Eclipse / Intellij-idée de ne pas reformater automatiquement vos commentaires Javadoc.

On peut trouver ce bizarre (les commentaires Javadoc ne sont pas conçus pour intégrer autre chose que des commentaires), mais ce manque de chaîne multiligne en Java est vraiment ennuyeux à la fin, je trouve que ce soit le moins pire des solutions.

Une autre option peut être de stocker des chaînes longues dans un fichier externe et lire le fichier dans une chaîne.

Ceci est quelque chose que vous devriez jamais utilisation sans penser à ce qu'il fait. Mais je l'ai utilisé cela avec grand succès pour les scripts one-off:

Exemple:

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

Code:

// 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 a ajouté une nouvelle méthode statique à java.lang.String qui offre une alternative un peu mieux:

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

L'utiliser:

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

Si vous définissez vos chaînes dans un fichier de propriétés, il regardera bien pire. IIRC, ça va ressembler à:

string:text\u000atext\u000atext\u000a

En général, il est une idée raisonnable de ne pas intégrer de grandes chaînes dans la source. Vous pouvez les charger en tant que ressources, peut-être en XML ou un format de texte lisible. Les fichiers texte peuvent être soit lus lors de l'exécution ou compilé dans la source Java. Si vous finissez en les plaçant dans la source, je suggère de mettre le + à l'avant et en omettant de nouvelles lignes inutiles:

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

Si vous avez de nouvelles lignes, vous voudrez peut-être un peu de jointure ou méthode de formatage:

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

Les points positifs sont convertis en StringBuilder.append, sauf si les deux chaînes sont des constantes de sorte que le compilateur peut les combiner au moment de la compilation. Au moins, voilà comment il est dans le compilateur de Sun, et je soupçonne la plupart, sinon tous les autres compilateurs feraient la même chose.

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

génère normalement exactement le même code que:

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

Par contre:

String c="Hello"+"Goodbye";

est le même que:

String c="HelloGoodbye";

Autrement dit, il n'y a pas de pénalité pour briser vos chaînes littérales sur plusieurs lignes avec des signes plus pour une meilleure lisibilité.

Dans le IntelliJ IDE il vous suffit de taper:

""

Ensuite, placez votre curseur dans les guillemets et collez votre chaîne. L'IDE augmentera dans plusieurs lignes concaténés.

JEP 355: blocs de texte (Preview) vise à couvrir cette fonctionnalité, il est actuellement le ciblage 13 JDK comme fonction de prévisualisation. Permettant d'écrire quelque chose comme:

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

Avant cette JEP, dans jdk12, JEP 326: Raw littéraux de chaîne visant à mettre en œuvre une fonction similaire, mais il a finalement été retirée.

Malheureusement, Java n'a pas littéraux de chaîne multi-ligne. Vous devez soit concaténer littéraux de chaîne (en utilisant + ou StringBuilder étant les deux approches les plus communes à ce sujet) ou lire la chaîne à partir d'un fichier séparé.

Pour les grandes littéraux de chaîne multi-ligne, je serais enclin à utiliser un fichier séparé et le lire dans l'utilisation getResourceAsStream() (une méthode de la classe Class). Cela rend plus facile de trouver le fichier que vous n'avez pas à vous soucier du répertoire courant par rapport à l'endroit où votre code a été installé. Il rend également plus facile d'emballage, parce que vous pouvez stocker le fichier dans votre fichier jar.

Supposons que vous êtes dans une classe appelée Foo. Il suffit de faire quelque chose comme ceci:

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

L'un autre ennui est que Java ne dispose pas d'une norme « lire tout le texte de ce lecteur dans une chaîne » méthode. Il est assez facile d'écrire que:

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

Mais, la meilleure alternative est d'utiliser String.format

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

Depuis Java ne supporte natif pas (encore) des chaînes à plusieurs lignes, le seul moyen pour pirater est maintenant autour d'elle en utilisant l'une des techniques mentionnées ci-dessus. J'ai construit le script Python suivant en utilisant certains des trucs mentionnés ci-dessus:

import sys
import string
import os

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

Mettez ça dans un fichier nommé javastringify.py et votre chaîne dans une mystring.txt et exécuter le fichier comme suit:

cat mystring.txt | python javastringify.py

Vous pouvez ensuite copier la sortie et le coller dans votre éditeur.

Modifier ce que nécessaire pour traiter des cas particuliers, mais cela fonctionne pour mes besoins. Espérons que cela aide!

Vous pouvez utiliser scala-code, qui est compatible avec Java et permet multiligne joint-cordes avec "" ":

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

(notez les guillemets à l'intérieur de la chaîne) et de java:

String s2 = foobar.SWrap.bar ();

Que ce soit plus confortable ...?

Une autre approche, si vous manipulez souvent long texte, qui devrait être placé dans votre code source, pourrait être un script, qui prend le texte à partir d'un fichier externe, et il wrappes comme multiligne-java-String comme ceci:

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

de sorte que vous pouvez couper et coller facilement dans votre source.

Vous pouvez concaténer votre dans une méthode ajouter ses séparée comme:

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

De toute façon, préfère StringBuilder la notation plus.

En fait, ce qui suit est la mise en œuvre plus propre que je l'ai vu jusqu'à présent. Il utilise une annotation pour convertir un commentaire dans une variable string ...

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

Ainsi, le résultat final est que le code HTML variable contient la chaîne multiligne. Pas de citations, pas de points positifs, pas de virgule, juste chaîne pure.

Cette solution est disponible à l'adresse suivante ... http://www.adrianwalker.org/2011/12/java-multiline -string.html

L'espoir qui aide!

Voir Java Stringfier . Transforme votre texte dans un bloc java StringBuilder échapper en cas de besoin.

Une alternative que je ne l'ai pas vu comme réponse est encore java.io.BufferedWriter a un procédé de newLine() est passé sous silence.

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

Si vous aimez la goyave autant que je le fais de Google, il peut donner une représentation assez propre et une belle façon facile de ne pas coder vos sauts de ligne trop:

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

Utilisez Properties.loadFromXML(InputStream). Il n'y a pas besoin de libs externe.

Mieux qu'un code désordre (depuis la maintenabilité et la conception sont vos préoccupations), il est préférable de ne pas utiliser des chaînes longues.
Commencez par lire les propriétés xml:

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


alors vous pouvez utiliser votre chaîne multiligne dans un plus maintenable chemin ...

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


MultiLine.xml` se trouve dans le même dossier 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 .: Vous pouvez utiliser <![CDATA[" ... "]]> pour une chaîne comme xml.

Une solution indépendante tout à fait efficace et la plate-forme serait en utilisant la propriété système pour les séparateurs de ligne et la classe StringBuilder pour construire des chaînes:

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 build accès rapide # 12 , on peut maintenant utiliser des chaînes multilignes en Java comme suit:

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

et cela se traduit par la sortie suivante:

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

Définir ma chaîne dans un fichier de propriétés?

chaînes multilignes ne sont pas autorisés dans les fichiers de propriétés. Vous pouvez utiliser \ n dans les fichiers de propriétés, mais je ne pense pas que beaucoup d'une solution dans votre cas.

Une bonne option.

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

    }

Je sais que c'est une vieille question, mais pour les développeurs Intersted MULTIVOL littéraux va être dans # java12

http://mail.openjdk.java .net / pipermail / orange-dev / 2018-Juillet / 003254.html

Je suggère d'utiliser un utilitaire tel que suggéré par ThomasP, et alors que le lien dans votre processus de construction. Un fichier externe est toujours présent pour contenir le texte, mais le fichier est lu lors de l'exécution. Le workflow est alors:

  1. Construire un 'fichier texte au code java' utilitaire et vérifier dans le contrôle de version
  2. Sur chaque build, exécutez l'utilitaire contre le fichier de ressources pour créer une source java révisée
  3. La source Java contient un en-tête comme class TextBlock {... suivi d'une chaîne statique qui est généré automatiquement à partir du fichier de ressources
  4. Générez le fichier java généré avec le reste de votre code

Quand une longue série de + sont utilisés, un seul StringBuilder est créé, à moins que la chaîne est déterminée au moment de la compilation auquel cas aucun StringBuilder est utilisé!

La seule fois StringBuilder est plus efficace est lorsque plusieurs déclarations sont utilisés pour construire la chaîne.

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

Note:. Un seul StringBuilder est créé

  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
  

Pour préciser ma question plus loin, je ne suis pas préoccupé par la performance du tout. Je suis préoccupé par les problèmes de maintenabilité et de conception.

Faites aussi simple et claire que possible.

Un petit truc. L'utilisation de ce que je javascript dans une injecter page HTML créée dynamiquement

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

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top