對 ActiveMQ .NET 1.1.0 元件接受中文資訊亂碼的修復
最近在使用 Apache ActiveMQ 訊息佇列做一些工作,在使用的時候,發現傳送訊息的內容是中文時,獲得訊息時,獲得的是亂碼。
傳送和接收我使用的是 ActiveMQ .NET 1.1.0 元件。
分析原因進去後,發現是這個開源元件的 Apache.NMS.ActiveMQ 元件的 \Apache.NMS.ActiveMQ-1.1.0-src\src\main\csharp\Transport\Stomp\StompWireFormat.cs 檔案對應的 StompWireFormat 類的 public Object Unmarshal(BinaryReader dis) 方法中有錯誤。
錯誤在該檔案的 166 行
之前的錯誤程式碼如下:
public Object Unmarshal(BinaryReader dis) { string command; do { command = ReadLine(dis); } while (command == ""); Tracer.Debug("<<<< command: " + command); IDictionary headers = new Hashtable(); string line; while ((line = ReadLine(dis)) != "") { int idx = line.IndexOf(':'); if (idx > 0) { string key = line.Substring(0, idx); string value = line.Substring(idx + 1); headers[key] = value; Tracer.Debug("<<<< header: " + key + " = " + value); } else { // lets ignore this bad header! } } byte[] content = null; string length = ToString(headers["content-length"]); if (length != null) { int size = Int32.Parse(length); content = dis.ReadBytes(size); // Read the terminating NULL byte for this frame. int nullByte = dis.Read(); if(nullByte != 0) { Tracer.Debug("<<<< error reading frame. null byte."); } } else { MemoryStream ms = new MemoryStream(); int nextChar; while((nextChar = dis.Read()) != 0) { if( nextChar < 0 ) { // EOF ?? break; } ms.WriteByte((byte)nextChar); } content = ms.ToArray(); } Object answer = CreateCommand(command, headers, content); Tracer.Debug("<<<< received: " + answer); return answer; } internal String ReadLine(BinaryReader dis) { MemoryStream ms = new MemoryStream(); while (true) { int nextChar = dis.Read(); if (nextChar < 0) { throw new IOException("Peer closed the stream."); } if( nextChar == 10 ) { break; } ms.WriteByte((byte)nextChar); } byte[] data = ms.ToArray(); return encoding.GetString(data, 0, data.Length); }
這個原始碼檔案可以在下面地址看到:
正確的程式碼如下:
internal string ReadLine(NetworkStream ns) { MemoryStream ms = new MemoryStream(); while (true) { int nextChar = ns.ReadByte(); if (nextChar < 0) { throw new IOException("Peer closed the stream."); } if (nextChar == 10) { break; } ms.WriteByte((byte)nextChar); } byte[] data = ms.ToArray(); return encoding.GetString(data, 0, data.Length); } public Object Unmarshal(BinaryReader dis) { NetworkStream ns = dis.BaseStream as NetworkStream; if (ns == null) return null; if (!ns.CanRead) return null; // 讀取 command 資訊 string command; do { command = ReadLine(ns); } while (command == ""); Tracer.Debug("<<<< command: " + command); // 讀取 header 資訊 IDictionary headers = new Hashtable(); string line; while ((line = ReadLine(ns)) != "") { int idx = line.IndexOf(':'); if (idx > 0) { string key = line.Substring(0, idx); string value = line.Substring(idx + 1); headers[key] = value; Tracer.Debug("<<<< header: " + key + " = " + value); } else { // lets ignore this bad header! } } // 讀取訊息內容 MemoryStream ms = new MemoryStream(); do { int t = ns.ReadByte(); if (t <= 0) break; ms.WriteByte((byte)t); } while (ns.DataAvailable); byte[] content = ms.ToArray(); Object answer = CreateCommand(command, headers, content); Tracer.Debug("<<<< received: " + answer); return answer; }
之前的錯誤程式碼,在傳送“a1郭紅俊b2” 這樣的中英文數字混合的資訊時,傳送時,傳送的 byte陣列 資訊如下:
97,49,233,131,173,231,186,162,228,191,138,98,50
接受時,接受到的 byte 陣列資訊就變成了
97,49,239,191,189,239,191,189,98,50
原先的 BinaryReader dis 其實是個這個開源元件自己寫的派生自BinaryReader 的 OpenWireBinaryReader 類。這個類有很多不完善的地方。
這部分的邏輯可以在 TcpTransport 類的下面呼叫中看到
private readonly Socket socket;
private BinaryReader socketReader;
socketReader = new OpenWireBinaryReader(new NetworkStream(socket));
原先的 OpenWireBinaryReader 不完善的地方:
1、傳送中文時,會丟資料;ms.WriteByte((byte)nextChar); 會讓本來nextChar對應的 byte 陣列,只取了陣列的第一項,陣列的其他項則丟失了;
2、編碼混亂,unicode 和 utf-8 轉換有問題。
參考資料:
Apache ActiveMQ
http://activemq.apache.org/
ActiveMQ .NET
http://activemq.apache.org/nms/
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-616448/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 二進位制修復中文亂碼的問題
- telnet AIX 中文亂碼AI
- win10軟體亂碼如何解決 win10開啟軟體中文亂碼怎麼修復Win10
- win10英文版改中文亂碼怎麼解決_win10英文版改中文部分文字亂碼修復方法Win10
- uploadify-v3.1 java 例項 修復補充中文檔名亂碼問題Java
- Android熱修復原理(一)熱修復框架對比和程式碼修復Android框架
- vs2017引用vue元件中文亂碼Vue元件
- mysql中文亂碼MySql
- secureCRT中文亂碼Securecrt
- oracle 中文亂碼Oracle
- PHP中文亂碼PHP
- gedit中文亂碼
- gitk中文亂碼Git
- plsql中文亂碼SQL
- .Net Core踩坑記:讀取txt中文亂碼
- win10遊戲亂碼怎麼解決_win10部分遊戲亂碼修復方法Win10遊戲
- 中文亂碼的總結薦
- java的中文亂碼轉換Java
- java web 中文亂碼JavaWeb
- JS cookie 中文亂碼JSCookie
- solaris程式檔案屬性紊亂的修復
- .net客戶端呼叫activeMQ程式碼客戶端MQ
- asp.net查出 oracle資料庫中的中文亂碼問題ASP.NETOracle資料庫
- asp.net中引入外部js檔案的中文亂碼問題ASP.NETJS
- Get提交方式中文亂碼
- JD-GUI中文亂碼GUI
- EasyUI 中文亂碼問題UI
- oracle中文顯示亂碼Oracle
- RHEL中文亂碼解決
- HttpClient 解決中文亂碼HTTPclient
- MSSQL中文亂碼問題SQL
- Java 中文 亂碼問題Java
- jsp 中文亂碼急救JS
- include jsp 中文亂碼JS
- MySQL解決中文亂碼MySql
- java,awt,中文方框,中文亂碼10/16Java
- Asp.netcore中由於頁面編碼導致的中文亂碼ASP.NETNetCore
- win10瀏覽器亂碼如何解決_win10瀏覽器字型亂碼修復方法Win10瀏覽器