关于SWF文件格式分析及SWFEXE的经验积累
刚刚无意中发现的一篇挺不错的文章,没地方放,只好放blog这里收藏了!最近又重新在学习流技术和看有关流编程方面的东东!今天又学到不少..hoho 当然陈经韬以前写的几篇有关流的编程文章也是相当相当精彩!感兴趣的朋友可以翻翻我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 07 00):一个integer表示文件的长度,低在前,高在后,这里是$000766b4 = 485044字节,这里应该等于未压缩的swf文件实际大小或压缩过的swf解压后的长度+文件头(8字节)
字节 9 - 。。。: swf显示区域,(左上角坐标,右下角坐标),用下面的方法计算得到:第9字节前5位(70 shr 3 = 14),以后的字节以14位进行分割,所需位数为 14*4+5 = 61,需要 8 个字节来表示,那么:
70 00 0f a0 00 00 bb 80
01110 00000000000 00001111 10100000 00000000 0000000 010111011 10000000
01110 00000000000000 01111101000000 00000000000000 01011101110000 000
14 0 8000 0 6000
因为flash的坐标是twip格式的,需要除以20的,所以实际为(0,400,0,300)
接下来的两字节 (00 0c):表示帧速率,前一字节表示小数位,后一字节表示整数位,不过一般极少有小数位的帧率,所以一般我们只计整数就可以了,这里 $0c = 12,即每秒12帧再接下来的两字节 (9f 03):表示总帧数,word类型,$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(var buffer;count:longint):longint;virtual;abstract;
参数buffer为数据读出时放置的缓冲区,count为需要读出的数据的字节数,该方法返回值为实际读出的字节数,它可以小于或等于count中指定的值。
2、write:此方法实现将数据写入流中。函数原形为:
function write(var buffer;count:longint):longint;virtual;abstract;
参数buffer为将要写入流中的数据的缓冲区,count为数据的长度字节数,该方法返回值为实际写入流中的字节数。
3、seek:此方法实现流中读取指针的移动。函数原形为:
function seek(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类来存取文件,
首先要建立一个实例。声明如下:
constructor 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 or fmshareexclusive );
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论坛
↓相关文章:
- · HThost免费空间(PHP+MYSQL+邮局+无限子站+统计系统)申请与管理攻略
- · hthost的一条龙服务
- · 在肉机上开个隐藏的个人主页
- · QQ2005新春贺岁版应用全攻略
- · Php+Mysql注入专题
- · 识别WEB应用组件
- · 计算机密码破解实用手册
- · 免费拥有网易收费服务
- · SQL 语法参考手册
- · 黑客常用术语
- · 玩QQ宠物的八大秘笈绝招
- · 什么是Trackback
- · 汉化软件教程
- · 解决Explorer.exe 在 Windows XP 中反复意外退出
- · 命令行方式使用FTP实战练习
- · MP4背景知识
- · 完全BIOS优化
- · ADSL入侵
- · Python学习资料
- · 网站LOGO设计规范的思考
- · 美工LOGO设计进阶
- · 防止入侵 两步修改XP远程管理默认端口
- · 解决安装XP SP2 后无法显示验证码的问题
- · 如何设计LOGO-字母变形标志教程
- · 关于Java的一切 : 工具, 类库, 框架
- · 预防SQL注入漏洞函数
- · SQL注入漏洞全接触
- · XREA空间数据库操作的相关更新
- · ADSL知识合集
- · Windows2000绝版安全
- · QQ号码的基本知识
- · 86件Firefox浏览器能而IE不能做的事
- · 解决国内不能正常访问GMAIL的方法
- · Label标签创新使用,1G容量轻松管理
- · cs1.5命令
- · 巧用DOS命令上传文件
- · 动态IP變固定ip的詳細步驟
- · Window 服务全攻略大全
- · Discuz! 2.5F cookie未过滤漏洞
- · 来自MSN官方网站的使用技巧集锦
- · WinXPSP2激活精彩问答
- · 修改MD5加密 提高网站安全
- · MSSQL注入攻击服务器与防护
- · TCP端口的作用、漏洞和操作建议
- · 国内10大bt站点
- · 用命令检查电脑是否被安装木马
- · 美国名牌大学的计算机网络课程网址
- · IPC$命令
- · 网管秘技八招
- · 实现重启后删除文件的工具
- · Windows 2000游戏能力大揭密
- · 网络故障诊断排除70例
- · 网络组建基础必备-网线制作
- · 腾讯QQ申请分析
- · MolyX Board原代码泄露漏洞
- · 不花钱拿IT认证
- · 用net start 可以启动肉鸡的命令一览
- · 提升(web)权限终极9技巧
- · 利用对方服务器漏洞远程注册DLL
- · 对win2k以上“隐藏虚拟目录”再分析

