大家来支招吧!C# 字节编码成字符串

lisa9342 2012-07-05 01:42:06
http://topic.csdn.net/u/20120705/11/4b20d635-cfe0-4c12-8384-2a7d17e22cad.html?56443


上午发的帖子没人回,自己不能再回复了,就再发一个,大家去看看,两边都给分,就是想解决问题呀!
...全文
194 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lisa9342 2012-07-09
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:
调试结果是通的,结果被我们测试人员又给测出毛病来了
原来我那个防误删的模块忘了考虑前面连续是汉字的情况,只考虑了前面是ASCII码的情况,这样的话,如果最后一个字节刚好截的是一个汉字的前半个字节,那就又乱码了。

现在我想了个方法,能不能判断下:当最后一个字节>127,它的前边也>127时,判断它后面连续的非ASCII码的字节的个数,如果是奇数个,那就删掉它,如果是偶数个,那就保留它。


最重要是红色的那两个条件,怎么实现



[/Quote]
lisa9342 2012-07-09
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
补充说明,以上方法,只适用于假设你前面的字符都是完整的,而最后一个字符不确定是否完整的情况。
[/Quote]


谢谢 可是我这边的情况是文件名里不只是汉字,还有各种文件名中允许出现的ASCII码,下面是我写的程序,大家看下:

string path = f;
string newpath = path;
string fullname = Path.GetFileName(path);//返回文件名和后缀名
string name = Path.GetFileNameWithoutExtension(path);//返回文件名
string extn = Path.GetExtension(path);//返回后缀名
byte[] Bytes = System.Text.Encoding.Default.GetBytes(fullname);//获得文件名+后缀名的字节数组
byte[] nameBytes = System.Text.Encoding.Default.GetBytes(name);//获得文件名的字节数组
byte[] extnBytes = System.Text.Encoding.Default.GetBytes(extn);//获得后缀名的字节数组
string newname = fullname;//新(文件名+后缀名)
while (Bytes.Length > 128)
{
Common.ImportDllCom.SetProfile(Utils.LogName, "log", fullname + "(" + DateTime.Now.ToString("yyyyMMddHHmmss") + ")", "文件名长度超限");
int cutCount = Bytes.Length - 128;
int initialCopyCount = nameBytes.Length - cutCount;
int finalCopyCount;


//排除误截汉字编码的可能
if (nameBytes[initialCopyCount - 1] > 127)
{
if (nameBytes[initialCopyCount - 2] > 127)
{
finalCopyCount = initialCopyCount;
}
else
{
finalCopyCount = initialCopyCount - 1;
cutCount = cutCount + 1;
}
}
else
finalCopyCount = initialCopyCount;

ArrayList al = new ArrayList();
al.InsertRange(0, nameBytes);//这里是将文件名部分完全添加到ArrayList中
al.RemoveRange(finalCopyCount, cutCount);//根据需要截取的长度,删除ArrayList中多余的元素
al.InsertRange(finalCopyCount, extnBytes);//将后缀名部分添加到ArrayList的最后
byte[] newNameBytes = new byte[al.Count];//根据ArrayList中的元素数目新建字节数组
al.CopyTo(newNameBytes);//将ArrayList中的所有元素复制到新文件名的字节数组中
newname = System.Text.Encoding.Default.GetString(newNameBytes);//将新文件名的字节数组编码成字符串
byte[] test = System.Text.Encoding.Default.GetBytes(newname);

newpath = Path.GetDirectoryName(path).TrimEnd('\\') + "\\" + newname;
break;
}
File.Move(path, newpath);//改文件名




调试结果是通的,结果被我们测试人员又给测出毛病来了
原来我那个防误删的模块忘了考虑前面连续是汉字的情况,只考虑了前面是ASCII码的情况,这样的话,如果最后一个字节刚好截的是一个汉字的前半个字节,那就又乱码了。

现在我想了个方法,能不能判断下:当最后一个字节>127,它的前边也>127时,判断它后面连续的非ASCII码的个数,如果是奇数个,那就删掉它,如果是偶数个,那就保留它。


大家有没有具体的可以调用的函数?就是GetCount之类的,不过要加判断条件,我实在是新手,储备量太少,找不到函数
lisa9342 2012-07-09
  • 打赏
  • 举报
回复
这是最后调试成功的代码:

string path = f;
string newpath = path;
string fullname = Path.GetFileName(path);//返回文件名和后缀名
string name = Path.GetFileNameWithoutExtension(path);//返回文件名
string extn = Path.GetExtension(path);//返回后缀名
byte[] Bytes = System.Text.Encoding.Default.GetBytes(fullname);//获得文件名+后缀名的字节数组
byte[] nameBytes = System.Text.Encoding.Default.GetBytes(name);//获得文件名的字节数组
byte[] extnBytes = System.Text.Encoding.Default.GetBytes(extn);//获得后缀名的字节数组
string newname = fullname;//新(文件名+后缀名)
while (Bytes.Length > 128)
{
int cutCount = Bytes.Length - 128;
int initialCopyCount = nameBytes.Length - cutCount;
int finalCopyCount;
int notAsciiBytesNumber = 0;

for (int i = initialCopyCount; i < nameBytes.Length; i++)
{
if (nameBytes[i] > 127)
notAsciiBytesNumber++;
else
break;
}

//排除误截汉字编码的可能
if (nameBytes[initialCopyCount - 1] > 127)
{
if (nameBytes[initialCopyCount - 2] > 127)
{
if (notAsciiBytesNumber % 2 == 0)
{
finalCopyCount = initialCopyCount;
}
else
{
finalCopyCount = initialCopyCount - 1;
cutCount = cutCount + 1;
}
}
else
{
finalCopyCount = initialCopyCount - 1;
cutCount = cutCount + 1;
}
}
else
finalCopyCount = initialCopyCount;

ArrayList al = new ArrayList();
al.InsertRange(0, nameBytes);//这里是将文件名部分完全添加到ArrayList中
al.RemoveRange(finalCopyCount, cutCount);//根据需要截取的长度,删除ArrayList中多余的元素
al.InsertRange(finalCopyCount, extnBytes);//将后缀名部分添加到ArrayList的最后
byte[] newNameBytes = new byte[al.Count];//根据ArrayList中的元素数目新建字节数组
al.CopyTo(newNameBytes);//将ArrayList中的所有元素复制到新文件名的字节数组中
newname = System.Text.Encoding.Default.GetString(newNameBytes);//将新文件名的字节数组编码成字符串

newpath = Path.GetDirectoryName(path).TrimEnd('\\') + "\\" + newname;
break;
}
File.Move(path, newpath);//改文件名
popo0762 2012-07-05
  • 打赏
  • 举报
回复
补充说明,以上方法,只适用于假设你前面的字符都是完整的,而最后一个字符不确定是否完整的情况。
popo0762 2012-07-05
  • 打赏
  • 举报
回复
根据你的需求,我写了个校验方法,调试过,你试试:

//传入校验前字符数组,及返回数组的最大长度,返回校验后不包含不完整字符的字符数组
Byte[] GetCheckedArr(Byte[] btArr, int iMaxLen)
{
if (iMaxLen >= btArr.Length || iMaxLen <= 0 || btArr == null)
{
return btArr;
}

//定义一个bool类型,指示字符是否完整
Boolean isComplete = true;

for (int i = 0; i < iMaxLen; i++)
{
//判断是否为汉字
if (btArr[i] > 127)
{
isComplete = !isComplete;
}
}

if (!isComplete)
{
--iMaxLen;
}

if (iMaxLen == 0)
{
return null;
}

Byte[] btReturn = new Byte[iMaxLen];

Array.Copy(btArr, 0, btReturn, 0, iMaxLen);

return btReturn;
}


调用示例:
String sTmp = "是否是汉字,ABC";
Byte[] btTmp = Encoding.Default.GetBytes(sTmp);
Byte[] btResult = GetCheckedArr(btTmp, 3);
lisa9342 2012-07-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
try Catch 捕获异常
[/Quote]

异常:路径中有非法字符。


那个所谓的非法字符就是把一个汉字的两个字节截掉了一个之后剩下的怪胎丫,所以,怎么解决呢?
熙风 2012-07-05
  • 打赏
  • 举报
回复
try Catch 捕获异常
lisa9342 2012-07-05
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
你代码中的128是什么意思,可能就是它引起你array的copy丢失字符后(长度不对),产生了非法字符,而且你截取字节,太生硬了,c#是unicode编码,如果你是奇数个字节,那就会有乱码了
[/Quote]



128是文件名最长不超过128字节的意思,底层传输的限制,所以我就是按字节截取的,文件名里又有单字节字符又有双字节字符,所以这样截取很不科学,如果恰好碰到一个双字节的字符被截得只剩一半,就无法正确编码了,所以我在想有没有一种检查的方法,先检查下截取后的字节序列能不能完全正确编码,如果有这种情况,就再把那1个字节给删掉,只编前面的那些字节。
因为这段代码的最终目的就是想让将要传输的文件名在限制内
bdmh 2012-07-05
  • 打赏
  • 举报
回复
你代码中的128是什么意思,可能就是它引起你array的copy丢失字符后(长度不对),产生了非法字符,而且你截取字节,太生硬了,c#是unicode编码,如果你是奇数个字节,那就会有乱码了

110,545

社区成员

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

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

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