技术开发 频道

ASP.NET程序是如何处理文件编码

   复习了Sytem.Text下关于编码转换的一些类,回到我们的问题,你也许已经在想,判断完文件编码的类型后,只需要调用相应的GetString()函数就可以解码了。如下: 

PaTextEncoding EncodingType = GetTextEncodingType(Buffer);
        
string DecodedString = "";
        
switch (EncodingType)
         {
        
case PaTextEncoding.UTF16LittleEndian:
         DecodedString
= System.Text.Encoding.Unicode.GetString(buffer);
        
break;
        
case PaTextEncoding.UTF16BigEndian:
         DecodedString
= System.Text.Encoding.BigEndianUnicode.GetString(buffer);
        
break;
        
case PaTextEncoding.UTF8:
         DecodedString
= System.Text.Encoding.UTF8.GetString(buffer);
        
break;
        
case PaTextEncoding.UTF7:
         DecodedString
= System.Text.Encoding.UTF7.GetString(buffer);
        
break;
        
case PaTextEncoding.Unknown:
        
throw new Exception("Unkonw Encoding");
        
break;
         }  

  想法是没错的,但有一个小小的问题,之前我们提到过BOM,不同的编码文件前面几个字节会有不同的BOM标示,这几个字节唯一的作用就是指明编码类型,在解码时应该去掉这几个字节,但问题是,GetString()函数不会自动去掉这几个字节,如果直接把所有的字节数组传给GetString()函数,因为BOM的影响,解码得到的字符串前面几个字是乱码。

  DNN里用了一个比较巧妙的办法,首先侦测字节数组的编码方式,之后把所有的字节数组都转换为ASCII编码方式的字节数组,最后通过ASCIIEncoding的GetString()函数得到字符串。因为BOM的影响,转换得到的ASCII字符串前面会有一些”?”字符,查找这些字符并去掉即可。代码如下:

  这一部分代码在DNN的DotNetNuke.Modules.Admin.ResourceInstaller命名空间下的PaDnnInstallerBase类里。

  GetAsciiString()函数实现转换为ASCII编码,并解码为String           

Protected Function GetAsciiString()Function GetAsciiString(ByVal Buffer As Byte(), ByVal SourceEncoding As Encoding) As String
         Create two different encodings.
         Dim TargetEncoding As Encoding
= Encoding.ASCII
         Perform the conversion from one encoding to the other.
         Dim asciiBytes As Byte()
= Encoding.Convert(SourceEncoding, TargetEncoding, Buffer)
         Convert the
new byte[] into an ascii string.
         Dim asciiString As String
= System.Text.Encoding.ASCII.GetString(asciiBytes)
         Return asciiString
         End Function  

  根据不同的编码方式,传入不同的参数:       

Dim strScript As String = ""
         Select Case sqlFile.Encoding
         Case PaTextEncoding.UTF16LittleEndian
         strScript
= GetAsciiString(sqlFile.Buffer, System.Text.Encoding.Unicode) 'System.Text.Encoding.Unicode.GetString(sqlFile.Buffer)
         Case PaTextEncoding.UTF16BigEndian
         strScript
= GetAsciiString(sqlFile.Buffer, System.Text.Encoding.BigEndianUnicode) 'System.Text.Encoding.BigEndianUnicode.GetString(sqlFile.Buffer)
         Case PaTextEncoding.UTF8
         strScript
= GetAsciiString(sqlFile.Buffer, System.Text.Encoding.UTF8) 'System.Text.Encoding.UTF8.GetString(sqlFile.Buffer)
         Case PaTextEncoding.UTF7
         strScript
= GetAsciiString(sqlFile.Buffer, System.Text.Encoding.UTF7) 'System.Text.Encoding.UTF7.GetString(sqlFile.Buffer)
         Case PaTextEncoding.Unknown
         Throw New Exception(String.Format(SQL_UnknownFile, sqlFile.Name))
         End Select
         This check needs to be included because the unicode Byte Order mark results
in an extra character at the start of the file
         The extra character
- '?' - causes an error with the database.
         If strScript.StartsWith(
"?") Then
         strScript
= strScript.Substring(1)
         End If  

  最后的一点问题

  DNN里这种避免BOM影响解码的方法有一个问题,那就是它把所有的文件都转为ASCII编码,而ASCII编码是不支持双字节的,也就是说如果文件中包含中文,中文在解码后就成为乱码了。具体现象可以参考这个文章;SQL SERVER 2005 EXPRESS与ASP.net出现中文变成问号的奇怪问题。很可能不是通常的utf-8编码问题。

  我想解决方案是,把所有的文件都转为UTF编码,针对BOM影响编码的问题,使用UTF8Encoding.GetString(buffer, 3, buffer.length)跳过字节数组的前三个字节。

0
相关文章