5

What's the right way to check if a string contains null characters only?

String s = "\u0000";
if(s.charAt(0) == 0) {
   System.out.println("null characters only");
}

Or

String s = "\0\0";
for(int i = 0; i < s.length(); i++) {
   if(s.charAt(i) == 0) 
       continue;

   else break;

}

Both work. But is there a better and more concise way to perform this check. Is there a utility to check if a string in java contains only null characters(\u0000 OR \0) ?

And what is the difference between '\0' and '\u0000'?

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
tusharRawat
  • 719
  • 10
  • 24
  • 4
    Hmm. I am hard-pressed to think of a **valid** use-case that involves testing to see if a string contains just NUL characters. (The only use-cases I can think of involve treating non-text data as text ... and that's conceptually wrong.) – Stephen C May 13 '21 at 03:27
  • @StephenC, my service needs to call a downstream server, which is returning a parameter in json body say "eCode", based on this I need to check if there's something went wrong in downstream server, so if this string is empty OR contains only null characters than everything is fine, other wise if "eCode" contains anything else than I need to returned an error response to the upstreams. – tusharRawat May 13 '21 at 18:37
  • 1
    OK ... so why is a server sending you a string that contains NUL characters in a JSON response? That is ... umm ... bad design. Are you sure that you haven't misunderstood the spec? (Might it actually say "an empty string or null"? There is a null value in JSON.) – Stephen C May 14 '21 at 05:30
  • No I have even tested calling the service, they are returning null character string, I initially thought it should be null or "" empty string but as my test cases got failed than I realized that they are returning something else, and that's indeed a bad design, I concur, But you know, I have to deal with it as I don't have the ownership of other service. – tusharRawat May 14 '21 at 12:46

7 Answers7

9

A char literal (in Java) can be written multiple ways (all of which are equivalent). For example,

System.out.println('\u0000' == '\0');
System.out.println('\u0000' == 0);

Will output

true
true

because a char is a 16-bit integral type in Java. And all three of \u0000, \0 and 0 are the same value. As for finding if a String contains only 0 char values - simply iterate it. Like,

boolean allNulls = true;
for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) != 0) {
        allNulls = false;
        break;
    }
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 2
    ... and if you want a **consise** way to do the test, put the above code into a method/function. – Stephen C May 13 '21 at 03:22
  • Okay so we have to iterate over every single char and compare with '\u0000', we have no util available for that? – tusharRawat May 13 '21 at 05:20
  • 1
    @tusharRawat What do you mean by a "util"? Anything you use will, at some point or another, loop through each character of the string. It's just that you might not see the loop in the code you write. After all, how do you know if _every_ character is NUL without checking every one of them? – Sweeper May 13 '21 at 05:51
  • Yeah understand @Sweeper, what your are saying, I know internally also the utility is going to do the same, 1-by-1 character comparison, but the entire purpose of having a utility is if something is built already just use it in development don't reinvent the wheel, I hope you understand what I am saying. – tusharRawat May 13 '21 at 13:00
  • 1
    @tusharRawat In that case, I'm going to refer to Stephen C's comment on your question - this is not a common thing to do, at all (it is also possible that you _shouldn't_ be doing this at all). There's no reason for such a utility to exist. My answer or user15793316's answer is probably the shortest solutions you can get. – Sweeper May 13 '21 at 13:05
  • 1
    @Sweeper It's not better (because it creates temporaries) but `if (s.replaceAll("\u0000", "").length() == 0) { /* */ }` is shorter. At least I think it is. – Elliott Frisch May 13 '21 at 22:50
  • 1
    @ElliottFrisch why do developers come up so often with creative detours but fail to directly use the method expressing the intent? When you want to check whether a string *matches* a certain pattern, just use, e.g. `s.matches("\0*")`, instead of replacing the matches (`replaceAll` also uses the regex engine) with empty strings, only to test whether only empty strings will remain. If you are worried about temporary objects, use `Pattern.compile(...)` to reuse the part whose construction is truly expensive (the `Matcher` is negligible). – Holger May 16 '21 at 11:27
  • @Holger Hang on. I'm looking for a forest, but all I can see is these stupid trees. – Elliott Frisch May 16 '21 at 13:56
  • 1
    Never mind. I just see this pattern so often and really wondered why this happens so often. Perhaps, there is something about APIs or documentation we could improve… – Holger May 17 '21 at 06:54
5

You can get the chars() as an IntStream, then use allMatch:

if (yourString.chars().allMatch(x -> x == 0)) {
    // all null chars!
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
3

You can use a regular expression

to match one or more \u0000

boolean onlyNulls = string.matches("\u0000+");  // or "\0+"

use * instead of + to also match the empty string


(the stream solution by Sweeper is my preferred solution - IMHO it better resembles the intended task, despite I would use '\u0000' instead of 0)

0

I do not think there is a predefined way to check it, and I think the second one you mentioned is the correct way of testing for the same

Richard Onslow Roper
  • 5,477
  • 2
  • 11
  • 42
0

Other than the other answers (all valids), I've just found a one liner, based on org.apache.commons.lang3.StringUtils:

StringUtils.containsOnly(<string>, '\u0000')

Just a note: this method manages the empty string "" returning true.

mginius
  • 104
  • 2
  • 12
-1

You can use the existing String methods like trim and isEmpty with combination for this. consider this:

String s = "\u0000";
s.trim().isBlank()
Meetesh
  • 172
  • 2
  • 13
  • But this would also be true for `\t\r` and other all-whitespace inputs. – Tim Biegeleisen May 13 '21 at 02:39
  • Yes it would, i haven't considered this. – Meetesh May 13 '21 at 02:42
  • 1
    When you use `isBlank()` as in your code example, there is no sense in doing a `trim()` first. `trim()` would only be necessary when you use `isEmpty()` as described in the first sentence of you answer. – Holger May 16 '21 at 11:31
-1

\u0000 is Unicode value , The console output is a space

Stream.of("\u0000","\0\0","jack", "luca")
  .filter(s -> !s.trim().equals(""))
  .forEach(System.out::println);

output:

jack
luca
Luca
  • 31
  • 8