从中性的bytes获取正确的编码(如windows自带的记事本)

很久以前曾写一篇文章来研究.NET中的编码:
http://blog.csdn.net/www_123du_com/archive/2006/08/24/1114266.aspx

今天有人遇到个问题:如何从中性的bytes获取正确的编码?(如windows自带的记事本)

细想一下,得出一方案:

先将其以猜测的编码方式解码成string,然后再将string以此编码方式再次编码,比较前后的bytes。
(如果以错误的编码方式解码后未丢失数据,那么此方法将无效,不过经过我的简单测试,基本都成功了)

// encodings参数可以不填 (那么将默认猜测gb2312,utf-8,unicode三种编码)
public   string  GetString( byte [] buffer,  params  Encoding[] encodings)
{
    
if  (encodings.Length  <   1 )
    {
        encodings 
=   new  Encoding[] { Encoding.GetEncoding( " gb2312 " ), Encoding.UTF8, Encoding.Unicode };
    }

    
foreach  (Encoding encoding  in  encodings)
    {
        
// 按此编码获取字符串
         string  str  =  encoding.GetString(buffer);

        
// 反向转换一次,看是否可逆
         byte [] tempBytes  =  encoding.GetBytes(str);

        
// 若长度不一样,编码错误
         if  (buffer.Length  !=  tempBytes.Length)
        {
            
continue ;
        }
        
for  ( int  i  =   0 ; i  <  buffer.Length; i ++ )
        {
            
// 若其中任何一个字节不一样,也说明编码错误
             if  (buffer[i]  !=  tempBytes[i])
            {
                
goto  continueforeach;
            }
        }

        
return  str;

    continueforeach:
        
continue ;
    }
    
throw   new  Exception( " 没有找到正确的编码或数据错误。 " );
}


如果是文本文件,可以判断前几个字节来获知编码(来源:CSDN 袁晓辉):

///   <summary>
///  取得一个文本文件流的编码方式。
///   </summary>
///   <param name="stream"> 文本文件流。 </param>
///   <param name="defaultEncoding"> 默认编码方式。当该方法无法从文件的头部取得有效的前导符时,将返回该编码方式。 </param>
///   <returns></returns>
public   static  Encoding GetEncoding(FileStream stream, Encoding defaultEncoding)
{
    Encoding targetEncoding 
=  defaultEncoding;
    
if  (stream  !=   null   &&  stream.Length  >=   2 )
    {
        
// 保存文件流的前4个字节
         byte  byte1  =   0 ;
        
byte  byte2  =   0 ;
        
byte  byte3  =   0 ;
        
byte  byte4  =   0 ;
        
// 保存当前Seek位置
         long  origPos  =  stream.Seek( 0 , SeekOrigin.Begin);
        stream.Seek(
0 , SeekOrigin.Begin);

        byte1 
=  Convert.ToByte(stream.ReadByte());
        byte2 
=  Convert.ToByte(stream.ReadByte());
        
if  (stream.Length  >=   3 )
        {
            byte3 
=  Convert.ToByte(stream.ReadByte());
        }
        
if  (stream.Length  >=   4 )
        {
            byte4 
=  Convert.ToByte(stream.ReadByte());
        }
        
// 根据文件流的前4个字节判断Encoding
        
// Unicode {0xFF, 0xFE};
        
// BE-Unicode {0xFE, 0xFF};
        
// UTF8 = {0xEF, 0xBB, 0xBF};
         if  (byte1  ==   0xFE   &&  byte2  ==   0xFF ) // UnicodeBe
        {
            targetEncoding 
=  Encoding.BigEndianUnicode;
        }
        
if  (byte1  ==   0xFF   &&  byte2  ==   0xFE   &&  byte3  !=   0xFF ) // Unicode
        {
            targetEncoding 
=  Encoding.Unicode;
        }
        
if  (byte1  ==   0xEF   &&  byte2  ==   0xBB   &&  byte3  ==   0xBF ) // UTF8
        {
            targetEncoding 
=  Encoding.UTF8;
        }
        
// 恢复Seek位置       
        stream.Seek(origPos, SeekOrigin.Begin);
    }
    
return  targetEncoding;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值