B/S互動中為何出現亂碼個人淺析
前言:要理解這些你需要知道字元編碼的本質,壓縮和解壓縮的本質等
首先,客戶端在請求資料的時候並不知道伺服器會以什麼編碼返回資料,所以請求頭部會含有Accept-Encoding,Accept-Charset,Accept-language等資訊,這個的目的就是告訴伺服器自己可以接受的各種編碼和MIME型別等,但是我用代理工具攔截請求資料時發現,請求頭中很少有Accept-charset這個資訊,也就是說,客戶端並沒有指定自己可以接受的編碼型別,或者說客戶端可以接受任何的編碼型別,這就導致伺服器總是按照自己設定的或者被開發者指定的編碼方式傳送資料給客戶端,這其實才是亂碼的本質。
再來詳細解釋一下我對亂碼的理解,剛已經說過,客戶端很少指定自己可接受的編碼方式,因為現在的作業系統,客戶端或者說是瀏覽器幾乎可以解析任何的編碼格式,因此沒有必要指定編碼(題外話,如果指定的話,一個請求就需要增加幾十個字元所佔用的位元組,整個網際網路一秒鐘所傳送的請求量之大我們難以想象,這幾十個位元組再乘以請求量可以想象為整個網路所帶來的網路負載有多大,經濟損失又得多大。。。)。現在客戶端請求傳送到了伺服器,首先監測伺服器被請求頁面有沒有指定編碼格式,沒有則是按照預設的方式,如果既沒有指定,而且伺服器頁面又有中文,那麼伺服器回送給客戶端的資料是按照預設的ISO-8859-1進行編碼的,同時會告訴客戶端用這個編碼進行解碼,此時亂碼自然就出現了,此時我們需要想到為什麼B/S用的同樣的編碼方式,為什麼伺服器看起來是正常,而客戶端亂碼呢?這是因為伺服器端有自己的資料編碼方式,假設“程式設計師”這三個字,伺服器顯示的時候用的是utf-8,utf-8的二進位制是1010110 0011101 110101(不要在意錯對,重在原理) ,而伺服器回送資料的時候按照預設的ISO-8859-1進行傳送,假設這種編碼一個字元用5個二進位制位,那麼此時原來的編碼就成了10101 10001 11011 10101,三個字變成了五個字,不亂碼才怪,(要理解這個需要再加一點東西:不管什麼編碼,不同的客戶端在顯示同一個資料的時候用的是同一個資料實體,而不同的客戶端則用的不同的編碼演算法進行字元編碼,那麼同一個資料實體所解析出來的資料自然不一樣。同樣,伺服器顯示資料的時候用的編碼,與伺服器傳送資料的時候用的編碼也是互不影響的,但是他們用的是同一個資料實體)。
請求通過Servlet的時候出現亂碼,這又是為什麼呢?同樣的道理,在Servlet變成中,在解析請求資料之前經常可以看到request.setCharacterEncoding("UTF-8");這個就是告訴接下來的程式程式碼,客戶端請求的資料是以utf-8的編碼方式編碼的,然後伺服器中的Servlet或者JSP或者其他解析器就會按照指定的編碼方式進行解碼,那麼就不會出現亂碼了。
request.getParameter("name")).getBytes("ISO-8859-1"),"UTF-8");這段程式碼應該見過,這個的本質其實就是String.getBytes("A","B");將A編碼的資料轉換成utf-8的編碼方式,這是因為request.getParameter("name"))是以ISO-8859-1編碼方式得到資料,然後getBytes("ISO-8859-1"),"UTF-8")再將這個編碼的二進位制進行底層的轉換變成utf-8的編碼方式,這可能使得資料發生變化,因為不同的編碼方式佔用的位元組數不一樣。
《個人暫時理解,可能有錯,僅供參考》