,,c#实现flv解析详解示例

,,c#实现flv解析详解示例

本文提供的解析程序简单的把猫白血病病毒分解了出来,如果要做猫白血病病毒的修改操作的话,可以给每个类加个toStream方法,再历遍依次调用就可以写回到文件里了

先上效果图:

工具类

在解析的过程中,我们会和字节做各种运算,所以我定义了一个字节工具类字节数:

复制代码代码如下:使用系统;使用系统。集合。泛型;使用系统100 . Linq使用系统。文本;使用系统。木卫一;

命名空间FLVParer .utils { class ByteUtils { public static uint ByteToUInt(byte[]bs,int length){if (bs==null || bs .长度长度)返回0;uint RTN=0;for(int I=0;我长度;I){ RTN=8;RTN |=bs[I];}返回RTN } public static double ByteToDouble(byte[]bs){ if(bs==null | | bs .长度8)返回0;字节[] b2=新字节[8];for(int I=0;I 8;I){ B2[I]=bs[7-I];}返回比特转换器.ToDouble(b2,0);} public static short readui 16(Stream src){ byte[]bs=new byte[2];如果(src .读取(bs,0,2)=0)返回0;return(short)((bs[0]8)| bs[1]);} public static uint readui 24(Stream src){ byte[]bs=new byte[3];如果(src .读取(bs,0,3)=0)抛出新的IOException(“流尾”);返回ByteToUInt(bs,3);} public static uint readui 32(Stream src){ byte[]bs=new byte[4];如果(src .读取(bs,0,4)=0)抛出新的IOException(“流尾”);返回ByteToUInt(bs,4);}公共静态字符串GetTime(uint time){ return(time/60000).ToString()':'(时间/1000 % 60)。ToString('D2 ')' '(时间% 1000)。ToString(' D3 ');}}}

猫白血病病毒类

猫白血病病毒类,主要的类,里面包括一个页眉和许多的标签,也就是一个猫白血病病毒文件的结构:

复制代码代码如下:使用系统;使用系统。集合。泛型;使用系统100 . Linq使用系统。文本;使用系统。木卫一;使用FLVParer .实用工具

命名空间FLVParer .模型{ class FLV { public Header Header { get;私有集;}列表标签标签;公共FLV(Stream Stream){ Header=new Header();标题。读取头(流);溪流Seek(header.size,SeekOrigin .begin);tags=new list tag();而(流。位置流。长度-4){标签add(read tag(stream));}

}

私有标记read Tag(Stream Stream){ Tag Tag=null;字节[]缓冲区=新字节[4];溪流. Read(buf,0,4);int type=stream .读取字节();switch(type){ case 8:tag=new AudioTag();打破;案例9:tag=新视频标签();打破;案例18:tag=新脚本tag();打破;}tag.presize=ByteUtils .ByteToUInt(buf,4);tag.datasize=ByteUtils .ReadUI24(流);tag.timestamp=ByteUtils .ReadUI24(流);标签.时间戳_ex=流read byte();tag.streamid=ByteUtils .ReadUI24(流);tag.readData(流);返回标签;}}}

页眉类

页眉类,保存猫白血病病毒文件的头信息:

复制代码代码如下:使用系统;使用系统。集合。泛型;使用系统100 . Linq使用系统。文本;使用系统。木卫一;使用FLVParer .实用工具

命名空间FLVParer .模型{ class Header { public String type { get;私有集;} public int版本{ get私有集;}公共bool hasVideo { get私有集;} public bool hasAudio { get私有集;}公共单位大小{ get私有集;}

public void read header(Stream Stream){ byte[]buf=new byte[4];溪流. Read(buf,0,3);类型=编码默认。GetString(buf);溪流Read(buf,0,1);version=buf[0];溪流Read(buf,0,1);buf[0]=0x0f;if((buf[0]0x 01)==1){ has video=true;} if((buf[0]0x 04)==4){ hasAudio=true;}流. Read(buf,0,4);大小=字节数ByteToUInt(buf,4);}}}

标签类

标签类是一个抽象类,因为标签的种类有三种,为了统一管理,抽象出标签类:

复制代码代码如下:使用系统;使用系统。集合。泛型;使用系统100 . Linq使用系统。文本;使用系统。木卫一;

命名空间FLVParer .模型{枚举标记类型{视频、音频、脚本}抽象类Tag { public TagType tagType//标签类型公共单元预定尺寸;//前一标签大小公共uint数据大小;//数据区大小公共uint时间戳;//时间戳单位mspublic int timestamp _ ex//时间戳扩展公共uint流id//id公共长偏移量;//偏移量公共字节[]数据;//数据//对标签进行读取公共抽象void readData(流流);}}

脚本标签类

脚本标签类,继承自标签类,并添加成员变量价值观,用于保存脚本信息:

复制代码代码如下:使用系统。集合。泛型;使用系统。文本;使用系统。木卫一;使用FLVParer .实用工具

命名空间FLVParer .模型{类脚本标记:标记{ public ListKeyValuePairstring,对象值{ get私有集;}公共脚本tag(){ tag type=tag type .剧本;values=new ListKeyValuePairstring,object();}

公共重写void读取数据(流Stream){ offset=0;价值观. clear();字节[] bs=新字节[3];而(抵消这个。datasize){ stream .读(bs,0,3);if(bs[0]==0bs[1]==0bs[2]==9){ offset=3;打破;}流Seek(-3,SeekOrigin .当前);添加元素(" # "偏移量读取元素(流));}}

private void AddElement(string key,object o){Values .Add(new KeyValuePairstring,object(key,o));}

私有对象读取元素(流src){ int type=src .读取字节();偏移;开关(类型){ case 0://Number-8 return read double(src);情况1://布尔型-1返回读取字节(src);情况2://String-2n返回读取字符串(src);情况三://object返回读取对象(src);案例四://电影剪辑返回ReadString(src);案例5://null break;案例6://未定义的break案例7://Reference-2 return readu short(src);案例8://ECMA数组返回读取数组(src);案例10://Strict array返回read Strict array(src);案例11://Date-8 2返回读取日期(src);案例12://Long string-4n return read Long string(src);}返回null}私有对象读取对象(流src){ byte[]bs=新字节[3];脚本对象obj=新脚本对象();while (offset this.datasize){src .读(bs,0,3);if(bs[0]==0bs[1]==0bs[2]==9){ offset=3;打破;}src .Seek(-3,SeekOrigin .当前);string key=读取字符串(src);if(key[0]==0)break;obj[key]=读取元素(src);} return obj } private double read date(Stream src){ double d=read double(src);src .Seek(2,SeekOrigin .当前);offset=2;返回d;}私有脚本对象读取数组(Stream src){ byte[]buffer=new byte[4];src .Read(缓冲区,0,4);偏移=4;uint count=ByteUtils .字节跳动(缓冲区,4);脚本对象数组=新脚本对象();for(uint I=0;我数;I){ string key=read string(src);array[key]=读取元素(src);}src .Seek(3,SeekOrigin .当前);//00 00 09 offset=3;返回数组;}私有脚本数组ReadStrictArray(Stream src){ byte[]bs=new byte[4];src .读(bs,0,4);偏移=4;脚本数组array=新脚本数组();uint count=ByteUtils .ByteToUInt(bs,4);for(uint I=0;我数;I){数组增加(改为要素(src));}返回数组;} private double read double(Stream src){ byte[]buffer=new byte[8];src .阅读(缓冲区,0,8);偏移=8;返回ByteUtils .字节数加倍(缓冲区);}私有字节读取字节(流src){ offset;返回(字节)src .读取字节();}私有字符串read string(Stream src){ byte[]bs=new byte[2];src .读(bs,0,2);offset=2;int n=(int)ByteUtils .ByteToUInt(bs,2);bs=新字节[n];src .Read(bs,0,n);offset=n;返回编码ASCII码。GetString(bs);}私有字符串read long string(Stream src){ byte[]bs=new byte[4];src .读(bs,0,4);偏移=4;int n=(int)ByteUtils .ByteToUInt(bs,4);bs=新字节[n];src .Read(bs,0,n);offset=n;返回编码ASCII码。GetString(bs);} private ushort read ushort(Stream src){ byte[]buffer=new byte[2];src .Read(buffer,0,2);offset=2;返回(ushort)ByteUtils .ByteToUInt(buffer,2);}}

公共类脚本对象{ public static int indent=0;private Dictionarystring,object values=新字典字符串,object();public object this[string key]{ get { object o;价值观TryGetValue(key,out o);返回o;}设置{如果(!价值观ContainsKey(key)){values .添加(键,值);} } }公共重写字符串ToString(){ string str=' { \ r \ n ';脚本对象。缩进=2;foreach (KeyValuePairstring,object kv in values){ str=new string(' ',ScriptObject.indent) kv .按键:' kv .值”\ r \ n”;}脚本对象。indent-=2;//if (str .长度1)//str=str .子字符串(0,字符串。长度-1);str=" }返回字符串;} }公共类脚本数组{私有Listobject values=new Listobject();公共对象this[int index]{get{if (index=0索引值.计数)返回值[索引];返回null} }公共void Add(object o){values .添加(o);}公共重写字符串ToString(){ string str='[';int n=0;foreach(object o in values){ if(n % 10==0)str=' \ r \ n ';n;str=o ',';}if (str .长度1)str=str .子字符串(0,字符串。长度-1);str=' \ r \ n]';返回字符串;}}}

视频标签类

视频标签类:

复制代码代码如下:使用系统。木卫一;

命名空间FLVParer .模型{ class video Tag:Tag { public int frame type;//帧类型public int encodeID//编码id公共视频标签(){标签类型=标签类型。视频;}公共重写void读取数据(流Stream){ int info=Stream .读取字节();frameType=info 4;encodeID=info0x0fdata=新字节[datasize-1];溪流Read(data,0,(int)datasize-1);}}}

音频标签类音频标签类:

复制代码代码如下:使用系统。木卫一;

命名空间FLVParer .模型{ class音频标记:Tag { public int format//音频格式公共利率;//采样率公共(同Internationalorganizations)国际组织大小;//采样的长度公共int类型;//音频类型公共音频标签(){标签类型=标签类型。音频;}

公共重写void读取数据(流Stream){ int info=Stream .读取字节();甲酸=信息4;rate=(info0x0c)2;size=(信息0x 02)1;type=info0x01data=新字节[datasize-1];溪流Read(data,0,(int)datasize-1);}}}

使用方法

用法很简单,新的出来的时候把猫白血病病毒文件的溪流对象传进去就行了,比如我这样的:

复制代码代码如下:FLV flv=null;使用(FileStream fs=new FileStream(' t31 _ stract。flv ',文件模式.打开,文件访问. Read)){flv=新FLV(fs);}

之后就可以使用猫白血病病毒对象来分析当前猫白血病病毒的信息了。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • 设计一个简单的C#控制台应用程序,C#控制台程序,C# 创建控制台应用程序
  • 深入解析windows第8版,深入解析C#(第4版)
  • 数组代码,c# 数组操作,C# 数组实例介绍(图文)
  • 学会C#要多久,学会c#要多久,c#学习之30分钟学会XAML
  • 回溯法01背包问题c,回溯法求解01背包问题伪代码,C#使用回溯法解决背包问题实例分析
  • xml文件转义字符,xml转意字符,C# XML中的转义字符操作
  • winform 进度条控件,c# 进度条使用
  • winform 进度条控件,c# 进度条使用,C#使用winform实现进度条效果
  • winform backgroundworker,c# isbackground
  • winform backgroundworker,c# isbackground,C# BackgroundWorker用法详解
  • lua与c#交互,lua c#
  • lua与c#交互,lua c#,ToLua框架下C#与Lua代码的互调操作
  • linq c#,linq原理 c#
  • linq c#,linq原理 c#,c#中LINQ的基本用法实例
  • java decimal保留两位小数,sql中decimal函数保留2位小数,C#中decimal保留2位有效小数的实现方法
  • 留言与评论(共有 条评论)
       
    验证码: