2016-01-03 102 views
1

我已經嘗試了很多帶有隨機字符的字符串,除了空字符串「」,它們的.getBytes()字節數組似乎永遠不會包含任何0值(如{123,-23,54,0,-92})。String.getBytes()的結果是否包含零?

它的.getBytes()字節數組總是不包含除了空字符串之外的所有nero嗎?

編輯:以前的測試代碼如下。現在我瞭解到,在Java 8中,如果字符串由(char)random.nextInt(65535)+ 1組成,結果似乎總是「不包含0」如果字符串包含(char)0,則「包含0」。

private static String randomString(int length){ 
    Random random = new Random(); 

    char[] chars = new char[length]; 
    for (int i = 0; i < length; i++){ 
     int integer = random.nextInt(65535) + 1; 
     chars[i] = (char) (integer); 
    } 
    return new String(chars); 
} 

public static void main(String[] args) throws Exception { 

    for (int i = 1; i < 100000; i++){ 
     String s1 = randomString(10); 
     byte[] bytes = s1.getBytes(); 
     for (byte b : bytes) { 
      if (b == 0){ 
       System.out.println("contains 0"); 
       System.exit(0); 
      } 
     } 
    } 
    System.out.println("contains no 0"); 

} 
+1

你能提供你已經嘗試和代碼以及絃樂。只提供最少和特定的代碼。 – YoungHobbit

+0

請注意,在幾個[標準字符集](https://docs.oracle.com/javase/7/docs/api/java/nio/charset/StandardCharsets.html)中,空字符串'「」'不*編碼轉換爲帶有'0'元素的字節數組。 ASCII,UTF-8和ISO_8859_1都將空字符串表示爲空數組。如果你看到''''編碼爲'{0}',那麼你的系統正在使用其他默認字符集,並且你不應該期望你的結果是典型的。 – dimo414

+0

對不起,我沒有仔細檢查。空字符串對我來說也是一個空數組。 – Tom

回答

7

它取決於您的平臺本地編碼。但在許多編碼中,'\0'(空)字符將導致getBytes()返回一個數組,其中有一個零。

System.out.println("\0".getBytes()[0]); 

這將與US-ASCII,ISO-8859-1和UTF-8編碼工作:

System.out.println("\0".getBytes("US-ASCII")[0]); 
System.out.println("\0".getBytes("ISO-8859-1")[0]); 
System.out.println("\0".getBytes("UTF-8")[0]); 

如果你有一個字節數組,你想與其對應的字符串,你也可以做相反的:

​​

然而,這將產生不同的結果爲不同的編碼,並且在某些編碼可能是一個無效的序列。

而其中的字符可能無法打印。

你最好的賭注是ISO-8859-1編碼,只是無法打印空字符:

byte[] b = { 123, -23, 54, 0, -92 }; 
String s = new String(b, "ISO-8859-1"); 
System.out.println(s); 
System.out.println((int) s.charAt(3)); 

編輯

在您發佈的代碼,它也很容易得到「載0「,如果你指定的UTF-16編碼:

byte[] bytes = s1.getBytes("UTF-16"); 

這是關於編碼,你沒有指定它。如果您沒有將其作爲參數傳遞給getBytes方法,則需要使用您的平臺默認編碼。

要找出那是你的平臺是什麼,這條命令:

System.out.println(System.getProperty("file.encoding")); 

在MacOS,它是UTF-8;在Windows上它可能是Cp-1252之類的Windows代碼頁之一。

java -Dfile.encoding=UTF16 <the rest> 

如果你運行你的代碼,這樣你還可以看到它包含0

1

是它始終是:當你運行Java您也可以在命令行上的平臺默認他們的.getBytes()字節數組除了空字符串之外總是不包含nero?

不,沒有這樣的保證。首先,最重要的是,.getBytes()使用平臺的默認字符集返回「」字節序列。因此,沒有任何東西阻止你從defining your own custom charset明確地將某些值編碼爲0s。

更實際上,許多常見的編碼將包括零字節,特別是代表NUL character。但即使您的字符串不包括NUL的字節序列可能包含0 s。特別是UTF-16(其中Java uses internally)表示兩個字節中的所有字符,意味着ASCII字符(僅需要一個)與0字節配對。


你也很容易通過嘗試從含有0 s的一個合適的構造函數,如String(byte[] bytes)String(byte[] bytes, Charset charset)字節序列構建String測試這個自己。例如(請注意我的系統默認的字符集是UTF-8):

System.out.println("Default encoding: " + System.getProperty("file.encoding")); 
System.out.println("Empty string: " + Arrays.toString("".getBytes())); 
System.out.println("NUL char: " + Arrays.toString("\0".getBytes())); 
System.out.println("String constructed from {0} array: " + 
        Arrays.toString(new String(new byte[]{0}).getBytes())); 
System.out.println("'a' in UTF-16: " + 
        Arrays.toString("a".getBytes(StandardCharsets.UTF_16))); 

打印:

Default encoding: UTF-8 
Empty string: [] 
NUL char: [0] 
String constructed from {0} array: [0] 
'a' in UTF-16: [-2, -1, 0, 97]