如果我將一個UTF-8字符轉換爲字節,那麼基於區域設置,環境等,這三種實現的結果是否會有所不同?單字節UTF-8到字節
byte a = "1".getBytes()[0];
byte b = "1".getBytes(Charset.forName("UTF-8"))[0];
byte c = '1';
如果我將一個UTF-8字符轉換爲字節,那麼基於區域設置,環境等,這三種實現的結果是否會有所不同?單字節UTF-8到字節
byte a = "1".getBytes()[0];
byte b = "1".getBytes(Charset.forName("UTF-8"))[0];
byte c = '1';
你的第一線是取決於環境,因爲這將編碼使用系統的默認字符編碼,這可能是也可能不是UTF-8的字符串。
無論系統的語言環境或默認字符編碼是什麼,第二行總會產生相同的結果。它將始終使用UTF-8對字符串進行編碼。
請注意,UTF-8是一種可變長度字符編碼。只有前127個字符被編碼在一個字節中;所有其他字符將佔用2到6個字節。
您的第三條線將char
投射到int
。這將導致int
包含字符的UTF-16字符代碼,因爲Java char
存儲使用UTF-16的字符。由於UTF-16以與UTF-8相同的方式對字符進行部分編碼,因此結果與第二行相同,但對於任何字符而言通常都不是這樣。
原則上的問題已經回答了,但我無法抗拒張貼有點潦草,對於那些誰喜歡玩弄代碼:
import java.nio.charset.Charset;
public class EncodingTest {
private static void checkCharacterConversion(String c) {
byte asUtf8 = c.getBytes(Charset.forName("UTF-8"))[0];
byte asDefaultEncoding = c.getBytes()[0];
byte directConversion = (byte)c.charAt(0);
if (asUtf8 != asDefaultEncoding) {
System.out.println(String.format(
"First char of %s has different result in UTF-8 %d and default encoding %d",
c, asUtf8, asDefaultEncoding));
}
if (asUtf8 != directConversion) {
System.out.println(String.format(
"First char of %s has different result in UTF-8 %d and direct as byte %d",
c, asUtf8, directConversion));
}
}
public static void main(String[] argv) {
// btw: first time I ever wrote a for loop with a char - feels weird to me
for (char c = '\0'; c <= '\u007f'; c++) {
String cc = new String(new char[] {c});
checkCharacterConversion(cc);
}
}
}
如果你運行這個例如與:
java -Dfile.encoding="UTF-16LE" EncodingTest
你將得不到輸出。 但當然,每一個字節(好吧,除了第一個)會,如果你嘗試是錯誤的:
java -Dfile.encoding="UTF-16BE" EncodingTest
因爲在「大端」的第一個字節始終是ASCII字符爲零。 這是因爲在UTF16 ASCII字符'\u00xy
由兩個字節表示的,在UTF16-LE如[xy, 0]
和UTF16-BE爲[0, xy]
但是隻有第一個語句產生任何輸出,所以b
和c
確實對於前127個ASCII字符也是如此 - 因爲在UTF-8中它們由單個字節編碼。然而,對於任何其他人物來說,這不會是真的。它們都使用UTF-8進行多字節表示。
絕對。試試「UTF-16值大於127的任何字符」。考慮到*有超過255個字符,您怎麼可能期望在不丟失信息的情況下將'char'轉換爲'byte'? – 2015-04-02 19:19:56
@JonSkeet那麼剛纔的127個字符呢? – tachyonflux 2015-04-02 19:50:37