Flex 识别文件编码

这是一篇转帖共同学习共同讨论
两天前看到你这个问题,那个时候我也一样遇到了,本打算等有大侠来解决的,结果等到花都谢了,废话少说,说说我这几天调研的结果:



1.少数编辑器,比如记事本、Eclipse等,会在保存utf-8编码的文件时,在文件头加上BOM标记。就是网上说的那种方法。


2.有的编辑器,比如Editplus,默认编码是UTF-8,对于未标记的BOM头,就认为是UTF-8的。当然,这个也和编辑器的设置有关系。所以,有的没有BOM头的文件,在记事本中看到的编码是ANSI,而在Editplus等编辑器中看到的是UTF-8


3.关于这个问题,没有特别完美的解决方案,任何编辑器都会面临这个问题,也都没有完美方案,这点是肯定的。因为文件的编码并不是文件的某种属性,文件本身存储的时候只是二进制串,程序完全可以无视BOM头的“潜规则”而把它当做一个想当然的编码文本来解读。


4.说了这么多,上我的代码。这不是我写的,是找到java的方案来移植的:
01.var file:File = e.target as File;

02.var fs:FileStream = new FileStream();

03.var charset:String = File.systemCharset;

04.fs.open(file, FileMode.READ);

05.var bytes:ByteArray = new ByteArray();

06.fs.readBytes(bytes, 0, file.size);

07.if(bytes[0] === 0xff && bytes[1] === 0xfe){

08.        charset = 'unicode';

09.} else if(bytes[0] === 0xfe && bytes[1] === 0xff){

10.        charset = 'UTF-16BE';

11.} else if(bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf){

12.        charset = 'UTF-8';

13.} else {

14.        //从这里开始,就是你可能没看到的解决方案。

15.        var read:uint;

16.        for(var i:int = 0, len:int = bytes.length; i < len; i++){

17.                read = bytes[i];

18.                if(read >= 0xf0) {

19.                        charset = 'GBK';

20.                        break;

21.                }

22.                if(0x80 <= read && read <= 0xbf) {

23.                        charset = 'GBK';

24.                        break;

25.                }

26.                if(0xc0 <= read && read <= 0xdf){

27.                        read = bytes[++i];

28.                        if(0x80 <= read && read <= 0xbf)

29.                                continue;

30.                        else {

31.                                charset = 'GBK';

32.                                break;

33.                        }

34.                } else if(0xe0 <= read && read <= 0xef){

35.                        read = bytes[++i];

36.                        if(0x80 <= read && read <= 0xbf) {

37.                                read = bytes[++i];

38.                                if(0x80 <= read && read <= 0xbf) {

39.                                        charset = 'UTF-8';

40.                                        break;

41.                                } else {

42.                                        charset = 'GBK';

43.                                        break;

44.                                }

45.                        } else {

46.                                charset = 'GBK';

47.                                break;

48.                        }

49.                }

50.        }

51.}
复制代码相信这段代码的前半部分你很熟悉了,后面,是我找到的java某程序的实现思路,判断整个序列中是否有GBK编码的某些特征序列。类词法分析,效率还是可以接受的。此方法基本上对于几种常用的编码基本上都涵盖了。


5.咨询了一些客户端的同学,还有一种思路仅供参考,就是判断形如ANSI -> Unicode -> ANSI这种转换,通过判断转后得到的ANSI序列和转换前的是否一致来决定这个文件是不是ANSI编码的,诚如你所料,这需要一个白名单,然后根据名单,按图索骥的把所有编码二次转码的试一遍。直到成功match。当然,你也可以使用一个默认的编码格式,优先对照,并将剩余的编码做个按概率排序,性能会有提示。


6.总结:根据这些猥琐的方法和这几天的调研,判断文件编码不是一件十分靠谱的事,不可能完美,软件要做的就是尽可能的“智能”匹配出编码,实现这个目的,有这么几种思路:




1.判断BOM头,虽然这也不精确,比如“联通问题”,但挺方便。


2.判断是否存在只有特定编码才有的16进制序列,就好像我上面代码注释后面给出的部分一样。


3.做二次转码,黑盒测试,比对转码前和转码后。


4.如果以上三种方法还有漏网之鱼,就给个输入框,让用户自己填这个神秘又该死的编码吧。

  

//var bytes:ByteArray = new ByteArray;   
//filestream.readBytes(bytes,0,file.size);   
// 读取不同 编码的文档   
private function transEncodingText(bytes:ByteArray):String   
{   
	var str:String = "";
	// 1. unicode 文档 开头 16进制码为 FF FE ,对应 十进制 数 为 255,254   
	if (bytes[0]==255 && bytes[1]==254){   
	str =  bytes.readMultiByte(bytes.length,"unicode");   
	}    
	// 2.unicode big endian 开头 16进制 为 FE FF,对应十进制数 为 254,255   
	if (bytes[0]==254 && bytes[1]==255){   
		str =  bytes.readMultiByte(bytes.length,"UTF-16BE");
	}   
	// 3.utf-8 开头 16进制 为 EF BB ,对应 十进制 数 为 239,187   
	if (bytes[0]==239 && bytes[1]==187){   
		str =  bytes.readMultiByte(bytes.length,"utf-8");   
	}  
	if(bytes[0]==73 && bytes[1]==68){
		str =  bytes.readMultiByte(bytes.length,"ANSI");
	}
	return str;
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
此资源包含源代码和实验报告。 一、实验目的 设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。 二、实验要求 该程序要实现的是一个读单词过程,从输入的源程序识别出各个具有独立意义的单词,即关键字、标识符、数据、运算符、分界符等五大类,并依次输出各个单词的种类及单词符号自身值。若遇到错误则显示“Error”,然后跳过错误部分继续显示 。 三、实验内容 通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示。 以下是实现词法分析设计的主要工作: (1)从源程序文件读入字符。 (2)删除空格类字符,包括回车、制表符空格。 (3)按拼写单词,并用(单词,属性)二元式表示。 (4)如果发现错误则报告出错。 单词的基本分类: 关键字:由程序语言定义的具有固定意义的标识符。也称为保留字例如 i f、const; 单词种别码为1。 标识符:用以表示各种名字,如变量名、数组名、函数名;种别码为2。 数据: 任何数值常数。如 125,3.14等;种别码为3。 运算符:+、-、*、/、<、、>=、;种别码为4。 分界符: ; 、, 、(、) 、[、];种别码为5。 Error:#、%等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值