Подтвердить что ты не робот

Многострочная строка Java

Исходя из Perl, я уверен, что отсутствует способ "here-document" для создания многострочной строки в исходном коде:

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

В Java я должен иметь громоздкие цитаты и знаки плюс на каждой строке, поскольку я соединяю свою многострочную строку с нуля.

Каковы некоторые альтернативы? Определить мою строку в файле свойств?

Изменить: два ответа говорят, что StringBuilder.append() предпочтительнее плюсовой нотации. Может ли кто-нибудь объяснить, почему они так думают? Мне это не кажется более предпочтительным. Я ищу способ избежать того факта, что многострочные строки не являются первоклассной конструкцией языка, что означает, что я определенно не хочу заменять конструкцию языка первого класса (конкатенацию строк с помощью плюс) вызовами методов.

Изменить: Чтобы уточнить мой вопрос дальше, я вообще не беспокоюсь о производительности. Я обеспокоен проблемами ремонтопригодности и проектирования.

4b9b3361

Ответ 2

Похоже, вы хотите сделать многострочный литерал, которого нет в Java.

Ваша лучшая альтернатива - это строки, которые всего лишь + 'd вместе. Некоторые другие варианты, упомянутые выше (StringBuilder, String.format, String.join), были бы предпочтительнее, если бы вы начали с массива строк.

Рассмотрим это:

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

В сравнении с 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"
);

Если вы хотите использовать новую строку для своей конкретной системы, вам нужно либо использовать System.getProperty("line.separator"), либо использовать %n в String.format.

Другой вариант - разместить ресурс в текстовом файле и просто прочитать содержимое этого файла. Это было бы предпочтительнее для очень больших строк, чтобы избежать излишней раздувания ваших файлов классов.

Ответ 3

В Eclipse, если вы включите опцию "Escape text при вставке в строковый литерал" (в "Настройки" > "Java" > "Редактор" > "Ввод текста" ) и вставьте многострочную строку в кавычки, она автоматически добавит " и \n" + для всех ваших линий.

String str = "paste your text here";

Ответ 4

Это старая тема, но новое довольно элегантное решение (с 4 или 3 небольшими недостатками) заключается в использовании пользовательской аннотации.

Проверьте: http://www.adrianwalker.org/2011/12/java-multiline-string.html

Проект, вдохновленный этой работой, размещен на GitHub:

https://github.com/benelog/multiline

  Пример кода 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);
  }
}

Недостатками являются

  1. что вы должны активировать соответствующую (предоставленную) аннотацию процессор.
  2. эта строковая переменная не может быть определена как локальная переменная. Проверьте проект Raw String Literals, где вы можете определить переменные как локальные переменные
  3. эта строка не может содержать другие переменные, как в Visual Basic.Net с литералом XML (<%= variable %>) :-)
  4. этот строковый литерал ограничен комментарием JavaDoc (/**)

И вам, вероятно, придется настроить Eclipse/Intellij-Idea, чтобы он не переформатировал автоматически ваши комментарии Javadoc.

Это может показаться странным (комментарии Javadoc не предназначены для встраивания чего-либо, кроме комментариев), но поскольку отсутствие многострочной строки в Java действительно раздражает в конце, я считаю, что это наименее худшее решение.

Ответ 5

Другим вариантом может быть сохранение длинных строк во внешнем файле и чтение файла в строку.

Ответ 6

Это то, что вы никогда не должны использовать, не задумываясь о том, что он делает. Но для одноразовых скриптов я использовал это с большим успехом:

Пример:

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

код:

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

Ответ 7

String.join

Java 8 добавила новый статический метод в java.lang.String который предлагает немного лучшую альтернативу:

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

Используй это:

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

Ответ 8

Если вы определяете свои строки в файле свойств, это будет выглядеть намного хуже. IIRC, это будет выглядеть так:

string:text\u000atext\u000atext\u000a

Как правило, разумная идея не встраивать большие строки в источник. Возможно, вы захотите загрузить их в качестве ресурсов, возможно, в формате XML или в текстовом формате. Текстовые файлы могут быть прочитаны во время выполнения или скомпилированы в источник Java. Если вы положите их в исходный код, я предлагаю поставить + на передний план и опустить ненужные новые строки:

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

Если у вас есть новые строки, вам может понадобиться некоторый метод соединения или форматирования:

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

Ответ 9

Плюсы преобразуются в StringBuilder.append, за исключением случаев, когда обе строки являются константами, поэтому компилятор может комбинировать их во время компиляции. По крайней мере, так, как это происходит в компиляторе Sun, и я бы заподозрил большинство, если бы не все другие компиляторы сделали бы то же самое.

Итак:

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

обычно генерирует точно такой же код, как:

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

С другой стороны:

String c="Hello"+"Goodbye";

совпадает с:

String c="HelloGoodbye";

То есть, нет штрафа за нарушение ваших строковых литералов на нескольких строках с плюсовыми признаками для удобочитаемости.

Ответ 10

В IntelliJ IDE вам просто нужно ввести:

""

Затем поместите курсор внутри кавычек и вставьте строку. IDE расширит его на несколько конкатенированных строк.

Ответ 11

JEP 355. Текстовые блоки (предварительный просмотр) призваны охватить эту функцию, в настоящее время он использует JDK 13 в качестве функции предварительного просмотра. Позволяет написать что-то вроде:

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

До этого JEP, в JDK12, JEP 326: необработанные строковые литералы стремились реализовать аналогичную функцию, но в конце концов она была отозвана.

Ответ 12

К сожалению, в Java нет многострочных строковых литералов. Вам либо нужно объединить строковые литералы (используя +, либо StringBuilder, являющийся двумя наиболее распространенными подходами к этому), либо прочитайте строку из отдельного файла.

Для больших многострочных строковых литералов я бы склонен использовать отдельный файл и читать его с помощью getResourceAsStream() (метод класса Class). Это позволяет легко находить файл, так как вам не нужно беспокоиться о текущем каталоге и о том, где был установлен ваш код. Это также упрощает упаковку, потому что вы можете хранить файл в своем файле jar.

Предположим, вы находитесь в классе Foo. Просто сделайте что-нибудь вроде этого:

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

Еще одна досада заключается в том, что Java не имеет стандартного "чтения всего текста из этого метода чтения в строку". Это довольно легко написать:

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

Ответ 13

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

Но лучше всего использовать String.format

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

Ответ 14

Вы можете использовать scala -код, который совместим с java и позволяет многострочные строки, заключенные в "":

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

(обратите внимание на кавычки внутри строки) и из java:

String s2 = foobar.SWrap.bar ();

Будет ли это более комфортно...?

Другой подход, если вы часто обрабатываете длинный текст, который должен быть помещен в исходный код, может быть script, который берет текст из внешнего файла и обертывает его как многострочный java-String следующим образом:

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

чтобы вы могли легко и просто вставлять его в свой источник.

Ответ 15

Так как Java не поддерживает (но еще) встроенные многострочные строки, единственный способ - это взломать его, используя один из вышеупомянутых методов. Я построил следующий Python script, используя некоторые из трюков, упомянутых выше:

import sys
import string
import os

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

Поместите это в файл с именем javastringify.py и свою строку в файл mystring.txt и запустите его следующим образом:

cat mystring.txt | python javastringify.py

Затем вы можете скопировать вывод и вставить его в свой редактор.

Измените это, если необходимо, для обработки каких-либо особых случаев, но это работает для моих нужд. Надеюсь, это поможет!

Ответ 16

Вы можете объединить свои добавления отдельным методом, например:

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

В любом случае, предпочтите StringBuilder плюсовой нотации.

Ответ 17

См. Java Stringfier. Поворачивает ваш текст в escape-код java-блока StringBuilder, если это необходимо.

Ответ 18

На самом деле, это самая чистая реализация, которую я видел до сих пор. Он использует аннотацию для преобразования комментария в строковую переменную...

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

Итак, конечный результат состоит в том, что переменная html содержит многострочную строку. Нет кавычек, нет плюсов, нет запятых, просто чистая строка.

Это решение доступно по следующему URL-адресу... http://www.adrianwalker.org/2011/12/java-multiline-string.html

Надеюсь, что это поможет!

Ответ 19

Альтернативой, которую я еще не видел в качестве ответа, является 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();

Также тот факт, что java.io.BufferedWriter имеет метод newLine() не упоминается.

Ответ 20

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

Ответ 21

Если вам нравится google guava столько, сколько я, он может дать довольно чистое представление и хороший, простой способ не жестко кодировать символы новой строки:

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

Ответ 22

Используйте Properties.loadFromXML(InputStream). Там нет необходимости в внешних библиотеках.

Лучше, чем беспорядочный код (поскольку для вас требуется поддержка и дизайн), предпочтительнее не использовать длинные строки.

Начните с чтения свойств xml:

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


то вы можете использовать свою многострочную строку более удобным образом...

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


MultiLine.xml 'находится в той же папке 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.: Вы можете использовать <![CDATA["... "]]> для xml-подобной строки.

Ответ 23

Достаточно эффективное и независимое от платформы решение будет использовать системное свойство для разделителей строк и класс StringBuilder для построения строк:

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

Ответ 24

С сборкой раннего доступа JDK/12 # 12 теперь можно использовать многострочные строки в Java следующим образом:

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

и это приводит к следующему результату:

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

Ответ 25

Определите мою строку в файле свойств?

В файлах свойств не разрешены многострочные строки. Вы можете использовать \n в файлах свойств, но я не думаю, что это большая часть решения в вашем случае.

Ответ 26

Я предлагаю использовать утилиту, как предложено ThomasP, а затем связать это с вашим процессом сборки. Внешний файл все еще присутствует, чтобы содержать текст, но файл не читается во время выполнения. Рабочий процесс следующий:

  1. Создайте утилиту "текстовый файл в java-код" и установите флажок в управлении версиями
  2. На каждой сборке запустите утилиту с файлом ресурса, чтобы создать обновленный источник java
  3. Источник Java содержит заголовок как class TextBlock {... за которым следует статическая строка, которая автоматически генерируется из файла ресурсов
  4. Создайте сгенерированный Java файл с остальной частью вашего кода.

Ответ 27

Один хороший вариант.

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

    }

Ответ 29

Когда используется длинная серия +, создается только один StringBuilder, если только String не определяется во время компиляции, и в этом случае не используется StringBuilder!

Единственный раз, когда StringBuilder эффективнее, используется несколько операторов для построения строки.

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

Примечание. Создается только один 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

Чтобы уточнить мой вопрос, меня вообще не интересует производительность. Я обеспокоен проблемами ремонтопригодности и проектирования.

Сделайте это как можно яснее и понятнее.

Ответ 30

Один маленький трюк. Используя это, я добавляю javascritp в динамически создаваемую HTML-страницу

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

}