兩個進程間通過網絡傳輸字符串
在計算機底層傳輸?shù)闹挥行稳?code>01011101這種數(shù)字,1字節(jié)是由8位bit組成走哺,而字符則是在某種字符集下字節(jié)的表現(xiàn)形式蚯嫌,最終都是通過一串01數(shù)字表達。當我們談論字符而忽略字符集時是完全沒有意義的丙躏,之所以有時不用去關心字符集是因為平臺往往是有個默認的字符集择示。所以在傳輸字符的時候,發(fā)送方和接收方必須要事先約定好字符集晒旅。
下面的例子摘自《Java特種兵》書籍的第四章
例如發(fā)送2個漢字栅盲,用UTF-8編碼發(fā)送后會占用6個字節(jié),對方若知道傳來的數(shù)據是UTF-8編碼废恋,便知道這6個字節(jié)代表什么漢字剪菱,就自然能正確得到char字符了。但是如果對方用GBK來編碼拴签,則可能會認為有3個字符孝常,若按照每2個字節(jié)計算一個字符,得到的3個字符自然不是需要傳遞的2個漢字字符蚓哩。假如此時意識到自己的編碼錯誤了构灸,通過得到的3個字符的字符串調用get-Byte(“GBK”)還可以還原6個字節(jié),然后通過這6個字節(jié)再用new String(byte[]岸梨,“UTF-8”)得到實際的兩個漢字喜颁。真的是這樣嗎?要知道這是偶然的曹阔,不是必然的半开,因為UTF-8轉換出來的6個字節(jié),當按照每2個字節(jié)組成編碼時赃份,這個編碼未必在GBK的編碼范圍內寂拆,若不在GBK的編碼范圍內,就可能會用一個“抓韩?”或其他字符來代表纠永,由于“?”本身也是一個字符谒拴,當再次調用get-Byte(“GBK”)時得到的對應字節(jié)就是“尝江?”對應的字節(jié),而不是原來字符的字節(jié)英上,有可能都不再是6個字節(jié)了炭序。換句話說啤覆,這樣的情況是永遠無法轉換回來的。
字節(jié)流和字符流的關系
Reader/Writer內在的實現(xiàn)是通過sun.nio.cs.StreamDecoder惭聂、sun.nio.cs.StreamEn-coder來對字符集進行處理窗声,最終還是通過字節(jié)來完成發(fā)送和接收的。
read()的小疑惑
InputStream.read()
方法返回一個int值彼妻,表示從流中讀取的一個字節(jié)嫌佑。我們知道byte類型的取值范圍是:-128到127豆茫,但是read方法返回值的范圍是0 - 255(另外返回-1表示流中沒有可讀字節(jié))侨歉。
為什么要這樣設計呢?其中一個原因是因為字符集的碼表都是用非負數(shù)來表示的揩魂。
那如何進行轉換呢幽邓?在BufferedInputStream
中,其read()方法是這樣寫的
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return buf[pos++] & 0xff;
}
其中buf是byte數(shù)組火脉,可以看到通過buf[pos++] & 0xff
將字節(jié)的范圍轉移到0 - 255牵舵。
按用途分類流
字節(jié)輸入流 | 字節(jié)輸入流 | 字符輸入流 | 字符輸出流 | |
---|---|---|---|---|
基礎 | InputStream | OutputStream | Reader InputStreamReader | Writer OutputStreamWriter |
數(shù)組 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
文件 | FileInputStream RandomAccessFile | FileOutputStream RandomAccessFile | FileReader | FileWriter |
網絡 | SocketInputStream URL HttpURLConnection Socket | SocketOutputStream URL HttpURLConnection Socket | ||
管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
緩沖 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
Filtering | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter |
解析 | PushbackInputStream StreamTokenizer | PushbackReader LineNumberReader | ||
String | StringReader | StringWriter | ||
Data | DataInputStream | DataOutputStream | ||
格式 | PrintStream | PrintWriter | ||
序列化 | ObjectInputStream | ObjectOutputStream | ||
Utilities | SequenceInputStream LineNumberInputStream | LineNumberReader |
擴展閱讀
Java IO Tutorial