当前位置:编程学习 > VB >>

VB变态应用活动:我最近写的FlashBit。

资源下载:
http://d.download.csdn.net/down/566609/KiteGirl

FlashBit是我最想写而又一直没时间写的一个程序,今天一鼓作气把它捣鼓出来了。
这是在VB下实现对Bit操作的一组实用函数,是个把Byte肢解成若干Bit来操作的玩意儿,说它变态一点不过分。
这个程序看起来似乎有点吃饱了撑的,但实际上它相当有用。写它的动机来自于以VB编写哈夫曼编码/解码器和单片机应用的一些需求。VB下对Bit操作相当不方便,连移位命令都没有。而利用算数方法实现一些对Bit的操作在速度上实在难以忍受,而且代码及其冗长复杂。就这个程序本身来说,如果用纯算数方法实现,速度至少慢10倍,我是用一种比较缺德的查表法来实现的(将近9MB大的一个表,非常变态)。
至于它能做什么?比较典型的用途是做BASE64编码/解码器、哈夫曼编码/解码器,或者把信息藏在一个BMP文件像素的0位面里(据说本·拉登先生曾用这个办法通过互联网传递信息)。单色位图、采集点阵字库、GIF编码也会用到它。

这个程序有Simple和Professional两种。功能、速度完全一样。两者区别是:
Simple没有真正的计算函数,纯粹是查表,不能自己生成FlashBit_BSL_Buffer.dat;
Professional有真正的计算函数,可以自己生成甚至不用这个文件,为了实现这个功能则多了一大堆你看了之后想撞墙的代码。但那些代码除了生成FlashBit_BSL_Buffer.dat文件,压根不实用(速度比查表法要慢许多)。
考虑到代码的简洁,上面提供下载的是Simple。如果你想要Professional也不是不可以,我会在稍后贴出来的。

下面是这个模块里所有方法、函数的说明:

BytesBit_BitsPutToBytes方法
格式:tClass.BytesBit_BitsGetByBytes pBytes(), pBitsLoacte, pBitsValue, pBitsCount[, pHL_Logic][, pBoundLock]
功能:在字符串数组指定位写入指定位长的位值。
参数:byte       pBytes()    被写入的字节数组。
      long       pBitsLoacte 起始位。取值范围(0 To 2^31)。
      long       pBitsCount  写位长。取值范围(-8 to 8)。
                             pBitsCount > 0  从起始位向右读;
                             pBitsCount < 0  从起始位向左读;
                             pBitsCount = 0  无效(不写入)
      Boolean    pHL_Logic   可选参数。位序逻辑。默认为False。
                             =True   书写顺序。
                             =False  逻辑顺序。
      Boolean    pBoundLock  可选参数。字节数组下标锁定。默认为True。
                             =True   不锁定字节数组下标。
                             =False  锁定字节数组下标。
返回:byte       tByte       位值。
说明:1、pBytes()必须是下标从0开始的至少有一个元素的数组,否则会出错。
      2、pBitsLoacte从0开始计数,不能是负值。pBitsLoacte上限可以超出实际字节数组所具备的位数。
      3、pBoundLock=False的情况下,如pBitsLoacte前后位数不足pBitsCount定义的位长,则作如下处理:
         pBitsCount > 0  取从起始位到第0位之间的位长,截取pBitsValue高位写入。
         pBitsCount < 0  取从起始位到第7位之间的位长,截取pBitsValue低位写入。
         pBoundLock=True的情况下,pBitsLoacte后位数不足会扩展字节数组以容纳写入的位。
         但pBitsCount < 0的情况下,如pBitsLoacte前的位数不足则截取pBitsValue低位写入。
      4、pHL_Logic=True  将字节最左边的位作为0位,以符合书写顺序。
         pHL_Logic=False 将字节最右边的位作为0位,以符合逻辑顺序。

BytesBit_BitsGetByBytes函数
格式:[tByte] = tClass.BytesBit_BitsGetByBytes(pBytes(), pBitsLoacte, pBitsCount[, pHL_Logic])
功能:从字符串数组指定位读取指定位长的位值。
参数:byte       pBytes()    字节数组。
      long       pBitsLoacte 起始位。取值范围(0 To 2^31)。
      long       pBitsCount  取位长。取值范围(-8 to 8)。
                             pBitsCount > 0  从起始位向右读;
                             pBitsCount < 0  从起始位向左读;
                             pBitsCount = 0  无效(返回0)
      Boolean    pHL_Logic   可选参数。位序逻辑。默认为False。
                             =True   书写顺序。
                             =False  逻辑顺序。
返回:byte       tByte       位值。
说明:1、pBytes()必须是下标从0开始的至少有一个元素的数组,否则会出错。
      2、pBitsLoacte从0开始计数,不能是负值。pBitsLoacte上限可以超出实际字节数组所具备的位数,返回0。
      3、如果pLocate前后位数不足pBitsCount定义的位长,则作如下处理:
         pBitsCount > 0  取从起始位到第0位之间的位,并后后面补足够的0。
         pBitsCount < 0  取从起始位到第7位的位值。
      4、pHL_Logic=True  将字节最左边的位作为0位,以符合书写顺序。
         pHL_Logic=False 将字节最右边的位作为0位,以符合逻辑顺序。

BinaryText_SetToBytes函数
格式:[tBytes()] = tClass.BinaryText_SetToBytes(pText[, pLimit])
功能:将八位二进制字符串文本解码为字节数组。
参数:string     pText       八位二进制字符串文本。
      string     pLimit      可选参数。八位二进制字符串之间的分隔符,默认为" "。
返回:byte       tBytes()    字节数组。

BinaryText_GetByBytes函数
格式:[tString] = tClass.BinaryText_GetByBytes(pBytes()[, pLimit])
功能:将字节数组编码为八位二进制字符串。
参数:byte       pBytes()    字节数组。
      string     pLimit      可选参数。八位二进制字符串之间的分隔符,默认为" "。
返回:string    tString      八位二进制字符串文本。

BinaryString_FormatCheck函数
格式:[tBool] = tClass.BinaryString_FormatCheck(pString)
功能:检测八位二进制字符串的合法性。
参数:string     pString     字节值的八位二进制字符串。
返回:boolean    tBool       True - 合法; False - 非法

BinaryString_SetToByte函数
格式:[tByte] = tClass.BinaryString_GetByByte(pString)
功能:从八位二进制字符串取得字节值。
参数:string     pString     字节值的八位二进制字符串。
返回:byte       tByte       字节值。

BinaryString_GetByByte函数
格式:[tString] = tClass.BinaryString_GetByByte(pByte)
功能:取字节值的八位二进制字符串。
参数:byte       pByte       字节值。
返回:string    tString      字节值的八位二进制字符串。

BinaryBits_Put函数
格式:[tOutByte] = tClass.BinaryBits_Put(pByte, pLocate, pCount, pValue)
功能:将指定长度的位值写入字节指定位置。
参数:byte       pByte       原始字节。
      long       pLocate     起始位。取值范围(7 to 0)。
      long       pCount      写位长。取值范围(-8 to 8)。
                             pCount > 0 从起始位向右写;
                             pCount < 0 从起始位向左写;
                             pCount = 0 无效
      byte       pValue      写位值。
返回:byte       pByte       写值后的字节。
说明:1、这是BinaryBits_MathPut的缓冲版函数。
      2、缓冲函数不对参数值范围做任何检测,取值范围外的参数值会导致程序崩溃。
      3、pLocate对一个字节的8个位序的定义为Bit7,Bit6,Bit5,Bit4,Bit3,Bit2,Bit1,Bit0
      4、如果pLocate前后位数不足pCount定义的位长,则作如下处理:
         pCount > 0  取从起始位到第0位之间的位长,截取pValue高位写入。
         pCount < 0  取从起始位到第7位之间的位长,截取pValue低位写入。
      5、如果pValue的值超过pCount定义的位长,则按pCount定位的位长截取低位。

BinaryBits_Get函数
格式:[tOutByte] = tClass.BinaryBits_Get(pByte, pLocate, pCount)
功能:从字节指定位置取指定位长的位值。
参数:byte       pByte       源Byte。
      long       pLocate     起始位。取值范围(7 to 0)。
      long       pCount      取位长。取值范围(-8 to 8)。
                             pCount > 0 从起始位向右取;
                             pCount < 0 从起始位向左取;
                             pCount = 0 无效(返回0)
返回:byte       pByte       位值。
说明:1、这是BinaryBits_MathGet的缓冲版函数。
      2、缓冲函数不对参数值范围做任何检测,取值范围外的参数值会导致程序崩溃。
      3、pLocate对一个字节的8个位序的定义为Bit7,Bit6,Bit5,Bit4,Bit3,Bit2,Bit1,Bit0
      4、如果pLocate前后位数不足pCount定义的位长,则作如下处理:
         pCount > 0  取从起始位到第0位之间的位,并后后面补足够的0。
         pCount < 0  取从起始位到第7位的位值。

BinaryBits_Move函数
格式:[tOutByte] = tClass.BinaryBits_Move(pByte, pStep, [pLoop])
功能:对Byte进行算数移位。
参数:byte       pByte       源Byte。
      long       pStep       移位数量。取值范围(-7 to 7)
                             pStep < 0 右移位
                             pStep = 0 不移位
                             pStep > 0 左移位
      boolean    pLoop       循环移位开关。取值范围(0,1)默认为0。
                             pLoop = 0 不循环
                             pLoop = 1 循环
返回:byte       tOutByte    移位后的Byte。
说明:1、这是BinaryBits_MathMove的缓冲版函数。
      2、缓冲函数不对参数值范围做任何检测,取值范围外的参数值会导致程序崩溃。
--------------------编程问答-------------------- VB变态应用活动  
我两个月后看能不能也发表个这个题目的文章。 --------------------编程问答--------------------
引用楼主 KiteGirl 的帖子:
(据说本·拉登先生曾用这个办法通过互联网传递信息)

妹子,啥时候和本·拉登扯上了? --------------------编程问答--------------------
引用 2 楼 zzyong00 的回复:
引用楼主 KiteGirl 的帖子:

(据说本·拉登先生曾用这个办法通过互联网传递信息) 
 
妹子,啥时候和本·拉登扯上了?


我首先是从关于本·拉登的新闻里学到这个办法。新闻里说拉登把信息藏在图片的像素里。我当时琢磨了几种可能,最后认为他应该是在像素最后一个位保存信息。
后来在一本美国人编写的数字图象教材里找到关于这个技术的说明,确实是这么干的。 --------------------编程问答-------------------- 0分贴,BS --------------------编程问答-------------------- 靠 又见变态的小仙妹 俺给你整到论坛首页上去 --------------------编程问答-------------------- o --------------------编程问答-------------------- 厉害 --------------------编程问答--------------------
引用 5 楼 Modest 的回复:
靠 又见变态的小仙妹 俺给你整到论坛首页上去


BT,嘿嘿,小心被告啊,嘎嘎 --------------------编程问答-------------------- 小仙妹...偶像啊~~ --------------------编程问答-------------------- 鲜美 厉害 --------------------编程问答-------------------- 学习! --------------------编程问答-------------------- 好厉害的MM啊 --------------------编程问答-------------------- --------------------编程问答-------------------- 拉登可能用了个比较简单的方法~~


COPY 1.jpg /B + 1.txt /A 2.jpg

用记事本2.jpg打开到最后可以看到文本的内容


^_^ --------------------编程问答-------------------- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS --------------------编程问答-------------------- I am sorry .
I am hurry! --------------------编程问答-------------------- 狂顶~~ --------------------编程问答-------------------- 恩,不错的主意 --------------------编程问答-------------------- up --------------------编程问答-------------------- 拉登可能用了个比较简单的方法~~ 

如 
COPY 1.jpg /B + 1.txt /A 2.jpg 

用记事本2.jpg打开到最后可以看到文本的内容  --------------------编程问答-------------------- 查表法虽然直观,但是对 Byte 这种无符号整数,直接运算更快。
表的大小勉强算得上变态。

§函数
'Byte 类型的移位操作
'2008-08-04, Tiger_Zhao
Option Explicit

'左移
Function LShift(ByVal Value As Byte, ByVal bits As Long) As Byte
    Dim byTopBit        As Byte
    Dim i               As Long
    
    If Value = 0 Then Exit Function
    
    Select Case bits
        Case 0:     LShift = Value
        Case 1:     LShift = (Value And &H7F) * &H2
        Case 2:     LShift = (Value And &H3F) * &H4
        Case 3:     LShift = (Value And &H1F) * &H8
        Case 4:     LShift = (Value And &HF) * &H10
        Case 5:     LShift = (Value And &H7) * &H20
        Case 6:     LShift = (Value And &H3) * &H40
        Case 7:     LShift = (Value And &H1) * &H80
    End Select
End Function

'循环左移
Function LShiftZ(ByVal Value As Byte, ByVal bits As Long) As Byte
    If Value = 0 Then Exit Function
    
    If bits = 0 Then
        LShiftZ = Value
    Else
        LShiftZ = LShift(Value, bits) Or RShift(Value, 8 - bits)
    End If
End Function

'右移
Function RShift(ByVal Value As Byte, ByVal bits As Long) As Byte
    Dim byTopBit        As Byte
    Dim i               As Long
    
    If Value = 0 Then Exit Function
    
    Select Case bits
        Case 0:     RShift = Value
        Case 1:     RShift = Value \ &H2
        Case 2:     RShift = Value \ &H4
        Case 3:     RShift = Value \ &H8
        Case 4:     RShift = Value \ &H10
        Case 5:     RShift = Value \ &H20
        Case 6:     RShift = Value \ &H40
        Case 7:     RShift = Value \ &H80
    End Select
End Function

'循环右移
Function RShiftZ(ByVal Value As Byte, ByVal bits As Long) As Byte
    If Value = 0 Then Exit Function
    
    If bits = 0 Then
        RShiftZ = Value
    Else
        RShiftZ = RShift(Value, bits) Or LShift(Value, 8 - bits)
    End If
End Function

§调用方式
(1) BinaryBits_Move(): pStep = [0..7], pLoop = 0
(2) LShift(): pStep 同上
(3) BinaryBits_Move(): pStep = [-7..7], pLoop = 1
(4) : pStep 同上
    If pStep < 0 Then
        n = RShiftZ(pByte, Abs(pStep))
    Else
        n = LShift(pByte, pStep)
    End If


§运行方式
(A) 在 IDE 中执行
(B) 不选任何优化选项,编译成 exe 执行
(C) 选择全部优化选项,编译成 exe 执行

§测试结果
--- ----- ----- ----- -----
     (1)   (2)   (3)   (4)
--- ----- ----- ----- -----
(A) 3.204 2.393 5.446 8.189
(B) 0.641 0.158 1.200 0.398
(C) 0.605 0.080 1.133 0.311
--- ----- ----- ----- -----
--------------------编程问答-------------------- 稍微更正一下,调用方式(4)用的是 LShiftZ 而不是 LShift --------------------编程问答-------------------- VB不能移位,用C++呀...非得要用VB吗? --------------------编程问答-------------------- VB VB --------------------编程问答-------------------- 小仙妹又搞高精尖。。。。
毫不犹豫地。。。。顶。。。。 --------------------编程问答--------------------
引用 21 楼 Tiger_Zhao 的回复:
查表法虽然直观,但是对 Byte 这种无符号整数,直接运算更快。 
表的大小勉强算得上变态。 


非常感谢老鸟的赐教。刚刚做了测试,发现了一些现象:

FlashBit是以一个Class模块提供的。其实它没必要非写成Class模块。
在这种状态下:LShiftZ 0.58秒、BinaryBits_Move是1.5秒。

把FlashBit改成一般的模块。无论pBit是正值还是负值、是否循环,测试结果均是:
LShiftZ 0.56秒、BinaryBits_Move是0.76秒。
BinaryBits_Move函数本身不是一个函数,而是一个叫priBuffer_BinaryBits_Move()的表。
这个表涵盖了左右、循环操作,因此不大可能有速度上的差别。

就单独移位操作而言,LShiftZ确实最快。实际也多次发现查表缓冲不如直接计算快的情况。

但对于更复杂的BinaryBits_Get和BinaryBits_Put函数。他们也是同样结构的查表函数,速度几乎和BinaryBits_Move一样快。
--------------------编程问答-------------------- 不顶不行啊,顶 --------------------编程问答-------------------- VB怎么这么多啊? --------------------编程问答-------------------- 这里顶完 首页上也顶 哇咔咔 --------------------编程问答-------------------- 1 --------------------编程问答-------------------- 很好很强大
刘亦菲图片 --------------------编程问答--------------------
引用 26 楼 KiteGirl 的回复:


的确是用函数或类封装数组后性能急剧下降,下面是单纯对数组的访问测试,特别是优化编译后,与直接访问数组的差别不止一个数量级。

§运行方式
(A) 在 IDE 中执行
(B) 不选任何优化选项,编译成 exe 执行
(C) 选择全部优化选项,编译成 exe 执行

§测试结果
---------------- ------ ------ ------
    调用方式       (A)    (B)    (C) 
---------------- ------ ------ ------
全局静态数组      3.306  1.284  0.060
全局动态数组      3.242  0.817  0.058
局部静态数组      5.193  1.294  0.060
局部动态数组      5.479  0.854  0.057
函数封装静态数组 14.065  1.489  1.317
函数封装动态数组 14.089  1.154  0.904
对象封装静态数组 28.090  5.361  5.424
对象封装动态数组 28.434  5.372  5.477
---------------- ------ ------ ------
--------------------编程问答-------------------- 将 priBuffer_BinaryBits_Move 复制到模块中直接访问,查表法的速度优势才算体现出来了。
值得引以为戒,由于结构设计的原因影响了性能。

§调用方式
(1) (Object)BinaryBits_Move(): pStep = [0..7], pLoop = 0
(2) (Module)BinaryBits_Move(): pStep = [0..7], pLoop = 0
(3) LShift(): pStep 同上
(4) (Object)BinaryBits_Move(): pStep = [-7..7], pLoop = 1
(5) (Module)BinaryBits_Move(): pStep = [-7..7], pLoop = 1
(6) : pStep 同上
    If pStep < 0 Then
        n = RShiftZ(pByte, Abs(pStep))
    Else
        n = LShiftZ(pByte, pStep)
    End If


§运行方式
(A) 在 IDE 中执行
(B) 不选任何优化选项,编译成 exe 执行
(C) 选择全部优化选项,编译成 exe 执行

§测试结果
--- ------ ------ ------
      (A)    (B)    (C) 
--- ------ ------ ------
(1)  3.153  0.689  0.609
(2)  0.371  0.027  0.006
(3)  2.301  0.143  0.077
(4)  3.121  0.674  0.601
(5)  0.350  0.026  0.006
(6) 11.602  0.515  0.448
--- ------ ------ ------
--------------------编程问答-------------------- 顶~~~ --------------------编程问答-------------------- 厉害 --------------------编程问答-------------------- 我也写过,是为用md5加密word文档,不过单独测试什么输入都没问题,但是放算法里第二次循环就溢出了 --------------------编程问答-------------------- Bit操作真是好玩。 --------------------编程问答-------------------- 顶一把小仙妹。
--------------------编程问答--------------------
引用 25 楼 lsftest 的回复:
小仙妹又搞高精尖。。。。 
毫不犹豫地。。。。顶。。。。
--------------------编程问答-------------------- 顶 --------------------编程问答-------------------- mark! --------------------编程问答-------------------- 写它的动机来自于以VB编写哈夫曼编码/解码器和单片机应用的一些需求……………………………………(将近9MB大的一个表,非常变态)。 

--------------------------------------------

单片机的ROM可是非常有限啊,通常都是以K计的,9M的表,太夸张了吧!
鲜美,你又顽皮了。 --------------------编程问答-------------------- ..........顶顶..

不过对于42楼的说法,我觉得这表是用于数据处理的.....不是写到单片机里的吧.......

匿...... --------------------编程问答-------------------- 强大》。。。。。。。。 --------------------编程问答-------------------- ..........顶顶.. ..........顶顶..  --------------------编程问答-------------------- 拿c++封个库不是效率更高?何必拘泥于什么语言? --------------------编程问答-------------------- 左移右移不是可以用 >>  和  <<  吗?

比如 
         Dim test As Byte = 64
        MsgBox(test >> 2) --------------------编程问答-------------------- 学习乎 --------------------编程问答-------------------- ding  --------------------编程问答--------------------
引用 38 楼 jennyvenus 的回复:
顶一把小仙妹。 
--------------------编程问答-------------------- 果然bt --------------------编程问答-------------------- 果然变态 + 很久不见小仙妹 = 狂顶此帖

关于类似这种问题,我的另一个变态解决方案是用VC写一个DLL提供所需的功能函数。然后把DLL作为VB的资源文件整合到单一EXE文件中。用的时候把DLL释放到临时目录中然后调用。这样一直干得好好的,可是不知从什么时候开始,杀毒软件不让从临时文件目录调用可执行代码了,弄得我很头疼。所以说,还是小仙妹更加变态哦!

--------------------编程问答-------------------- 非常累的算法 --------------------编程问答-------------------- 不错。。。。 --------------------编程问答-------------------- 冲着小仙妹这三个字来的:) --------------------编程问答-------------------- 不错,支持啊! --------------------编程问答-------------------- 看来里面有相当多要学习啊~~ --------------------编程问答-------------------- 吃多了撑得 --------------------编程问答-------------------- 牛呀 --------------------编程问答-------------------- 我什么时候到达到楼主的水平呀。 --------------------编程问答-------------------- 顶

过来崇拜一下 --------------------编程问答-------------------- 我来顶 --------------------编程问答-------------------- 看见不少高人啊 --------------------编程问答--------------------
引用 55 楼 liangqingzhi 的回复:
冲着小仙妹这三个字来的:)
--------------------编程问答-------------------- 看不懂 --------------------编程问答-------------------- KiteGirl(小仙妹):
好妹妹,你真棒!你的FlashBit真的很不错!
我真的很受启发,也很受用!
谢谢!如果有机会一定很想认识一下你!
向你致敬!!! --------------------编程问答-------------------- 时间是很宝贵的,何必浪费在这上面? --------------------编程问答-------------------- VC写个DLL导出函数,用VB调用,比你的可靠强壮多少倍。 --------------------编程问答-------------------- fl --------------------编程问答-------------------- --------------------编程问答-------------------- 友情up --------------------编程问答-------------------- 友情up --------------------编程问答-------------------- --------------------编程问答-------------------- 不懂,up --------------------编程问答-------------------- 查表确实非常快,不过可能我以前的用法有误,当表比较大的时候(大概15M左右),程序性能下降很多,当时我是把整个表全部读到一个动态数组中查的.后来作性能对比的时候发现比直接算还慢,于是就把精力花在算计优化上了.

希望能知道楼主是怎么查表的 --------------------编程问答-------------------- 介个真的很牛逼哇 --------------------编程问答-------------------- up --------------------编程问答--------------------
引用 47 楼 wzuomin 的回复:
左移右移不是可以用 >>  和  < <  吗?

比如
        Dim test As Byte = 64
        MsgBox(test >> 2)

这是net中的用法么? --------------------编程问答-------------------- 【VB下实现对Bit操作的一组实用函数】
占位学习! --------------------编程问答-------------------- 哥看的不是vb是寂寞 --------------------编程问答-------------------- 我了个去,如何达到lz的深度 --------------------编程问答-------------------- 不得不说。VB确实能做所有工作。但是有的东西实现起来确实很变态才行。

不得不说楼主也很变态。。。。

不看这个了。收藏了。以后用到再看。死脑细胞呀。 --------------------编程问答--------------------
补充:VB ,  COM/DCOM/COM+
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,