知识大全 ASP.NET程序是如何处理文件编码

Posted 文件

篇首语:知识才智是实践经验的总结。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 ASP.NET程序是如何处理文件编码相关的知识,希望对你有一定的参考价值。

ASP.NET程序是如何处理文件编码  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  DotNetNuke作为开源项目 很多地方为我们提供了优良的示范 得以一窥前人的智慧 前几日 因为研究一个DNN的BUG 对文件编码和文件编码相关方面的处理有一些认识

  我们经常需要把一个Text文件(如XML SQL Script)上传到服务器 然后进行处理(如显示或者执行) 这里就涉及到文本文件编码的问题了

  什么是文件编码?

  首先我们来复习一下编码的基本概念 由于历史原因 Text文件存在ASCII Unicode UTF UTF 等等编码方式 对于中文 还有GB 对于Unicode还有Unicode Unicode 对于Unicode 又分为Unicode Little Endian Unicode Big Endian 要把所有的编码方式列举出来是相当的复杂 想仔细的研究一下各种编码的规则和由来可以参考一下这篇文章 编码 charset 乱码 unicode utf 与net简单释义 我们读取一个文本文件时 总是使用某一种编码方式去解码这个文本文件 如果我们使用的解码方式和文本文件本身的编码方式不一致 最后的结果就是得到一个乱码的文件

  我可以不用关心这个麻烦的文件编码吗?

  大致了解了什么是文件编码 我们来看看在DNN里为什么要和文件编码打交道 这么麻烦 我们不能绕开它吗?

  在DNN里 人们可以制作和上传皮肤 模块 语言包的 就拿模块包说吧 模块包里包含各种文本文件 比如定义模块的 dnn文件 数据库的SQL 脚本文件等等 因为DNN是一个开源软件 世界上任何一个地方的人群都可能使用它 所以这些文本文件可能以各种编码格式存储 你无法强制别人只用某一种格式来储存 我们只能侦测每一个遇到文本文件的编码方式 并做对应的解码

  这里要强调的一点是 对于DNN 对文本文件的编码方式做了一些限制 那就是一定要使用带有BOM的Unicode格式 其它格式都一律按不支持处理 所以DNN的代码并不是一个彻底的解决方案 但事情总是取一个平衡 为 %的应用在多做 %的工作 有时候是没必要的

  如何解决文件编码转换的问题?

  回到我们的问题 对于一个上传到服务器的Text文件 我们要解决的问题就是 如何得知这个文件的编码方式 并用正确的方式解码 得到 文本文件中的内容

  如何得知这个文件的编码方式?

  首先我们来看看如何得知文本文件的编码方式 为了简化问题 我们只讨论Unicode编码这种形式(实际上DNN里也只针对Unicode做了处理) 对于其它各种编码的判别方式我们不做讨论

  BOM

  这里涉及到一个BOM(Byte Order Mark) 的概念 简单的讲 在Unicode标准中 为了标示文本文件的编码类型 可以在文本文件的开始插入几个特殊的byte 通过这几个特殊的byte 应用程序就可以鉴别文本文件使用的是那种编码了 那几个特殊的byte也被称之为BOM(参考 )

  对于Unicode 几种编码的BOM如下

  UTF big endian 文件的前 个byte是 FE FF

  UTF little endian文件的前 个byte是 FF FE

  UTF big endian文件的前 个byte是 FE FF

  UTF little endian文件的前 个byte是 FF FE

  UTF 文件的前 个byte是 EF BB BF

  UTF 的规律特殊一点 不是前几个byte 而是所有的byte转换为十进制都小于

  判定文件编码方式

  知道了这一点 你也应该能想到如何判定一个文本文件的编码方式了吧 读取文件的前面几个字节 跟上面的表对比 就可以知道这个文件使用的哪一种编码了

  看看DNN的代码 这个函数在DotNetNuke Modules Admin ResourceInstaller命名空间下的PaFile类里

  GetTextEncodingType         Private Function GetTextEncodingType()Function GetTextEncodingType(ByVal Buffer As Byte()) As PaTextEncoding         UTF = No byte higher than          UTF = first three bytes EF BB BF         UTF BigEndian = first o bytes FE FF         UTF LittleEndian = first o bytes FF FE         Lets do the easy ones first         If Buffer( ) = And Buffer( ) = Then         Return PaTextEncoding UTF LittleEndian         End If         If Buffer( ) = And Buffer( ) = Then         Return PaTextEncoding UTF BigEndian         End If         If Buffer( ) = And Buffer( ) = And Buffer( ) = Then         Return PaTextEncoding UTF          End If         This does a simple test to verify that there are no bytes with a value larger than          which would be invalid in UTF encoding         Dim i As Integer         For i = To          If Buffer(i) > Then         Return PaTextEncoding Unknown         End If         Next         Return PaTextEncoding UTF

  End Function

  代码很好懂 PaTextEncoding是一个枚举类型 枚举各种编码格式 唯一要注意的就是对于UTF 编码 采用了一种比较简单的判定方式——只检查了前 个byte是否小于

  System Text

  知道了编码方式 接下来的工作就是解码了 这里我们要用到 Net的System Text命名空间下的一些类          Encoding        UnicodeEncoding        ASCIIEncoding        UTF Encoding        UTF Encoding        UTF Encoding

  等等

  Encoding是基类 UnicodeEncoding ASCIIEncoding UTF Encoding UTF Encoding UTF Encoding等类继承自Encoding类 专门用来处理各种编码

  使用Encoding Convert (Encoding Encoding Byte[])方法 可以把字节数组从一种编码的转换为另一种编码

  使用GetString(Byte[])方法 比如UTF Encoding GetString(Byte[])就可以把UTF 编码得到字节数组还原成一个String

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

             PaTextEncoding EncodingType = GetTextEncodingType(Buffer);         string DecodedString = ;         switch (EncodingType)                  case PaTextEncoding UTF LittleEndian:         DecodedString = System Text Encoding Unicode GetString(buffer);         break;         case PaTextEncoding UTF BigEndian:         DecodedString = System Text Encoding BigEndianUnicode GetString(buffer);         break;         case PaTextEncoding UTF :         DecodedString = System Text Encoding UTF GetString(buffer);         break;         case PaTextEncoding UTF :         DecodedString = System Text Encoding UTF 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 o 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 UTF LittleEndian         strScript = GetAsciiString(sqlFile Buffer System Text Encoding Unicode) System Text Encoding Unicode GetString(sqlFile Buffer)         Case PaTextEncoding UTF BigEndian         strScript = GetAsciiString(sqlFile Buffer System Text Encoding BigEndianUnicode) System Text Encoding BigEndianUnicode GetString(sqlFile Buffer)         Case PaTextEncoding UTF          strScript = GetAsciiString(sqlFile Buffer System Text Encoding UTF ) System Text Encoding UTF GetString(sqlFile Buffer)         Case PaTextEncoding UTF          strScript = GetAsciiString(sqlFile Buffer System Text Encoding UTF ) System Text Encoding UTF 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( )         End If

  最后的一点问题

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

cha138/Article/program/ASP/201311/21682

相关参考

知识大全 asp.net获取控制台应用程序路径

  获取当前程序文件的路径也算是一个比较常见的需求比如我有一个文件connxml位于exe的同一目录在运行时需要从中读取一些设置信息  stringstr=ProcessGetCurrentProce

知识大全 ASP.NET数据库编程之处理文件访问许可

ASP.NET数据库编程之处理文件访问许可  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!一个MDB

知识大全 ASP.NET错误处理和程序优化

ASP.NET错误处理和程序优化  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &nbs

知识大全 ASP.NET整个Postback程序处理的过程

ASP.NET整个Postback程序处理的过程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 Asp.net关于对url编码的转化

Asp.net关于对url编码的转化  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  今天突然遇到

知识大全 ASP.NET中的HTTP模块和处理程序(上)

ASP.NET中的HTTP模块和处理程序(上)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  介

知识大全 ASP.NET中的HTTP模块和处理程序(下)

ASP.NET中的HTTP模块和处理程序(下)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在

知识大全 ASP.NET入门教程 10.3.3 事件处理程序/函数

ASP.NET入门教程10.3.3事件处理程序/函数  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

知识大全 asp.net编程程序优化要注意的问题

  一SqlDataRead和Dataset的选择  Sqldataread优点读取数据非常快如果对返回的数据不需做大量处理的情况下建议使用SqlDataReader其性能要比datset好很多缺点直

知识大全 ASP.NET全局异常处理浅析

ASP.NET全局异常处理浅析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在我们写程序时偶尔