这一篇,我们来看一下代码。
using System;
using System.IO;
namespace SwfHeaderReader
{
/// <summary>
/// Summary description for FlashHeaderReader.
/// </summary>
public class FlashHeaderReader
{
internal int FrameRate
{
get { return mFrameRate; }
}
internal int FrameCount
{
get { return mFrameCount; }
}
internal int Width
{
get { return mWidth; }
}
internal int Height
{
get { return mHeight; }
}
internal bool Error
{
get {return mbErrorSignature;}
}
private int mFrameRate=0;
private int mFrameCount=0;
private int mVersion=0;
private bool mIsCompressed=false;
private int mWidth=0;
private int mHeight=0;
private bool mbErrorSignature;
// To Parse Header
private byte[] data;
private int currentIndex;
public FlashHeaderReader(String filename)
{
currentIndex=0;
mbErrorSignature=false;
FileStream fs = File.OpenRead(filename);
data = new byte[fs.Length];
fs.Read (data,data.Length);
fs.Close();
ParseHeader();
}
/*
*Parse the header of the swf format
*convert from PHP :
http://www.zend.com/codex.php?id=1382&single=1
*/
private void ParseHeader()
{
ReadSignature();
mVersion=GetNextByte();
ReadFileLength();
ReadFrameSize();
ReadFrameRate();
ReadFrameCount();
}
/*
* Read first caractere FWS or CWS
* File compressed are not supported
*/
private void ReadSignature()
{
Byte readingByte=GetNextByte();
if (readingByte=='C')
{
mIsCompressed=true;
// Not supported
}
if (readingByte!='F' && readingByte!='C')
{
mbErrorSignature=true;
}
if (GetNextByte()!='W') mbErrorSignature=true;
if (GetNextByte()!='S') mbErrorSignature=true;
}
/*
*Read the RECT Structure : Frame size in twips
*This retrieve from byte the size.
*the source PHP is difficult to translate I have made
*something working...
*/
private void ReadFrameSize()
{
int cByte = GetNextByte();
int NbBits=cByte>>3;
cByte&=7;
cByte<<=5;
int currentBit=2;
int currentValue;
// Must get all 4 values in the RECT
for (int numField=0;numField<4;numField++)
{
currentValue=0;
int bitcount = 0 ;
while (bitcount<NbBits)
{
if ((cByte&128)==128)
{
currentValue =currentValue + (1<<(NbBits-bitcount-1)) ;
}
cByte<<=1 ;
cByte &= 255 ;
currentBit-- ;
bitcount++ ;
// We will be needing a new byte if we run out of bits
if (currentBit<0)
{
cByte = GetNextByte() ;
currentBit = 7 ;
}
}
// TWIPS to PIXELS
currentValue/=20;
switch (numField)
{
case 0:
mWidth = currentValue ;
break ;
case 1:
mWidth = currentValue - mWidth ;
break ;
case 2:
mHeight = currentValue ;
break ;
case 3:
mHeight = currentValue - mHeight ;
break;
}
}
}
/*
* Read Frame delay in 8.8 fixed number of frames per second
*/
private void ReadFrameRate()
{
// Frame rate
bytefps_decimal,fps_int ;
fps_decimal = GetNextByte();
fps_int =GetNextByte();
mFrameRate=fps_int+(fps_decimal)/100;
}
private void ReadFrameCount()
{
for (int i=0;i<2;i++)
{
mFrameCount+= (GetNextByte()<<(8*i)) ;
}
}
/*
*ReadFileLength : Length of entire file in bytes
*Not implemented
*/
private void ReadFileLength()
{
//Read Size
GetNextByte();
GetNextByte();
GetNextByte();
GetNextByte();
}
/*
*Retrieve one caractere of the buffer.
*/
private byte GetNextByte()
{
Byte result;
result=data[currentIndex];
currentIndex++;
return(result);
}
}
}
哇塞。怎么这么写啊。
private void ParseHeader()
{
ReadSignature();
mVersion=GetNextByte();
ReadFileLength();
ReadFrameSize();
ReadFrameRate();
ReadFrameCount();
}
在C++里面,我一个File的open一下就读完所有的结构了啊。
还好我前两年看了设计模式,要不还不被人笑死。这个应该算是builder模式吧。
好了,先写个测试读取文件大小的用例吧。
写个读取swf文件的类。
//SwfReader.h
#pragma once
typedef struct SwfHeader {
DWORD mfType; // CWS,Signature 0x46,0x57,0x53 (“FWS”)
BYTE version;
DWORD fileLength;
WORD frameRate;
WORD frameCount;
} SWFHEADER,*PSWFHEADER;
class CSwfReader
{
public:
CSwfReader(void){};
~CSwfReader(void)
{
if (NULL != m_byData)
{
delete[] m_byData;
}
}
void ParseHeader(void)
{
ReadSignature();
swfHeader.version = GetNextByte();
m_bHeader = TRUE;
ReadFileLength();
ReadFrameSize();
ReadFrameRate();
ReadFrameCount();
}
SWFHEADER swfHeader;
BOOL m_bOpen;
BOOL m_bHeader;
private:
BYTE* m_byData;
CFile m_file;
int currentIndex;
void ReadSignature()
{
GetNextByte();
GetNextByte();
GetNextByte();
}
void ReadFileLength()
{
swfHeader.fileLength = GetNextDWord();
}
void ReadFrameSize()
{
}
void ReadFrameRate()
{
}
void ReadFrameCount()
{
}
BYTE GetNextByte()
{
BYTE result;
result=m_byData[currentIndex];
currentIndex++;
return(result);
}
WORD GetNextWord()
{
WORD result;
result=m_byData[currentIndex];
currentIndex+=2;
return(result);
}
DWORD GetNextDWord()
{
DWORD result;
int temp = 0;
result = m_byData[currentIndex];
temp = m_byData[currentIndex+1];
result += temp<<8;
temp = m_byData[currentIndex+2];
result += temp<<16;
temp = m_byData[currentIndex+3];
result += temp<<24;
currentIndex+=4;
return(result);
}
public:
CSwfReader(CString aszName)
:currentIndex(0)
,m_bOpen(FALSE)
,m_bHeader(FALSE)
{
if(!m_file.Open(aszName,CFile::modeRead))
{
m_bOpen = FALSE;
return ;
}
int dwFileSize = m_file.GetLength();
m_byData = new BYTE[dwFileSize];
memset(m_byData,0x00,dwFileSize);
m_file.Read(m_byData,dwFileSize);
m_bOpen = TRUE;
}
};
不是吧,怎么都写在h里面啊。(会写c++程序吗?)
过会儿,我就(乾坤)挪移一下。(真想挪点儿面包过来。)
void TestSwfReader(void)
{
CSwfReader swfR(_T("g:/worksource/Robot/Twins02.swf"));
swfR.ParseHeader();
BYTE version = swfR.swfHeader.version;
int length = swfR.swfHeader.fileLength;
CPPUNIT_ASSERT_EQUAL((int)version,5);
CPPUNIT_ASSERT_EQUAL(length,81125);
}
好了。泡一下测试吧。是不是又通过了。
这就像上学的时候,每次到大考的时候,都不慌张。为什么?
因为每月一次的模拟考试,已经让你了解了,你的考试水平。正常情况是不会有太大偏差的。
上传一下源码。让一些比较懒的朋友,舒服一下。
更多精彩部分,请看下篇。