摘要:我們下面的代碼是從一個流中讀取編碼的字符串。例如,笑臉符號有時會被解碼為個未知字符編碼字符串解碼字符串我們知道可以使用到個字節(jié)來表示一個字符,有關(guān)字符串編碼的知識可以參考字符編碼一文。參考資料字符編碼教程
我們下面的代碼是從一個流 stream 中讀取 UTF-8 編碼的字符串。我們可以先考慮一下其中存在的潛在問題。
string ReadString(Stream stream){ var sb = new StringBuilder(); var buffer = new byte[4096]; int readCount; while ((readCount = stream.Read(buffer)) > 0) { var s = Encoding.UTF8.GetString(buffer, 0, readCount); sb.Append(s); } return sb.ToString();}
問題出在:某些情況下返回的字符串與與原始編碼的字符串并不同。
例如,笑臉符號???? 有時會被解碼為 4 個未知字符:
編碼字符串: ????解碼字符串: ????
我們知道:UTF-8 可以使用 1 到 4 個字節(jié)來表示一個 Unicode 字符,有關(guān)字符串編碼的知識可以參考 ??字符編碼??? 一文。
??Stream.Read??? 方法可以把從 1 到?? messageBuffer.Length??? 字節(jié)返回,這意味著緩沖區(qū)可能包含不完整的 UTF-8 字符。
一旦緩沖區(qū)中的最后一個字符的 UTF-8 編碼不完整,那么 ??Encoding.UTF8.GetString?? 就是轉(zhuǎn)換一個無效的 UTF-8 字符串。在這種情況下,該方法返回一個無效字符串,因為它無法猜測丟失的字節(jié)。
我們使用以下代碼演示以上行為:
var bytes = Encoding.UTF8.GetBytes("?");// bytes = new byte[4] { 240, 159, 152, 138 }var sb = new StringBuilder();// 模擬逐個字節(jié)地讀取數(shù)據(jù)流for (var i = 0; i < bytes.Length; i++){ sb.Append(Encoding.UTF8.GetString(bytes, i, 1));}Console.WriteLine(sb.ToString());// "????" 代替了 "????"Encoding.UTF8.GetBytes(sb.ToString());// new byte[12] { 239, 191, 189, 239, 191, 189, 239, 191, 189, 239, 191, 189 }
有多種方法可以修復(fù)代碼。
第一種方法:只有當(dāng)你得到全部數(shù)據(jù)時,才將字節(jié)數(shù)組轉(zhuǎn)換為字符串。
string ReadString(Stream stream){ using var ms = new MemoryStream(); var buffer = new byte[4096]; int readCount; while ((readCount = stream.Read(buffer)) > 0) { ms.Write(buffer, 0, readCount); } return Encoding.UTF8.GetString(ms.ToArray());}
第二種方法:可以把流包進(jìn)一個具有正確編碼的 StreamReader 對象中。
string ReadString(Stream stream){ using var sr = new StreamReader(stream, Encoding.UTF8); return sr.ReadToEnd();}
另外,還可以使用System.Text.Decoder類來正確解碼緩沖區(qū)內(nèi)的字符。在需要性能的情況下,可以使用PipeReader、Rune類來以內(nèi)存優(yōu)化的方式讀取數(shù)據(jù)。
參考資料:
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/124125.html
摘要:我們下面的代碼微軟雅黑是從一個流中讀取編碼的字符串。微軟雅黑問題出在某些情況下返回的字符串與與原始編碼的字符串并不同。第一種方法只有當(dāng)你得到全部數(shù)據(jù)時,才將字節(jié)數(shù)組轉(zhuǎn)換為字符串。 我們下面的代碼是從一個流 stream 中讀取 UTF-8 編碼的字符串。我們可以先考慮一下其中存在的潛在問題。?string ReadStri...
摘要:過濾器流,如等,是類庫,是為了提供一些類讓你能夠處理一些極為常見的數(shù)據(jù)格式。讀寫器,由于流和過濾器流還是僅次于處理字節(jié),也就是二進(jìn)制。過濾器流緩沖流和類將寫入的數(shù)據(jù)存儲到緩沖區(qū)中一個名為的保護(hù)字節(jié)數(shù)組字段,直到緩沖區(qū)滿或刷新輸出流。 A little older, a little wiser, but happy to see you. ——Interstellar 2018年了,再...
摘要:如果不指定字符集,則使用系統(tǒng)默認(rèn)字符編碼,系統(tǒng)的默認(rèn)字符編碼一般是。所以更準(zhǔn)確的說,是將一個字節(jié)輸入流按照給定的字符編碼來解碼,從而得到一個字符輸入流。當(dāng)然,缺點就是不能選擇使用的字符編碼。 相對于Python和 C來說,Java的I/O操作API比較復(fù)雜,因此本文打算做個簡單的介紹。 1. I/O分類 總的來說Java的I/O按照處理數(shù)據(jù)的粒度和方向來劃分,一共可以分為4類: 基...
摘要:不同類型的流入,往往對應(yīng)于不同類型的流數(shù)據(jù)。所以通常會將字節(jié)緩存到一定數(shù)量后再發(fā)送。如果是,則將兩個標(biāo)記都拋棄并且將之前的內(nèi)容作為一行返回。因此二者陷入死鎖。因此推出了和類。 前言 最近在重拾Java網(wǎng)絡(luò)編程,想要了解一些JAVA語言基本的實現(xiàn),這里記錄一下學(xué)習(xí)的過程。 閱讀之前,你需要知道 網(wǎng)絡(luò)節(jié)點(node):位于網(wǎng)絡(luò)上的互相連通的設(shè)備,通常為計算機(jī),也可以是打印機(jī),網(wǎng)橋,路由器等...
摘要:是一個系統(tǒng)支持的所有字符的集合,包括各國家文字標(biāo)點符號圖形符號數(shù)字等字符集簡體中文碼表。支持中國國內(nèi)少數(shù)民族的文字,同時支持繁體漢字以及日韓漢字等字符集為表達(dá)任意語言的任意字符而設(shè)計,是業(yè)界的一種標(biāo)準(zhǔn),也稱為統(tǒng)一碼標(biāo)準(zhǔn)萬國碼。 1 File1.1 File類的概述和構(gòu)造方法File: 它是文件和目錄路徑名的抽象...
閱讀 3020·2021-11-22 12:06
閱讀 603·2021-09-03 10:29
閱讀 6553·2021-09-02 09:52
閱讀 2022·2019-08-30 15:52
閱讀 3417·2019-08-29 16:39
閱讀 1194·2019-08-29 15:35
閱讀 2067·2019-08-29 15:17
閱讀 1425·2019-08-29 11:17