谨慎使用Encoding.Default

本文讨论了文本处理中编码(Encoding)的重要性,特别是针对中文字符。文章解释了ASCII、Default及GB2312编码的区别,并建议在处理中文时使用GB2312或Unicode编码以避免乱码问题。

     在处理文本时,经常需要处理Encoding的概念。存在这个问题的原因在于,在.NET程序内文本只是string和char对象,而保存到硬盘时,或者准备用socket把它发送出去时,都得先转换成byte[]或者字节流。而转换的算法,就是Encoding。Encoding不同文本文件的行数也不同。

老外的程序里面,都喜欢用Encoding.ASCII,这是因为他们主要只使用western字符;于是我们经常要在他们的代码把Encoding.ASCII替换成Encoding.Default才能使用。

所谓Encoding.Default,是指当前系统设置的“默认字符集编码方式”。你可以通过控制面板里面的区域选项设置它(这是在我的机器上的设定):



 

 

注意红色方框内的部分,“为你的非Unicode程序选择一个语言来匹配其本地语言版本”。这里选择了Chinese (PRC),则Encoding.Default等效于Encoding.GetEncoding("gb2312")。gb2312在代码页936,所以所有以双字节编码(ANSI编码)字符的程序在这个系统上会使用936代码页,使用Unicode的不受影响。

你可以看到 Encoding.Default的值是和系统设定相关的。这样,有些时候会出问题:一台机器用socket发送一段文本到另一台机器,两边都设定编码方式为Encoding.Default,但两台机器的区域选项的这个设置是不一样的,却没有被注意;如果发送的是非western字符,则接受方必然会得到乱码。这种问题往往会令人很困惑。

所以在面对中文且为ANSI编码的情况下,最好不要用Encoding.Default,而用 Encoding.GetEncoding("gb2312"),或者更直接的Encoding.GetEncoding(936);而如果有可能的话,最好全部使用unicode,比如utf-8,也就是Encoding.UTF8。有了unicode之后,其实我们不需要代码页的概念。

 

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using MES.Device.Control; using MES.Manager; namespace TsHardWare { /// <summary> /// 条码枪 /// </summary> public class HardWare_ScanBar : HardWareBase { public delegate void DelegateReadBar(List<string> listBar); public event DelegateReadBar OnReadBar; public HardWare_ScanBar(string strIP, int port) : base(strIP, port) { } public HardWare_ScanBar(int _port, int _baudRate, Parity _parity, int _dataBits, StopBits _stopBits) : base(_port, _baudRate, _parity, _dataBits, _stopBits) { } /// <summary> /// 是否运行 /// </summary> public bool isRun = true; /// <summary> /// 一直读取条码串口或者tcp是否有数据回传 /// </summary> public void StartReading() { new Thread(() => { string strBarCode = ""; while (isRun) { Thread.Sleep(100); byte[] buff = null; if (HardWare.Read(ref buff) > 0) { strBarCode += Encoding.Default.GetString(buff); } if (strBarCode.Contains(EndLine)) //aaa\r\naaa\r\n { List<string> listBar = new List<string>(); string strLeft = ""; listBar = HardWareDataHelper.GetAllDataBySplit(strBarCode, EndLine, ref strLeft); if (listBar != null && listBar.Count != 0 && OnReadBar != null) { OnReadBar.BeginInvoke(listBar, null, null); strBarCode = strLeft; } } } }) { IsBackground = true }.Start(); } #region 字段 /// <summary> /// 每次读取的延时时间2s /// </summary> public int ReadBarCodeTimeOut = 5000; /// <summary> /// 每次读取的尝试次数 /// </summary> public int ReadTryTime = 3; /// <summary> /// 开命令 /// </summary> public string strOnCmd = ""; /// <summary> /// 关命令 /// </summary> public string strOffCmd; /// <summary> /// 发送是不是采用16进制协议 /// </summary> public bool OnHex;//发送是不是16进制的 public bool OffHex; /// <summary> /// 锁读取 /// </summary> private object lockRead = new object(); #endregion #region 读取设备条码 /// <summary> /// 读取设备条码 /// </summary> /// <param name="BarCode"></param> /// <returns></returns> public bool ReadEquipData(ref string BarCode, int Multiple = 1) { if (IsSimulater)//模拟数据 { Thread.Sleep(201); BarCode = "SimulaterCode" + DateTime.Now.ToString("yyyyMMddHHmmssfff"); return true; } if (HardWare == null) throw new Exception("[扫码]-协议基础未初始化!"); if (strOnCmd == null || strOnCmd == "") return false; try { if (HardWare.HareWareType == EnumHardWareTypes.RTU) { return ReadEquipDataRTU(Multiple, ref BarCode); } else if (HardWare.HareWareType == EnumHardWareTypes.TCP) { return ReadEquipDataTCP(Multiple, ref BarCode); } else { //WriteLog.LogError("ReadEquipData()->HardWare.HareWareType:" + HardWare.HareWareType.ToString()); } } catch (Exception ex) { //WriteLog.LogError("ReadEquipData()->EX:" + ex); } return false; } /// <summary> /// 读取设备条码 /// </summary> /// <param name="BarCode"></param> /// <returns></returns> public bool ReadEquipDataRTU(int Multiple, ref string BarCode) { if (IsSimulater)//模拟数据 { Thread.Sleep(201); BarCode = "ScanBar" + DateTime.Now.ToString("yyyyMMddHHmmssfff"); return true; } if (HardWare == null) throw new Exception("[扫码]-协议基础未初始化!"); if (strOnCmd == null || strOnCmd == "") return false; lock (lockRead) { try { if (!HardWare.IsConn) { HardWare.Connect(); } Stopwatch sw = new Stopwatch(); byte[] byteSend = null; if (OnHex) { byteSend = strOnCmd.String2HexByteArray(); } else { byteSend = Encoding.ASCII.GetBytes(strOnCmd); } HardWare.DiscardBuff(); HardWare.Write(byteSend);//开命令 //Thread.Sleep(20); //SendBarCodeOff(); //再发一个测量 sw.Reset(); sw.Start(); string strBarCode = ""; byte[] buff = null; while (sw.ElapsedMilliseconds < ReadBarCodeTimeOut) { Thread.Sleep(10); if (HardWare.Read(ref buff) > 0) { strBarCode += Encoding.Default.GetString(buff); // WriteLog.LogScan("扫描枪返回原始值:" + strBarCode); } if (strBarCode.EndsWith(EndLine)) //aaa\r\naaa\r\n { //WriteLog.LogScan("扫描枪返回原始值,带有结束符:" + strBarCode + EndLine); BarCode = HardWareDataHelper.GetMyDataByEndLine(strBarCode, EndLine); SendBarCodeOff(); return BarCode != "ERROR" && BarCode != (Multiple == 1 ? "ERROR" : "ERROR,ERROR"); ; } } SendBarCodeOff(); return false; } catch (Exception ex) { //WriteLog.LogError("ReadEquipData()->EX:" + ex); return false; } } } /// <summary> /// 读取设备条码 /// </summary> /// <param name="BarCode"></param> /// <returns></returns> public bool ReadEquipDataTCP(int Multiple, ref string BarCode) { if (IsSimulater)//模拟数据 { Thread.Sleep(201); BarCode = "ScanBar" + DateTime.Now.ToString("yyyyMMddHHmmssfff"); return true; } if (HardWare == null) throw new Exception("[扫码]-协议基础未初始化!"); if (strOnCmd == null || strOnCmd == "") return false; lock (lockRead) { try { HardWare.Close(); if (!HardWare.IsConn) { HardWare.Connect(); } Stopwatch sw = new Stopwatch(); byte[] byteSend = null; if (OnHex) { byteSend = strOnCmd.String2HexByteArray(); } else { byteSend = Encoding.ASCII.GetBytes(strOnCmd); } HardWare.DiscardBuff(); HardWare.Write(byteSend);//开命令 Thread.Sleep(20); //SendBarCodeOff(); //再发一个测量 sw.Reset(); sw.Start(); string strBarCode = ""; byte[] buff = null; while (sw.ElapsedMilliseconds < ReadBarCodeTimeOut) { Thread.Sleep(10); if (HardWare.Read(ref buff) > 0) { strBarCode += Encoding.Default.GetString(buff); } if (strBarCode.EndsWith(EndLine)) //aaa\r\naaa\r\n { BarCode = HardWareDataHelper.GetMyDataByEndLine(strBarCode, EndLine); //SendBarCodeOff(); //WriteLog.LogScan(Name + "读取扫码枪返回解析值:" + strBarCode); return BarCode != "ERROR" && BarCode != (Multiple == 1 ? "ERROR" : "ERROR,ERROR"); ; } } //SendBarCodeOff(); //rebot(); return false; } catch (Exception ex) { //WriteLog.LogError("ReadEquipData()->EX:" + ex); return false; } } } #endregion #region 扫码枪关闭命令-有的扫码枪需要读去完成后关闭条码枪 /// <summary> /// 扫码枪关闭命令 /// </summary> void SendBarCodeOff() { if (HardWare != null && strOffCmd != null && strOffCmd.Length != 0) { byte[] byteSend = null; if (OnHex) { byteSend = strOffCmd.String2HexByteArray(); } else { byteSend = Encoding.ASCII.GetBytes(strOffCmd); } //WriteLog.LogScan(OnHex + "关命令:" + strOffCmd); HardWare.Write(byteSend); } } #endregion } }帮我解释一下这个代码
最新发布
10-06
private void ConnectPlatform() //打开控制卡与配置 { int netid, imcid, i; string err; netid = NetworkCard.SelectedIndex; imcid = ControlCardID.SelectedIndex; if (Global.isOpen())//设备已打开则关闭 { IMC_Pkg.PKG_IMC_Close(Global.g_handle); Global.g_handle = IntPtr.Zero; OpenControlCard.Text = "打开控制卡"; timer1.Enabled = false; } else { //有3种方法可连接控制卡,根据需要选择其中一个方法 #if true //方法1, Global.g_handle = IMC_Pkg.PKG_IMC_Open(netid, imcid); #elif false //方法2,使用方法1无法打开通过无线网卡连接的控制卡时,可使用方法2打开 Global.g_handle = IMC_Pkg.PKG_IMC_OpenX(netid, imcid, 40, 1); #else //方法3,使用密码连接控制卡 byte[] password = new byte[32]; string pw = "123456"; //此密码由iMCAT-6xxE软件或者PKG_IMC_SetPassword函数得到 password = System.Text.Encoding.Default.GetBytes(pw); Global.g_handle = IMC_Pkg.PKG_IMC_OpenUsePassword(netid, imcid, ref password[0], 6); #endif if (Global.isOpen()) { OpenControlCard.Text = ("关闭控制卡"); timer1.Enabled = true; //启动定时器,定时读取位置信息 Global.GetIMCInfo(); if (Global.g_naxis > 0) { ListViewItem lvitem; AxisMonitor.Items.Clear(); for (i = 0; i < Global.g_naxis; i++) { lvitem = AxisMonitor.Items.Add("轴" + i.ToString()); lvitem.SubItems.Add(("0")); lvitem.SubItems.Add(("0")); lvitem.SubItems.Add(("0x0000")); m_error_t[i] = 0; //存储第 i 个轴的错误状态或代码 m_curpos_t[i] = 0; //存储第 i 个轴的指令位置 m_encp_t[i] = 0; //存储第 i 个轴的编码器位置 } lvitem = AxisMonitor.Items.Add("encs"); lvitem.SubItems.Add(("0")); lvitem.SubItems.Add(("Ecat Error:")); lvitem.SubItems.Add(("0x00000000")); m_encs_t = 0; m_EcatErr_t = 0; } else { err = Global.GetFunErrStr(); MessageBox.Show(err); } } else { MessageBox.Show(("无法打开控制卡!\r\n\r\n请检查网卡和控制卡ID是否选择正确!")); } } } 我这个代码是在线程A中使用的,而NetworkCard、ControlCardID、timer1、AxisMonitor等控件是在UI线程的,我要如何修改代码
03-13
using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApp8 { public class TcpServer { static TcpClient tcpClient; static NetworkStream stream; private TcpListener tcpListener; private IPEndPoint serverIPEndPoint; private static int bytesRead = 0; private string msg = ""; public static string clientIpAddress; public bool IsRun { get; set; } public Thread ReceiveThread { get; private set; } public Thread SendThread { get; private set; } public TcpServer(string ip,int pot) { try { serverIPEndPoint = new IPEndPoint(IPAddress.Parse(ip), pot); // 当前服务器使用的ip和端口 } catch (Exception ex) { Console.WriteLine(ex.Message); Console.ReadKey(); } } /// <summary> /// 发送消息 /// </summary> public string SendMsg(string ADD, string message,int Num) { stream = tcpClient.GetStream(); if (stream.DataAvailable) { byte[] buffer = new byte[1024]; int bytesRead = stream.Read(buffer, 0, buffer.Length); } string[] result = ADD.ToString().Split('.'); int add1 = int.Parse(result[0]); int add2 = int.Parse(result[1]); int add3 = int.Parse(result[2]); int add4 = int.Parse(result[3]); List<byte> messageBytes = new List<byte>(); try { if (Num >= 256 || Num <= -1) { Num = 0; } if (add1 >= 256 || add1 <= -1) { add1 = 0; } if (add2 >= 256 || add2 <= -1) { add2 = 0; } if (add3 >= 256 || add3 <= -1) { add3 = 0; } if (add4 >= 256 || add4 <= -1) { add4 = 0; } messageBytes.Add(0x5A); messageBytes.Add((byte)Num); messageBytes.Add((byte)add1); messageBytes.Add((byte)add2); messageBytes.Add((byte)add3); messageBytes.Add((byte)add4); messageBytes.Add(0xE0); messageBytes.Add((byte)Encoding.Default.GetByteCount(message)); Encoding gbkEncoding = Encoding.GetEncoding("GBK"); var a = gbkEncoding.GetBytes(message); messageBytes.AddRange(a); byte temp2 = 0x00; for (byte i = 0; i < messageBytes.Count; i++) { temp2 += messageBytes[i]; } messageBytes.Add(temp2); lock (stream) { // messageBytes = Encoding.UTF8.GetBytes(message); // 将消息编码成字符串数组 stream.Write(messageBytes.ToArray(), 0, messageBytes.Count); Thread.Sleep(8000); msg = HandleClient(tcpClient); return msg; } } catch (Exception ex) { throw ex; } } /// <summary> /// 接收消息 /// </summary> private string HandleClient(TcpClient client) { stream = client.GetStream(); var temp = ""; byte[] buffer = new byte[1024]; // 缓冲区大小为1KB if (stream.DataAvailable) { try { // 接收客户端发送的数据 int bytesRead = stream.Read(buffer, 0, buffer.Length); if (bytesRead != buffer.Length) { Array.Resize(ref buffer, bytesRead); } var stringVar = new List<string>(); foreach (var item in buffer) { stringVar.Add(string.Format("{0:X2}", item)); } temp = string.Join(",", stringVar); } catch (Exception ex) { return "与客户端通信时发生错误"; } } return temp; } internal bool Start() { tcpListener = new TcpListener(serverIPEndPoint); tcpListener.Start(); Console.WriteLine("服务端已启用......"); // 阻塞线程的执行,直到一个客户端连接 tcpClient = tcpListener.AcceptTcpClient(); IPEndPoint remoteEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint; clientIpAddress = remoteEndPoint.Address.ToString(); Console.WriteLine("已连接."); IsRun = true; stream = tcpClient.GetStream(); // 创建用于发送和接受数据的NetworkStream ReceiveThread = new Thread(getstart); ReceiveThread.Start(); return true; } public void getstart() { } internal void Stop() { IsRun = false; tcpListener.Stop(); tcpClient.Close(); } } }using CDPT.Integration.DataAccess; using CDPT.Integration.Model; using CDPT.Integration.Utility; using ConsoleApp8; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Web; namespace CDPT.Integration.Service.PTMES4APP { /// <summary> /// APP_Andon 的摘要说明 /// </summary> public class APP_Andon : IHttpHandler { private static int num = 1; private static object locker = new object(); ICamstarAccess dataSource = DataAccessFactory.CreateDataSourceService(); public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; var request = JsonConvert.DeserializeObject<Req_Andon>(JsonHelper.GetRequestJson(context)); var response = new Res_Andon(); if (request == null||request.Message==null) { //接口返回 response = new Res_Andon() { code = "-1", msg = "相关参数不能为空..." }; context.Response.Write(JsonConvert.SerializeObject(response)); } else { try { string sql = $@"select GROUPADD,STATUS,BRACELETADD from pt_andon_info where equipment ='{request.Equipment}' and status = '{request.STATUS}'"; DataTable dt = dataSource.QueryFromCamstar(sql); if (dt!=null&&dt.Rows.Count>0) { string msg = SendTdpDataPacket(request.Message, dt.Rows[0][0].ToString()); List<string> listIP = new List<string>(); bool isReturn = false; string returnmsg = ""; for (int i=0;i<dt.Rows.Count;i++) { string[] segments = dt.Rows[i][2].ToString().Split('.'); string hexString = ""; foreach (string segment in segments) { // 转换为整数 uint value = uint.Parse(segment); // 转换为两个字符的十六进制字符串 string hexSegment = value.ToString("X2"); // 拼接结果 hexString += hexSegment+","; } listIP.Add(hexString); } for (int j =0;j<listIP.Count;j++) { if (msg.Contains(listIP[j])) { isReturn = true; break; } } if (isReturn) { response.code = "1"; response.msg = "对应同事已收到消息,在来的路上!"; returnmsg = "对应同事已收到消息,在来的路上!"; } else { response.code = "2"; response.msg = "响应超时,请重试"; returnmsg = "响应超时,请重试"; } string uuid = Guid.NewGuid().ToString(); string sql_insert = $@"insert into pt_andonhistory_info(UUID,EQUIPMENT,PACKAGETYPE,INFO,RESPONSIVE,STATUS,DATETIME) values('{uuid}','{request.Equipment}','{request.PACKAGETYPE}','{request.Message}','{returnmsg}','{dt.Rows[0][1]}',sysdate)"; int count = dataSource.ExecuteNonQuery(sql_insert); context.Response.Write(JsonConvert.SerializeObject(response)); } else { response.code = "0"; response.msg = "请联系对应人员进行配置"; context.Response.Write(JsonConvert.SerializeObject(response)); } } catch (Exception e) { response.code = "-1"; response.msg = $@"消息发送失败,{e.Message}"; context.Response.Write(JsonConvert.SerializeObject(response)); } } } public string SendTdpDataPacket(string message,string add) { try { lock (locker) // 确保同一时间只有一个线程能访问 { num++; } TcpServer server = new TcpServer("172.17.12.108", 4000); return server.SendMsg(add, message,num); } catch (Exception ex) { throw ex; } } public bool IsReusable { get { return false; } } public class Req_Andon { public string Message { get; set; } public string Equipment { get; set; } public string STATUS { get; set; } public string PACKAGETYPE { get; set; } } public class Res_Andon { public string code { get; set; } public string msg { get; set; } } } }using ConsoleApp8; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace CDPT.Integration.Service.PTMES4APP { /// <summary> /// APP_GetConnection 的摘要说明 /// </summary> public class APP_GetConnection : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; if (APP_CloseConnection.server?.IsRun ?? false) { APP_CloseConnection.server.Stop(); } if (APP_CloseConnection.server is null) APP_CloseConnection.server = new TcpServer("172.17.12.108", 4000); if (APP_CloseConnection.server.Start()) { context.Response.Write("连接建立成功"); } } public bool IsReusable { get { return false; } } } }改成可以多线程执行,每一个线程就是一次服务器向网关发生信息,并且接收信息的过程
07-28
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值