23

The Java 13 multi line text block facility with """ delimiters is becoming well known.

However I have a recurring need where I need entire paragraphs without the embedded newlines.

In other words, the following code snippet:

String paragraph =
    """
    aaaa bbbb cccc
    dddd eeee ffff
    gggg hhhh iiii
    """;
System.out.println(paragraph);

produces the following, as you'd expect:

aaaa bbbb cccc
dddd eeee ffff
gggg hhhh iiii

...which is usually tremendously useful. However in my case, for particularly large paragraphs I need it to produce this:

aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii

(....and deal with text flow later.)

Is there a way to establish a "no-newline" parameter for the triple-quote feature?

alife
  • 411
  • 4
  • 14
  • Imagine entering in a large amount of text that is to be later part of an HTML document, or similarly flowed into (say) a resizable dialog box. I want to enter in many "lines" worth of data *without* the `"line" + "line" + "line"`, etc., and without the EOL's showing up. Avoiding such obtuse and hard to maintain syntax is entirely the point behind `"""`. – alife Dec 19 '19 at 04:55

5 Answers5

45

The designers of this feature realized this requirement as well (see 'New escape sequences' in JEP368). So, with the latest early access build for JDK 14 you can use a trailing \ to escape the new line at the end of a line:

public class Main {
    public static void main(String[] args) {
        String paragraph =
            """
            aaaa bbbb cccc \
            dddd eeee ffff \
            gggg hhhh iiii \
            """;
        System.out.println(paragraph);
    }
}

Prints:

aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii
Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93
  • 14, huh? I wonder how the concatenation of indenting will work, or if all white space is wiped clean? – alife Dec 12 '19 at 21:14
  • But that would still require modifying the existing string input which might just be worthy enough to directly remove newlines itself in that case. – Naman Dec 13 '19 at 00:31
  • 3
    Hmm, first they say being able to embed literal text as-is is such an important feature that it justifies language changes, now it gets escape sequences on their own, and I have to wonder, what’s the advantage over putting `"aaaa bbbb cccc "`, `+"dddd eeee ffff "`, and `+"gggg hhhh iiii "`, each in a distinct line… – Holger Dec 13 '19 at 07:14
  • @Holger The feature has been split into 2; text blocks (aka multi-line strings), and raw string literals (i.e. as-is string, which is tbd). This is just the former. Note that other escapes, like `\n`, still work in text blocks. – Jorn Vernee Dec 13 '19 at 10:36
  • Still, the “text blocks” feature is not very convincing. As @Naman pointed out, this is still not an exact “what you see is what you get” and even worse, all the considerations the Java language developers had to make (how is indentation processed, what happens to line breaks, whether and which escape sequences should still exist), are not obvious to the reader, so we have a syntax with a non-obvious meaning. (And we now have a syntax whose validity can’t be determined by just looking at the code. Is the backslash truly before the line break or is there some whitespace behind it? We don’t see) – Holger Dec 13 '19 at 11:24
  • @Holger, it definitely _does_ seem like a situation of incremental "oh crap, we forgot something"-isms. However, it truly is a blessing being able to maintain a paragraph free of the endless surrounding (...)`" + "`(...) crap. – alife Dec 19 '19 at 04:59
  • 1
    But now that we have [`readString`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/Files.html#readString(java.nio.file.Path)), embedded resources are much easier to handle too. I never wanted to integrate entire paragraphs into the source code, only the I/O stuff was annoying. – Holger Dec 19 '19 at 09:33
  • @Holger, I think common use-cases would be to embed (small) resources in unit tests, right next to the test code. Another goal is to be able to embed code from other languages. I suppose it could be interesting for (custom) DSLs for instance. – Didier L Jan 03 '20 at 17:27
  • This is the closest I've seen to an answer. – alife May 23 '20 at 19:45
4

You can use String.lines introduced since Java-11 as:

String output = paragraph.lines().collect(Collectors.joining());

A complimentary and for what's worth it, here is a screenshot from JShell execution of the two different blocks of code:

enter image description here

Naman
  • 27,789
  • 26
  • 218
  • 353
  • 3
    …which does the same as `String output = paragraph.replaceAll("[\n\r]", "");` – Holger Dec 13 '19 at 08:28
  • And non of the solutions (until JDK-14's modification of allowing `\s` in the `"""` block) allow me to intermix EOL-less lines with lines where I actually do want the hard return (such as between paragraphs, etc.) – alife Dec 19 '19 at 05:03
  • This doesn't work in all cases - for example in an annotation. – mjaggard Jul 27 '22 at 15:54
1

Indeed, finding a good answer in Java 13 is not easy (maybe even impossible) but I think Jorn Vernee addressed the concern gracefully in his reply (new escape sequences in Java 14 provide an acceptable solution).

To expand on several listed concerns:

  • Holger mentions "the 'text blocks' feature is not very convincing". I have seen a lot of "ugly" code that does artificial string concatenation, so I think the feature definitely addresses an issue. On the other side, I have to agree that a feature like this leaves a lot of room for abuse (as in "let us put a lot of text in the Java code because now we can nicely do it!" - see the next point).
  • The original question mentions "large paragraphs" which make me advise not using this feature at all, but externalizing that content to resource files.
  • About the clarity and that certain aspects "are not obvious to the reader, so we have a syntax with a non-obvious meaning". That is partly correct, and it takes some reading and experimentation while the available material is not that vast at this moment. I found this: Programmer's Guide To Text Blocks, which provides quite a lot of examples. I also authored some examples, the one on text blocks being here: TextBlocks.java.

(Let's not forget that text blocks are in 'second preview' mode).

halfer
  • 19,824
  • 17
  • 99
  • 186
Chris T
  • 374
  • 2
  • 3
0

paragraph.replaceAll("\\n","") should do the job for you.

Guillaume
  • 1,277
  • 2
  • 13
  • 21
  • Intellij is now in some kind of crashing loop because of my use of the escape characters at the end of the line. Perhaps what would be best is `""" line line line """.replaceAll("\\n","");` Can't verify it right now though. – alife Dec 12 '19 at 21:24
  • I suppose there's also the (minor) issue that this is handled at runtime and not compile-time, but that's not a requirement for my purposes. – alife Dec 12 '19 at 21:26
  • This solution also can't quite reach the `\s` ability of JDK-14. What if I want several paragraphs without line breaks, but line breaks in between them. – alife Dec 19 '19 at 05:02
-3

Why not just pull it through a scanner:

   String strip(String multiline){
      var scanner = new java.util.Scanner(multiline);
      var text = scanner.next();
      while (scanner.hasNext()) text += " "+ scanner.next();
      return text;
   }