【编码续】 www_123du_com请进!

是是非非 2006-09-25 08:56:30
http://community.csdn.net/Expert/topic/5044/5044314.xml?temp=.4205438

System.Text.Encoding.GetEncoding("GB2312").GetDecoder()....

//对流进行编码解码由于可能存在碎片现象,请使用Encoding.GetDecoder和GetEncoder方法获取编码解码器对其进行操作,Decoder和Encoder都会记录本次留下的碎片,第二次继续使用。

//不知你是不是这个原因。

老大,我一直怀疑是这个问题
能不能详细解释一下?

因为我在一次偶然的刷新时候,发现有一次竟然输出了剩下的部分
...全文
727 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
Csharp110 2006-09-26
  • 打赏
  • 举报
回复
学习中,帮顶!
www_123du_com 2006-09-26
  • 打赏
  • 举报
回复
呵呵,是我在楼主一个已经结贴的地方回复了,楼主才重开一个贴的,不是倒分贴。

其实说白了很简单,每一个字符被编码成byte后都不止一个byte,而是多个byte。只有当这多个byte在一起时才能正常解码。
而在流里面是直接传输byte序列,则有可能在第一次传输时的最后一个byte刚好要和第二次的第一个byte加在一起才是一个完整的字符,即本来两个byte表示一个字符传输时被截断(当然在byte模式下机器根本不知道这两个byte有任何关系)。于是第一次解码时最后一个字节由于不完整,则会被丢弃。而第二次解码时就有可能是乱码了。
.NET提供了Decoder和Encoder专门解决这种情况,它会将前一次解码剩下的不完整byte缓存起来,下一次解码时和前一个byte一起解码,于是就安全了。
antoniusguo 2006-09-26
  • 打赏
  • 举报
回复
接收以前先调用一下
this.decoder.Reset();

if(remoteSocket.Poll(10, System.Net.Sockets.SelectMode.SelectRead)
{
System.Int32 dataReceived;
System.Byte[] buffer = new System.Byte[1024];
System.Text.StringBuilder sBuilder = new System.Text.StringBuilder();
this.decoder.Reset();//这里加上



对于这个我也不是很熟,还要多看看大家意见,搞错不要介意啊
antoniusguo 2006-09-26
  • 打赏
  • 举报
回复
也不是很明白到底是什么意思,不过我觉得可以等每一次发的数据接收完了一起解码
while(true)
{
if(remoteSocket.Poll(10, System.Net.Sockets.SelectMode.SelectRead)
{
System.Int32 dataReceived;
System.Byte[] buffer = new System.Byte[1024];
CustomBuffer cb = new CustomBuffer();//这个还要自己实现一下
do
{
dataReceived = remoteSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
cb.Write(buffer, 0, dataReceived);
}
while(dataReceived > 0);
System.Byte[] receivedBytes = cb.GetReceivedBytes();
System.String data = this.encoding.GetString(receivedBytes);
}
}
我觉得类似这样应该可以


比如解码以后应该有2000字节
正常情况只输出1500字节

偶尔刷新快,能看到分两次的 1500字节和剩下的500字节

能不能再具体一点


或者可以这样
while(true)
{
if(remoteSocket.Poll(10, System.Net.Sockets.SelectMode.SelectRead)
{
System.Int32 dataReceived;
System.Byte[] buffer = new System.Byte[1024];
System.Text.StringBuilder sBuilder = new System.Text.StringBuilder();
do
{
dataReceived = remoteSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
System.Char[] receivedChars = new System.Char[this.decoder.GetCharCount(buffer, 0, dataReceived);
this.decoder.GetChars(buffer, 0, dataReceived, receivedChars, 0);
sBuilder->Append(receivedChars);
}
while(dataReceived > 0);
System.String data = sBuilder.ToString();
//引发事件
}
}
ILoveSee 2006-09-26
  • 打赏
  • 举报
回复
CSDN就这点不好,要持续回贴就要靠马甲了
上面写错判断条件了
if (charCount < testBytes.Length)
头晕晕的
应该是这样
if (byteUsed < fullBytes.Length)

==========================================

System.Text.Encoding utf8Encoding = System.Text.Encoding.UTF8;
System.String str = "我的测试(test)";
System.Byte[] fullBytes = utf8Encoding.GetBytes(str);
System.Byte[] testBytes = new System.Byte[fullBytes.Length - 1];

System.Buffer.BlockCopy(fullBytes, 0, testBytes, 0, testBytes.Length);

System.Text.Decoder decoder = utf8Encoding.GetDecoder();
decoder.Reset();

System.Char[] result = new System.Char[decoder.GetCharCount(testBytes, 0, testBytes.Length, false)];
System.Int32 byteUsed;
System.Int32 charCount;
System.Boolean completed;
decoder.Convert(testBytes, 0, testBytes.Length, result, 0, result.Length, false, out byteUsed, out charCount, out completed);
System.String decodedStr = new System.String(result);
Console.WriteLine("DecodedString is: '" + decodedStr + "'");
if (byteUsed < fullBytes.Length)
{
Console.WriteLine("Not Completed");
}
else
{
Console.WriteLine("Completed");
}
Console.ReadLine();
antoniusguo 2006-09-26
  • 打赏
  • 举报
回复
System.Text.Encoding utf8Encoding = System.Text.Encoding.UTF8;
System.String str = "我的测试(test)";
System.Byte[] fullBytes = utf8Encoding.GetBytes(str);
System.Byte[] testBytes = new System.Byte[fullBytes.Length - 1];

System.Buffer.BlockCopy(fullBytes, 0, testBytes, 0, testBytes.Length);

System.Text.Decoder decoder = utf8Encoding.GetDecoder();
decoder.Reset();

System.Char[] result = new System.Char[decoder.GetCharCount(testBytes, 0, testBytes.Length, false)];
System.Int32 byteUsed;
System.Int32 charCount;
System.Boolean completed;
decoder.Convert(testBytes, 0, testBytes.Length, result, 0, result.Length, false, out byteUsed, out charCount, out completed);
System.String decodedStr = new System.String(result);
Console.WriteLine("DecodedString is: '" + decodedStr + "'");
if (charCount < testBytes.Length)
{
Console.WriteLine("Not Completed");
}
else
{
Console.WriteLine("Completed");
}
Console.ReadLine();
antoniusguo 2006-09-26
  • 打赏
  • 举报
回复
得到的结果和GetChars是一样的,用发也差不多,不过有3个out参数,麻烦一点,而且,就算相同也不能说名全部完成了,可能是凑巧
antoniusguo 2006-09-26
  • 打赏
  • 举报
回复
使用Convert方法,其中有1个参数指示已有多少Byte被使用,和你的参数含有的Byte的数量进行比较如果相同说明已经完成,如果小于你参数的Byte数,说明没有完成
jrl5365 2006-09-26
  • 打赏
  • 举报
回复
不会,顶一下,学习一下了
www_123du_com 2006-09-26
  • 打赏
  • 举报
回复
如果你接收完了所有byte一起解码,就不会有问题,只因为你是一部分一部分解码的。

在实际操作中,你没有必要知道此次解码的byte组有没有剩余。因为有Decoder处理了。

如果你只是做测试用,那么简单,你把解码后的string再用相同的编码再编码一次,与原byte[]比较长度,如果相等,说明没有剩余byte,如果原byte[]长一些,那么长出来的部分就是剩余的byte。
是是非非 2006-09-26
  • 打赏
  • 举报
回复
.NET提供了Decoder和Encoder专门解决这种情况,它会将前一次解码剩下的不完整byte缓存起来,下一次解码时和前一个byte一起解码,于是就安全了。

================
怎样才能知道一次解码有没有完整呢?
是是非非 2006-09-25
  • 打赏
  • 举报
回复
比如解码以后应该有2000字节
正常情况只输出1500字节

偶尔刷新快,能看到分两次的 1500字节和剩下的500字节
califord 2006-09-25
  • 打赏
  • 举报
回复
并不理解你这样做的用意
antoniusguo 2006-09-25
  • 打赏
  • 举报
回复
200分还在这么后面,以为是倒分贴...
如果是UTF-8编码,那么每个Char占3个System.Byte,(如果<127好象还是1个Byte)
假设全是3个Byte的字符,而有100个Byte(比如Socket只接受了1半数据),那就多了1Byte,不能被全部被解码,所以Decoder保留这1Byte(丢掉的话问题就严重了),与接下来接收到的Byte组合再次解码

因为我在一次偶然的刷新时候,发现有一次竟然输出了剩下的部分
剩余的部分是指什么?
chaircat 2006-09-25
  • 打赏
  • 举报
回复
MSDN中关于Decoder的备注:

此类的实现通过连续调用 GetChars 方法将已编码的字节块转换为 Unicode 字符块。此类在 GetChars 的连续调用之间维护状态信息,使它能够对跨越相邻块的字节序列进行解码。例如,使用 GetChars 对没有特定结尾的字节序列(如流)进行解码。
是是非非 2006-09-25
  • 打赏
  • 举报
回复
虽然我现在用分段的方式解决了
但总觉得有一些遗憾,希望能进一步了解

是是非非 2006-09-25
  • 打赏
  • 举报
回复
www_123du_com能否解释一下相关的知识?

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧