[java] سلسلة جافا متعددة الأسطر


Answers

يبدو أنك تريد إجراء حرفية متعددة الأسطر ، وهي غير موجودة في Java.

سيكون البديل الأفضل عبارة عن سلاسل يتم جمعها معًا فقط. بعض الخيارات الأخرى التي ذكرها الناس (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";

مقابل 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 .

خيار آخر هو وضع المورد في ملف نصي ، وقراءة فقط محتويات ذلك الملف. قد يكون من الأفضل استخدام سلاسل كبيرة جدًا لتجنب انتفاخ ملفات الصف بشكل غير ضروري.

Question

قادمة من بيرل ، أنا متأكد من عدم وجود وسيلة "هنا الوثيقة" لإنشاء سلسلة متعددة الأسطر في شفرة المصدر:

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

في جاوا لا بد لي من أن تكون علامات الاقتباس مرهقة وعلامات زائد على كل سطر وأنا سلسلتي سلسلة متعددة الحدود من الصفر.

ما هي بعض البدائل الأفضل؟ تحديد السلسلة الخاصة بي في ملف خصائص؟

تحرير : إجابات اثنين تقول StringBuilder.append () الأفضل من تدوين زائد. هل يمكن لأي شخص أن يشرح لماذا يعتقدون ذلك؟ لا يبدو أكثر تفضيلا لي على الإطلاق. أنا أبحث عن حقيقة أن سلاسل متعددة الأسطر ليست بناء لغة من الدرجة الأولى ، مما يعني أنني بالتأكيد لا أريد استبدال تركيب اللغة من الدرجة الأولى (سلسلة سلسلة مع زائد) مع مكالمات الأسلوب.

تعديل : لتوضيح سؤالي أكثر ، لا أشعر بالقلق حيال الأداء على الإطلاق. أنا قلق بشأن الصيانة وقضايا التصميم.




تحديد السلسلة الخاصة بي في ملف خصائص؟

لا يُسمح باستخدام سلاسل متعددة الأسطر في ملفات الخصائص. يمكنك استخدام \ n في ملفات الخصائص ، ولكن لا أعتقد أن هذا هو الحل في قضيتك.




إذا قمت بتعريف السلاسل الخاصة بك في ملف خصائص سيبدو أسوأ بكثير. IIRC ، سوف يبدو الأمر كما يلي:

string:text\u000atext\u000atext\u000a

عموما فكرة معقولة لعدم تضمين سلاسل كبيرة في المصدر. قد ترغب في تحميلها كموارد ، ربما في XML أو تنسيق نص قابل للقراءة. يمكن قراءة الملفات النصية في وقت التشغيل أو تجميعها في مصدر Java. إذا انتهيت من وضعهم في المصدر ، أقترح وضع علامة + في المقدمة وإزالة خطوط جديدة غير ضرورية:

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

إذا كان لديك خطوط جديدة ، فقد تحتاج إلى بعض طرق الانضمام أو التنسيق:

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



Use Properties.loadFromXML(InputStream) . There's no need for external libs.

Better than a messy code (since maintainability and design are your concern), it is preferable not to use long strings.

Start by reading xml properties:

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


then you can use your multiline string in a more maintainable way...

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


MultiLine.xml` gets located in the same folder 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.: You can use <![CDATA[" ... "]]> for xml-like string.




هذا شيء يجب ألا تستخدمه مطلقًا دون التفكير في ما يفعله. لكن بالنسبة للنصوص الفريدة ، فقد استخدمت هذا بنجاح كبير:

مثال:

    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'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 out = Joiner.on(newline).join(ImmutableList.of(
    "line1",
    "line2",
    "line3"));



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



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



It may seem a little crazy, but since heredocs are syntactic sugar over one-line declarations with linebreaks escaped, one could write pre-processor for Java files that would change heredocs into single-liners during preprocessing.

It would require writing proper plugins for preprocessing files before compilation phase (for ant/maven build) and a plugin to IDE.

من وجهة النظر الأيديولوجية ، فإنه لا يختلف عن fg "generics" ، التي هي أيضا نوع من السكر النحوي قبل المعالجة على الصب.

ومع ذلك ، هناك الكثير من العمل ، لذلك سأستخدم في مكانك فقط ملفات .properties.




يمكنك استخدام رمز scala ، وهو متوافق مع جافا ، ويسمح باستخدام سلاسل متعددة الأسطر مع "" ":

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

سواء كان هذا أكثر راحة ...؟

هناك طريقة أخرى ، إذا كنت تعالج نصًا طويلًا ، والذي يجب أن يوضع في شفرة المصدر ، قد يكون برنامجًا نصيًا ، يأخذ النص من ملف خارجي ، ويطبعه كسلسلة متعددة الأسطر-جافا-مثل:

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

بحيث يمكنك قصها ولصقها بسهولة في المصدر.




يحتوي النموذج المتأخر JAVA على تحسينات لـ + مع سلاسل ثابتة ، يستخدم StringBuffer خلف الكواليس ، لذلك لا تريد فوضى رمزك معها.

It points to a JAVA oversight, that it does not resemble ANSI C in the automatic concatenation of double quoted strings with only white space between them, eg:

const char usage = "\n"
"Usage: xxxx <options>\n"
"\n"
"Removes your options as designated by the required parameter <options>,\n"
"which must be one of the following strings:\n"
"  love\n"
"  sex\n"
"  drugs\n"
"  rockandroll\n"
"\n" ;

I would love to have a multi-line character array constant where embedded linefeeds are honored, so I can present the block without any clutter, eg:

String Query = "
SELECT
    some_column,
    another column
  FROM
      one_table a
    JOIN
      another_table b
    ON    a.id = b.id
      AND a.role_code = b.role_code
  WHERE a.dept = 'sales'
    AND b.sales_quote > 1000
  Order BY 1, 2
" ;

To get this, one needs to beat on the JAVA gods.




انظر جافا Stringfier . يحول النص الخاص بك إلى كتلة جافا StringBuilder يهرب إذا لزم الأمر.




أقترح استخدام الأداة المساعدة على النحو الذي اقترحه ThomasP. ثم ربط ذلك في عملية البناء الخاصة بك. لا يزال يوجد ملف خارجي يحتوي على النص ، ولكن لا تتم قراءة الملف في وقت التشغيل. سير العمل هو:

  1. بناء أداة 'textfile إلى java code' والتحقق من التحكم في الإصدار
  2. على كل بناء ، تشغيل الأداة المساعدة ضد ملف المورد لإنشاء مصدر جافا المنقحة
  3. يحتوي مصدر java على رأس مثل class TextBlock {... متبوعًا بسلسلة ثابتة يتم إنشاؤها تلقائيًا من ملف المورد
  4. بناء ملف java الذي تم إنشاؤه مع بقية التعليمات البرمجية



للأسف ، لا تحتوي Java على قيم حرفية متعددة الأسطر. لديك إما لسَلسَلة سلسلة من القيم الحرفية (باستخدام + أو StringBuilder كونهما الأسلوب الأكثر شيوعًا لهذا) أو قراءة السلسلة في ملف منفصل.

بالنسبة إلى القيم الحرفية الكبيرة متعددة الأسطر ، سأكون مائلاً لاستخدام ملف منفصل وقراءته باستخدام getResourceAsStream() (طريقة لفئة Class ). هذا يجعل من السهل العثور على الملف حيث لا داعي للقلق حول الدليل الحالي مقابل مكان تثبيت التعليمات البرمجية. كما أنه يجعل التعبئة أسهل ، لأنه يمكنك تخزين الملف في ملف jar.

لنفترض أنك في صف يدعى Foo. فقط افعل شيئًا كهذا:

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

انزعاج واحد آخر هو أن جافا ليس لديها معيار "قراءة كل النص من هذا القارئ في سلسلة" طريقة. من السهل الكتابة على الرغم من ذلك:

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



هذا خيط قديم ، لكن الحل الجديد الأنيق (مع عيب واحد فقط) هو استخدام تعليق توضيحي مخصص.

تحقق: http://www.adrianwalker.org/2011/12/java-multiline-string.html

تعديل: يبدو أن عنوان URL المذكور مكسور. يتم استضافة مشروع مستوحى من هذا العمل على GitHub:

https://github.com/benelog/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);
  }
}

العيب هو أنه يجب عليك تفعيل المعالج التوضيحي المقابل (المقدم).

وربما لديك لتكوين Eclipse ليس إعادة صياغة تلقائيا تعليقاتك javadoc.

يمكن للمرء أن يجد هذا غريبًا (لم يتم تصميم تعليقات javadoc لتضمين أي شيء آخر غير التعليقات) ، ولكن لأن هذا النقص في سلسلة متعددة الأسطر في Java مزعج حقًا في النهاية ، أجد أن هذا هو الحل الأسوأ.




Links