跳到主要内容

一种简单的压缩算法

· 阅读需 5 分钟
wener

使用环境:简单加密,使用字符串的读取方式,压缩杂项数据

基本原理:也就是把混乱的数据中的00字节去掉。

我想到使用这个压缩方法的时候是为了在文件io很慢的环境下一次性读取较多的文件内容,从而进行的压缩。在很多情况下字符串都是以00结尾的,所以这个压缩的算法只是把数据中的00字节去掉了。当被处理的文件中很多00的时候压缩率较大。但是不适宜对文本,图片之类的压缩。注意,只是简单的压缩,压缩后能够简单的解压缩。在压缩普通数据的时候,大概平均压缩率能够达到 3 :4

 

E.g.              90 80 29 00 78 98 00 00

这段数据被压缩后的结果是

{ 00 010011 } 90 80 29 78 98  注意只能表示 90 80 29 00 78 98 这6位数据

{}为1byte大小

一看这个列子就很简单了吧

 

第一byte为标志位。

具体说明

 

1     全为0位 若数据全为00 则此位为1

E.g.  00 00 00 00 00 00 => 标志位{ 10 000000 }

2     全为1位 若数据全不为00 则此位为1

E.g.  01 02 03 04 05 06  => 标志位{ 01 000000 } 01 02 03 04 05 06

此时数据变大

3-8 位表示该位是否为00 若是则为 1 当 1th 或2ed 不全为0时,可以忽略后面的 3-8位

 

所以 一个标志位最多能够表示后面的6字节数据,此时消除了数据中的00位,就可以用字符串的读取方式来一次性读取,或者做简单的加密。

 

一个示例的程序:

是用的步步高学习机的一种叫做BBasic的环境下写的,这个算法其实就是为了应付它io极其的慢的毛病。

这个代码我也只能说表达的是那个意思,如果稍加改造下,大概能够提速10倍 - 100 +倍。

declare function dechex$( decVal)

declare function bindec( binVal$)

'//把所给的一段数据压缩

'//步骤   我先考虑是内存的情况,也就是给出一个位置偏移,然后挨个去读

dim XDB_GetOffset, XDB_GetLen, XDB_GetStr$, XDB_PutFp, XDB_I

dim XDB_GetCur, XDB_AllZ, XDB_AllO

dim Xbd_Offset_Cur

dim XDB_HStr,XDBCStr, XDB_CStr

dim XDB_HCode

dim XDB_GetStr_len

asm

 

ld int [ vint_XDB_GetOffset], 0

 

endasm

XDB_GetLen = 7685 - 16

 

'ab cd 00 39 09 28

'19 08 02 18 00 00

'82 10 00 28 19 00

 

open "x.txt" for binary as #1

 

XDB_GetStr_len = 0

XDB_HCode = 0

XDB_GetStr$ = ""

XDB_CStr$ = ""

XDB_HStr$ = ""

t = gettick()

while XDB_I <= XDB_GetLen

 

locate( 1, 1)

 

XDB_I = XDB_I + 1

 

Xbd_Offset_Cur = XDB_I mod 6

 

if Xbd_Offset_Cur = 0 then

 

if XDB_AllZ then

XDB_CStr$ = ""

end if

XDB_GetStr=XDBGetStr = XDB_GetStr + chr(bindec(XDBAllO( bindec( XDB_AllO + XDB_AllZ+XDBHStr +XDB_HStr )) + XDB_CStr$

 

 

 

XDB_HStr$ = ""

XDB_HCode = 0

XDB_CStr$ = ""

XDB_AllZ$ = "1"

XDB_AllO$ = "1"

 

XDB_GetStr_len = XDB_GetStr_len + 1

 

if XDB_GetStr_len > 4088 * 4 then

print XDB_I

put #1, XDB_GetStr$

XDB_GetStr$ = ""

end if

 

end if

 

'print "第二步"

 

asm

ld int [ vint_XDB_GetCur], 0

ld int r0, [ vint_XDB_GetOffset]

ld byte [ vint_XDB_GetCur], [ r0 ]

endasm

 

'=/当前位为非0

if XDB_GetCur then

 

XDB_CStr=XDBCStr = XDB_CStr + chr(XDBGetCur)"."+dechex( XDB_GetCur)'"." + dechex( XDB_GetCur)

XDB_HStr=XDBHStr = XDB_HStr + "0"

'==//全为0的标志位

XDB_AllZ$ = "0"

 

'=/当前位为0

else

XDB_HStr=XDBHStr = XDB_HStr + "1"

'==//全为1的标志位

XDB_AllO$ = "0"

end if

 

XDB_GetStr_len = XDB_GetStr_len + 1

'==//一次处理12位

XDB_GetOffset = XDB_GetOffset + 1

 

wend

 

print "用时"; gettick() - t

 

 

put #1, XDB_GetStr$

 

put #1, "END"

 

close #1

asm

 

jmp QingWuShi_XDB:

 

XDB_Compression_HCode:

.block 1 0

 

XDB_Compression_CCode:

.block 6 0

 

XDB_Compression_Catch:

.block 15 0

 

XDB_Compression_Base:

 

endasm

 

 

 

asm

ret

 

data x bin %abcd00390928190802180000821000281900%

 

QingWuShi_XDB:

endasm