识别文件编码_第1页
识别文件编码_第2页
识别文件编码_第3页
识别文件编码_第4页
识别文件编码_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、根据不同编码的特点和标志,对一个文本文件判断编码方法如下1 . UTF7 所有字节的内容不会大于127,也就是不大于&HFF2 . UTF8 起始三个字节为"EF BB BF"3 . UTF16BigEndian 起始三个字节为"FE FF"4 . UTF16SmallEndian 起始三个字节为"FF FE"注: BigEndian 和SmallEndian 表示存储方式的高位在前或者低位   在前,高位在前叫BigEndian 反之叫SmallEndian#这里研究一下如何来判断文件的编码是否是UTF-

2、8,关于这个问题网络上一般采用的是判断文件的BOM头,但是这种方法有个缺点,就是有一些工具,比如EditPlus,比如Java程序,做出来的UTF-8编码的文件是不会在文件内容的前面加上BOM头的,对于这种情况,网络上的这个办法就会检测失败。 在经过一些测试之后,研究了一个解决方案。 考虑如下文件输入流的代码, FileInputStream fis = null;InputStreamReader isr = null;BufferedReader br = null; File f = new File(fn);fis = new FileInputStream(f);isr = new

3、InputStreamReader(fis, "UTF-8");br = new BufferedReader(isr); 推测执行原理如下,(都是根据测试结果的猜测) 1。fis 根据文件的保存编码来采用不同的编码读取文件。读取结果为byte2.isr设定的话,那么根据isr设定的编码来读取文件,如果不设定,那么编码采用系统默认编码 ansi(window-31j,shift_jis)3。br.readline,将isr的结果组合为String,如果isr没有设定编码,那么组合String时采用的编码为系统默认编码 ansi(window-31j,shift_jis),如

4、果isr设定了编码,那么采用isr设定好的编码。4。new string(byte,"encode") 根据指定编码生成string,如果不指定,采用系统默认编码。系统默认编码 ansi5。string.getbyte("encode") 从String根据特定的编码取得byte 问题出在第1步,第一步fis因为读取文件的时候,调用的是native,也就是系统(windows系统)的东西,他用了系统的东西,系统的这个东西作了编码判断,但是因为他调用的是native的东西,这个判定结果没有返回给java,导致java里面isr,br没有办法跟fis协调一致

5、,isr,br只能采用系统默认编码 ansi(window-31j,shift_jis),而不是采用fis的判定结果来读取文件。 这导致了,当文件使用ansi编码保存的时候,默认编码跟fis判定结果一致,不会出任何问题。 当文件使用了utf-8编码的时候,默认编码ansi,跟fis判定结果utf-8不一致,fis采用uft-8编码读取出文件内容,而后,br.readline采用系统默认编码把UTF-8编码对应的byte组合成了ansi编码对应的字符串,就产生了乱码。 我在网络以及java api里面查找了一下,没有找到判定文件保存编码的方法。推论:因为java是调用了native的方法来实际读

6、取文件的,判定在native里面完成,但是没有把判定结果公开给我们程序员。 另有一个测试结果的推论,英文字符在任何编码下面读取出来的byte都是一样的。因为我们才用任何编码都不会出现英文字符乱码的问题,所以大多数时候这个判定对我们没有影响,这里不讨论特殊情况下因为这个原因造成的影响。 根据以上推论,考虑如下解决问题的思路, 1。通过fis来读取文件,这个时候读取来的byte根据文件的保存格式是不同的。fis会自动判断处理。2。通过br来读取文件。代码示例如下:private static void readTest(String fn) BufferedReader br = null; In

7、putStreamReader isr = null; FileInputStream fis = null; try File f = new File(fn); fis = new FileInputStream(f); isr = new InputStreamReader(fis, "UTF-8"); br = new BufferedReader(isr); String s = null; while (s = br.readLine() != null) byte buf = s.getBytes("UTF-8"); for(int j=0

8、; j<buf.length; j+) System.out.println(bufj); catch(Exception e) e.printStackTrace(); finally try fis.close(); isr.close(); catch(Exception e) e.printStackTrace(); 3。1,2的读取结果byte进行比较,如果相同,那么可以认为文件的保存格式为UTF-8(虽然存在全英文ansi保存的可能,但是这种状况认为是utf-8保存不会有影响),如果不同则不是UTF-8,考虑我们目前状况,那么不是UTF-8可以认为文件保存编码就是ANSI,如

9、果不可以这么认为,其他编码类型也要做这个判断。因为英文字符在任何编码下面读取出来的byte都是一样的。所以这里有一个效率问题,必须文件内容全部比较,不能只比较一部分。 以上推测经测试有效,没有问题。如果使用第三方开源代码common-io.jar的话,可以将以上思路简化为如下代码。public boolean isUTF8(File file) try byte buf = FileUtils.readFileToByteArray(file); String filecCntent = FileUtils.readFileToString(file,"UTF-8"); i

10、f(filecCntent.equals(new String(buf,"UTF-8") return true; catch (IOException e) / TODO 動生成 catch e.printStackTrace();return false; 这个判定有一个效率问题,在这个文章中采用的是读取整个文件,如果我们文件太大,会比较花时间。这种情况可以考虑按行来读取判定,某一行不一致就可以退出了。这样可以提高一些效率。#Byte-order mark Description EF BB BF UTF-8 FF FE UTF-16 aka UCS-2, little

11、 endian FE FF UTF-16 aka UCS-2, big endian 00 00 FF FE UTF-32 aka UCS-4, little endian. 00 00 FE FF UTF-32 aka UCS-4, big-endian.#java中自动识别文件编码是UTF8 or GBK 什么是jchardet? jchardet是mozilla自动字符集探测算法代码的java移植,其源代码可以从sourceforge下载。这个算法的最初作者是frank Tang,C+源代码在 . ource/intl/chardet/,可以从 . s/intl/chardet.html

12、得到更多关于这个算法的信息。 编译及应用 将下载后的chardet.zip解压缩后,到/mozilla/intl/chardet/java/目录下,运行ant即可在dist/lib目录下生成chardet.jar,将这个jar包加入CLASSPATH.然后 运行:java l.chardet.HtmlCharsetDetector 结果:CHARSET = GB18030 运行:java l.chardet.HtmlCharsetDetector 结果:CHARSET = ASCII 运行:

13、java l.chardet.HtmlCharsetDetector 结果:CHARSET = UTF-8 编程使用 下面就jchardet.jar中的HtmlCharsetDetector.java,对调用jchardet过程予以说明: /实现nsICharsetDetectionObserver接口,这个接口只有一个Notify()方法.当jchardet引擎自己认为已经识别出字符串的字符集后(不论识别的对错),都会调用这个Notify方法。 nsICharsetDetectionObserver cdo=new nsICharsetDetectionObse

14、rver()   public void Notify(String charset)    HtmlCharsetDetector.found = true ;    System.out.println("CHARSET = " + charset);   ; /* * 初始化nsDetector() *lang为一个整数,用以提示语言线索,可以提供的语言线索有以下几个: *    1. Japanese    2. Chinese    3. Sim

15、plified Chinese    4. Traditional Chinese    5. Korean    6. Dont know (默认) */ nsDetector det = new nsDetector(lang) ; / 设置一个Oberver det.Init(cdo); BufferedInputStream imp = new BufferedInputStream(url.openStream(); byte buf = new byte1024 ; boolean done = false ; 

16、 /是否已经确定某种字符集 boolean isAscii = true ;/假定当前的串是ASCII编码 while( (len=imp.read(buf,0,buf.length) != -1)   / 检查是不是全是ascii字符,当有一个字符不是ASC编码时,则所有的数据即不是ASCII编码了。   if (isAscii) isAscii = det.isAscii(buf,len);   / 如果不是ascii字符,则调用DoIt方法.   if (!isAscii && !done) done = det.DoIt(buf,

17、len, false);/如果不是ASCII,又还没确定编码集,则继续检测。 det.DataEnd();/最后要调用此方法,此时,Notify被调用。 if (isAscii) System.out.println("CHARSET = ASCII"); found = true ; if (!found) /如果没找到,则找到最可能的那些字符集 String prob = det.getProbableCharsets() ; for(int i=0; i   System.out.println("Probable Charset = " + prob); jchardet主要解决什么样的问题? Java字符串(及字符)类以Unicode编码保存数据。当处理来自外部的国际性文本时,我们需要提供关于这些文本的编码,以便准确地将它们转换为Unicode。这意味着你必须知道你的java代码要处理的所有文件的编码。许多基于Internet的Java应用程序,要处理来自随机数据源的数据,而很多数据的编码不能确切的知道。例如,一个HTML

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论