加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

关于SWF文件格式分析及SWF EXE的经验积累

发布时间:2020-12-15 18:40:45 所属栏目:百科 来源:网络整理
导读:刚刚无意中发现的一篇挺不错的文章,没地方放,只好放BLOG这里收藏了!有兴趣的话,大家可以学习一下。 ------------------------------------ 转自:CSDN 初次接触这个问题是为了完善我自己做的flashplayerV1.02的最后一个功能,也就是EXE-SWF的转换功能.当时并
刚刚无意中发现的一篇挺不错的文章,没地方放,只好放BLOG这里收藏了!有兴趣的话,大家可以学习一下。 ------------------------------------ 转自:CSDN 初次接触这个问题是为了完善我自己做的flashplayerV1.02的最后一个功能,也就是EXE<->SWF的转换功能.当时并不知道文件转换机制是什么,更对SWF文件格式也一窍不通.^_^我相信也有好多朋友和我遇到了一样的问题吧,以下就我自己积累的一些经验,以及别人对我的帮助.来谈一谈这个问题. 首先.我们来看一下SWF文件头格式:(以下为我的资料收集) 以一个实际的SWF文件头为例: 46 57 53 05 B4 66 07 00 70 00 0F A0 00 00 BB 80 00 0C 9F 03 字节 1-3 (46 57 53):SWF文件头标志,FWS表示未压缩,CWS表示压缩的SWF文件,需要从第9个字节起用ZLib解压 字节 4 (05): Flash文件的版本,这里表明它是用Flash5生成的 字节 5-8 (B4 66 0700):一个Integer表示文件的长度,低在前,高在后,这里是$000766B4 =485044字节,这里应该等于未压缩的SWF文件实际大小或压缩过的SWF解压后的长度+文件头(8字节) 字节 9 - 。。。:SWF显示区域,(左上角坐标,右下角坐标),用下面的方法计算得到:第9字节前5位(70shr 3 = 14),以后的字节以14位进行分割,所需位数为 14*4+5 =61,需要 8 个字节来表示,那么: 70 00 0F A0 00 00 BB 80 01110 00000000000 00001111 10100000 00000000 0000000 01011101110000000 01110 00000000000000 02222201000000 00000000000000 01011101110000000 14 0 8000 0 6000 因为Flash的坐标是TWIP格式的,需要除以20的,所以实际为(0,400,300) 接下来的两字节 (000C):表示帧速率,前一字节表示小数位,后一字节表示整数位,不过一般极少有小数位的帧率,所以一般我们只计整数就可以了,这里$0C = 12,即每秒12帧再接下来的两字节 (9F03):表示总帧数,成功类型,$039F=927帧,与ShockwaveFlash.TotalFrames得到的数值是一样的。 再后面的数据是SWF的实体数据 接着:我们来看EXE文件的真正面目.其实EXE的SWF并不存在什么文件格式转换的问题,SWF文件之所以能变为EXE文件,无非是加入了一些流的操作罢了.下面让我们看看EXE文件的由来,简单的说:EXE格式的SWF文件不过是一个Flash播放器程序后面跟着一个SWF文件,两个文件写在一起,然后再在文件末尾写入SWF文件的大小和“FA123456”标示。故SWF->EXE的转换机制其实就这么简单. 而EXE->SWF呢,无非就是从文件末尾得到内嵌的SWF文件大小,然后新建一个空白的扩展名为.swf的文件,把内嵌的SWF文件写入这个新文件就可以了! 明白的这些以后,我想就SWF与EXE的转换也就不难了吧.(关键是一些流操作) 以下我给出一些流操作的函数及用法: 一、Delphi中流的基本概念及函数声明 在Delphi中,所有流对象的基类为TStream类,其中定义了所有流的共同属性和方法。 TStream类中定义的属性介绍如下: 1、Size:此属性以字节返回流中数据大小。 2、Position:此属性控制流中存取指针的位置。 Tstream中定义的虚方法有四个: 1、Read:此方法实现将数据从流中读出。函数原形为: Function Read(varBuffer;Count:Longint):Longint;virtual;abstract; 参数Buffer为数据读出时放置的缓冲区,Count为需要读出的数据的字节数,该方法返回值为实际读出的字节数,它可以小于或等于Count中指定的值。 2、Write:此方法实现将数据写入流中。函数原形为: Function Write(varBuffer;Count:Longint):Longint;virtual;abstract; 参数Buffer为将要写入流中的数据的缓冲区,Count为数据的长度字节数,该方法返回值为实际写入流中的字节数。 3、Seek:此方法实现流中读取指针的移动。函数原形为: FunctionSeek(Offset:Longint;Origint:Word):Longint;virtual;abstract; 参数Offset为偏移字节数,参数Origint指出Offset的实际意义,其可能的取值如下: soFromBeginning:Offset为移动后指针距离数据开始的位置。此时Offset必须大于或者等于零。 soFromCurrent:Offset为移动后指针与当前指针的相对位置。 soFromEnd:Offset为移动后指针距离数据结束的位置。此时Offset必须小于或者等于零。该方法返回值为移动后指针的位置。 4、Setsize:此方法实现改变数据的大小。函数原形为: Function Setsize(NewSize:Longint);virtual; 另外,TStream类中还定义了几个静态方法: 1、ReadBuffer:此方法的作用是从流中当前位置读取数据。函数原形为: Procedure ReadBuffer(var Buffer;Count:Longint); 参数的定义跟上面的Read相同。注意:当读取的数据字节数与需要读取的字节数不相同时,将产生EReadError异常。 2、WriteBuffer:此方法的作用是在当前位置向流写入数据。函数原形为: Procedure WriteBuffer(var Buffer;Count:Longint); 参数的定义跟上面的Write相同。注意:当写入的数据字节数与需要写入的字节数不相同时,将产生EWriteError异常。 3、CopyFrom:此方法的作用是从其它流中拷贝数据流。函数原形为: Function CopyFrom(Source:TStream;Count:Longint):Longint; 参数Source为提供数据的流,Count为拷贝的数据字节数。当Count大于0时,CopyFrom从Source参数的当前位置拷贝Count个字节的数据;当Count等于0时,CopyFrom设置Source参数的Position属性为0,然后拷贝Source的所有数据; TStream还有其它派生类,其中最常用的是TFileStream类。使用TFileStream类来存取文件, 首先要建立一个实例。声明如下: constrtor Create(const Filename:string;Mode:Word); Filename为文件名(包括路径),参数Mode为打开文件的方式,它包括文件的打开模式和共享模式,其可能的取值和意义如下: 打开模式: fmCreate :用指定的文件名建立文件,如果文件已经存在则打开它。 fmOpenRead :以只读方式打开指定文件 fmOpenWrite :以只写方式打开指定文件 fmOpenReadWrite:以写写方式打开指定文件 共享模式: fmShareCompat :共享模式与FCBs兼容 fmShareExclusive:不允许别的程序以任何方式打开该文件 fmShareDenyWrite:不允许别的程序以写方式打开该文件 fmShareDenyRead :不允许别的程序以读方式打开该文件 fmShareDenyNone :别的程序可以以任何方式打开该文件 TStream还有一个派生类TMemoryStream,实际应用中用的次数也非常频繁。它叫内存流,就是说在内存中建立一个流对象。它的基本方法和函数跟上面是一样的。 好了,有了上面的基础后,我们就可以开始我们的编程之行了。 以下先给出一个EXE->SWF过程: procedure exe2swf( exeName,swfName: String); var // 分别处理EXE、SWF文件的文件流 SourStream,DestStream : TFileStream; // SWF文件的大小 SwfFileSize : Cardinal; i,j : Integer; begin // 打开EXE形式的源文件 SourStream :=TFileStream.Create( exeName,fmOpenRead orfmShareExclusive ); Try // 读取文件标志 SourStream.Seek( -2*SizeOf(Integer),soFromEnd ); SourStream.ReadBuffer( SwfFileSize,SizeOf(Integer) ); // 判断读到的文件标志是否和FA123456相同 //判断是否是Macromedia官方格式的Flash文件 if SwfFileSize=$FA123456 then begin SourStream.ReadBuffer( SwfFileSize,SizeOf(SwfFileSize) ); SourStream.Seek( -SwfFileSize -2*SizeOf(Integer),soFromEnd); // 打开目标SWF文件 DestStream :=TFileStream.Create( swfName,fmCreate ); Try // 从EXE文件流中读取数据 DestStream.CopyFrom( SourStream,SwfFileSize ); ShowMessage( '转换成功。' ); Finally //释放文件流 DestStream.Free; end; end else begin ShowMessage( '无法识别的EXE格式Flash影片。' ); end; finally //释放文件流 SourStream.Free; end; end; 以上就是EXE->SWF文件的全过程了,调用时如:exe2swf(edit1.Text,'1.swf')即将Edit文本框中的路径所指向的EXE文件转换为了当前目录下文件名为:1.SWF的文件了. 有了上面的知识,SWF->EXE的方法,我在这里也就不在重复了.哈哈.其实也很简单.到此一个简单的转换过程也就完成了,大家不妨都自己动手做一做,希望能对大家有所帮助。 (注:对于一些非官方的EXE格式的Flash文件,不一定存在$FA123456标志,故有时也可能不能识别其格式。) 作者:hottey 2003-11-17号于山西太原 MyEmail:delphi21@163.com 参考文献:陈经韬“谈Delphi编程中“流”的利用“,CSDN论坛

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读