想法是没错的,但有一个小小的问题,之前我们提到过BOM,不同的编码文件前面几个字节会有不同的BOM标示,这几个字节唯一的作用就是指明编码类型,在解码时应该去掉这几个字节,但问题是,GetString()函数不会自动去掉这几个字节,如果直接把所有的字节数组传给GetString()函数,因为BOM的影响,解码得到的字符串前面几个字是乱码。
DNN里用了一个比较巧妙的办法,首先侦测字节数组的编码方式,之后把所有的字节数组都转换为ASCII编码方式的字节数组,最后通过ASCIIEncoding的GetString()函数得到字符串。因为BOM的影响,转换得到的ASCII字符串前面会有一些”?”字符,查找这些字符并去掉即可。代码如下:
GetAsciiString()函数实现转换为ASCII编码,并解码为String
1 Protected Function GetAsciiString()Function GetAsciiString(ByVal Buffer As Byte(), ByVal SourceEncoding As Encoding) As String 2 3 ' Create two different encodings. 4 Dim TargetEncoding As Encoding = Encoding.ASCII 5 6 ' Perform the conversion from one encoding to the other. 7 Dim asciiBytes As Byte() = Encoding.Convert(SourceEncoding, TargetEncoding, Buffer) 8 9 ' Convert the new byte[] into an ascii string. 10 Dim asciiString As String = System.Text.Encoding.ASCII.GetString(asciiBytes) 11 12 Return asciiString 13 End Function 根据不同的编码方式,传入不同的参数: 1 Dim strScript As String = "" 2 Select Case sqlFile.Encoding 3 Case PaTextEncoding.UTF16LittleEndian 4 strScript = GetAsciiString(sqlFile.Buffer, System.Text.Encoding.Unicode) 'System.Text.Encoding.Unicode.GetString(sqlFile.Buffer) 5 Case PaTextEncoding.UTF16BigEndian 6 strScript = GetAsciiString(sqlFile.Buffer, System.Text.Encoding.BigEndianUnicode) 'System.Text.Encoding.BigEndianUnicode.GetString(sqlFile.Buffer) 7 Case PaTextEncoding.UTF8 8 strScript = GetAsciiString(sqlFile.Buffer, System.Text.Encoding.UTF8) 'System.Text.Encoding.UTF8.GetString(sqlFile.Buffer) 9 Case PaTextEncoding.UTF7 10 strScript = GetAsciiString(sqlFile.Buffer, System.Text.Encoding.UTF7) 'System.Text.Encoding.UTF7.GetString(sqlFile.Buffer) 11 Case PaTextEncoding.Unknown 12 Throw New Exception(String.Format(SQL_UnknownFile, sqlFile.Name)) 13 End Select 14 15 'This check needs to be included because the unicode Byte Order mark results in an extra character at the start of the file 16 'The extra character - '?' - causes an error with the database. 17 If strScript.StartsWith("?") Then 18 strScript = strScript.Substring(1) 19 End If |
最后的一点问题
DNN里这种避免BOM影响解码的方法有一个问题,那就是它把所有的文件都转为ASCII编码,而ASCII编码是不支持双字节的,也就是说如果文件中包含中文,中文在解码后就成为乱码了。具体现象可以参考这个文章;SQL SERVER 2005 EXPRESS与ASP.net出现中文变成问号的奇怪问题。很可能不是通常的utf-8编码问题。
我想解决方案是,把所有的文件都转为UTF编码,针对BOM影响编码的问题,使用UTF8Encoding.GetString(buffer, 3, buffer.length)跳过字节数组的前三个字节。
关注此文的读者还看过: