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