黑基网 首页 服务器 Windows Server 查看内容

Flex中实现对ZIP文件的解析

2009-8-11 12:39| 投稿: winserver

摘要: 要实现对ZIP文件的解析,首先我们需要来了解一下ZIP文件的数据结构。简单的说,一个 ZIP 文件的普通格式由三个部分组成: 压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志。1、压缩源文件...
要实现对ZIP文件的解析,首先我们需要来了解一下ZIP文件的数据结构。简单的说,一个 ZIP 文件的普通格式由三个部分组成: 压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志。1、压缩源文件数据区在这个数据区中每一个压缩的源文件/目录都是一条记录,记录的格式如下:[文件头+ 文件数据 + 数据描述符]a、文件头结构组成   长度文件头标记 4 bytes (0×04034b50)解压文件所需 pkware 版本 2 bytes全局方式位标记 2 bytes压缩方式 2 bytes最后修改文件时间 2 bytes最后修改文件日期 2 bytesCRC-32校验 4 bytes压缩后尺寸 4 bytes未压缩尺寸 4 bytes文件名长度 2 bytes扩展记录长度 2 bytes文件名 (不定长度)扩展字段 (不定长度)b、文件数据c、数据描述符组成  长度CRC-32校验 4 bytes压缩后尺寸 4 bytes未压缩尺寸 4 bytes这个数据描述符只在全局方式位标记的第3位设为1时才存在(见后详解),紧接在压缩数据的最后一个字节后。这个数据描述符只用在不能对输出的 ZIP 文件进行检索时使用。例如:在一个不能检索的驱动器(如:磁带机上)上的 ZIP 文件中。如果是磁盘上的ZIP文件一般没有这个数据描述符。2、压缩源文件目录区在这个数据区中每一条纪录对应在压缩源文件数据区中的一条数据组成   长度目录中文件文件头标记 4 bytes (0×02014b50)压缩使用的 pkware 版本 2 bytes解压文件所需 pkware 版本 2 bytes全局方式位标记 2 bytes压缩方式 2 bytes 10最后修改文件时间 2 bytes 12最后修改文件日期 2 bytes 14CRC-32校验 4 bytes 18压缩后尺寸 4 bytes 22未压缩尺寸 4 bytes 26文件名长度 2 bytes 28扩展字段长度 2 bytes 30文件注释长度 2 bytes 32磁盘开始号 2 bytes 34内部文件属性 2 bytes 36外部文件属性 4 bytes 38局部头部偏移量 4 bytes 42文件名 (不定长度) 46扩展字段 (不定长度)文件注释 (不定长度)3、压缩源文件目录结束标志组成   长度目录结束标记 4 bytes (0×06054b50)当前磁盘编号 2 bytes 4目录区开始磁盘编号 2 bytes 6本磁盘上纪录总数 2 bytes 8目录区中纪录总数 2 bytes 10目录区尺寸大小 4 bytes 12目录区对第一张磁盘的偏移量 4 bytes 16ZIP 文件注释长度 2 bytes 20ZIP 文件注释 (不定长度)下面是实现代码: 复制内容到剪贴板 程序代码 <?xml version="1.0" encoding="utf-8"?> <mx:Window xmlns:mx="http://www.adobe.com/2006/mxml" title="分析ZIP文件" layout="vertical" width="500" height="300"  creationComplete="init();"> <mx:Script> <![CDATA[ import flash.filesystem.*; import flash.utils.ByteArray; import flash.events.Event; private var bytes:ByteArray = new ByteArray();   //定义用来存储文件标头中元数据的变量 variables for reading fixed portion of file header private var fileName:String = new String(); private var flNameLength:uint; private var xfldLength:uint; private var offset:uint; private var compSize:uint; private var uncompSize:uint; private var compMethod:int; private var signature:int; private var k:int; //定义用来表示 .zip 文件的 File (zfile) 和 FileStream (zStream) 对象,并指定将从中提取文件的 .zip 文件的位置(桌面目录 //下名为“HelloAIR.zip” 的文件)。 // File variables for accessing .zip file private var zfile:File = File.desktopDirectory.resolvePath("HelloAIR.zip"); private var zStream:FileStream = new FileStream(); private function init():void {     var screenBounds:Rectangle = Screen.mainScreen.bounds;            nativeWindow.x = (screenBounds.width - nativeWindow.width) / 2;         nativeWindow.y = (screenBounds.height - nativeWindow.height) / 2;    } private function readout():void {     zStream.open(zfile, FileMode.READ);     bytes.endian = Endian.LITTLE_ENDIAN;     while (zStream.position < zfile.size)     {             //前 30 个字节组成了第一个文件标头的固定大小部分。         // read fixed metadata portion of local file header         zStream.readBytes(bytes, 0, 30);         bytes.position = 0;                signature = bytes.readInt();                // 再没有可提取的文件, quit         if (signature != 0x04034b50)//文件开始标记         {                            break;         }                 bytes.position = 8;         compMethod = bytes.readByte(); // store compression method (8 == Deflate)压缩算法 通常是8,没压缩的是0         offset = 0;// stores length of variable portion of metadata         bytes.position = 26; // offset to file name length         flNameLength = bytes.readShort();// store file name         trace("flNameLength="+flNameLength);         offset += flNameLength; // add length of file name         bytes.position = 28;// offset to extra field length         xfldLength = bytes.readShort();         trace("xfldLength="+xfldLength);         offset += xfldLength;// add length of extra field         // 接下来程序将读取文件标头的可变长度部分,以将该部分的字节数存储在 offset 变量中。         zStream.readBytes(bytes, 30, offset);                 bytes.position = 30;         fileName = bytes.readMultiByte(flNameLength,"gbk"); // read file name                 taFiles.text += fileName + "\n"; // write file name to text area         bytes.position = 18;         compSize = bytes.readUnsignedInt(); // store size of compressed portion         taFiles.text += "\tCompressed size is: " + compSize + '\n';         bytes.position = 22; // offset to uncompressed size         uncompSize = bytes.readUnsignedInt(); // store uncompressed size         taFiles.text += "\tUncompressed size is: " + uncompSize + '\n';         //将文件的其余部分按照压缩后大小所指定的长度读入 ,未压缩的长度会等于压缩的,所以长度是对的         zStream.readBytes(bytes, 0, compSize);         if (compMethod == 8) // if file is compressed, uncompress         {             bytes.uncompress(CompressionAlgorithm.DEFLATE);         }         outFile(fileName, bytes);            } // end of while loop     var flen:int=0;     var externlen:int=0;     var showlen:int=0;     while (zStream.position < zfile.size)//目录开始标记为0x02014b50     {         if(signature != 0x02014b50)         break;         bytes.position = 10;         compMethod = bytes.readByte();                bytes.position = 28;         flen= bytes.readByte();         trace("bytes.path len:"+flen);         zStream.readBytes(bytes, 0, 46-30);         bytes.position = 0;         externlen=bytes.readByte();         trace("bytes.externlen len:"+externlen);         bytes.position = 2;         showlen=bytes.readByte();         trace("bytes.showlen len:"+showlen);         zStream.readBytes(bytes, 0, flen+externlen+showlen);         if((zStream.position+30)<zfile.size){         zStream.readBytes(bytes, 0, 30);         bytes.position = 0;                signature = bytes.readInt();         }else{                                break;         }     }     zStream.readBytes(bytes, 0, 22);     bytes.position = 0;            signature = bytes.readInt();     if(signature == 0x06054b50){//目录结束标志         bytes.position = 20;         showlen=bytes.readByte();         trace("bytes.show len="+showlen);         zStream.readBytes(bytes, 22, showlen);         bytes.position = 22;                fileName=bytes.readMultiByte(showlen,"gbk");                        taFiles.text+="\n注释:"+fileName;     }    } // end of init() method   private function outFile(fileName:String, data:ByteArray):void {     var outFile:File = File.desktopDirectory; // dest folder is desktop     outFile = outFile.resolvePath(fileName); // name of file to write     var outStream:FileStream = new FileStream();     // open output file stream in WRITE mode     outStream.open(outFile, FileMode.WRITE);     // write out the file     outStream.writeBytes(data, 0, data.length);     // close it     outStream.close(); }   private function selectTextFile(root:File):void     {         taFiles.text="";         var txtFilter:FileFilter = new FileFilter("Zip", "*.Zip;*.zip");         root.browseForOpen("Open", [txtFilter]);         root.addEventListener(Event.Select, fileSelected);     }     private function fileSelected(event:Event):void     {         msg.text="读文件:"+event.target.nativePath;     } // The application code goes here ]]> </mx:Script> <mx:Label id="msg" text="只是测试了不包含子目录的几个文件压缩的zip"/><mx:Button label="文件" click="selectTextFile(zfile)" /> <mx:TextArea id="taFiles" width="320" height="150"/> <mx:Button label="分析" click="readout()" />   </mx:Window>
小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论


新出炉

返回顶部