[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
本帖最后由 CrLf 于 2016-10-7 02:00 编辑

回复 15# plp626


8192 的 Base64 压缩后是 4987 字节(含映射表,比 Base64 多用了 $@#| 四种字符):
  1. $20$1410@26144@U$@@2814@5B$@@2aUQ@i@|$10KFAAAChQAAAoUAAA$11kJCQ$13CQkJ$14A|TVqQAAM$144E$144//8AALg$149Q$1410$14bg$1454fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJ$149BQRQAATAEFAJOHz1c$14aOAADwMLAQI4AAw$144U$145gAAIBI$144Q$144I$@284Q$145gAAB$145E$144E$14aBg$144BAAAUV0AAAM$146CAAAB$146EAAAE$148B$14gBQAABAAw$204$147C50ZXh0$144FAo$144Q$144D$145Q$14iGAAAGAuZGF0YQAAAE$146I$145I$144Q$14iBAAADALnJkYXRhAADw$145D$145C$144Eg$14iQAAAQC5ic3M$145s$@28uIAAAMAuaWRhdGEAAEAD$144U$145Q$144U$14iBAAAD$20g$14mFWJ5YPsGIld+ItVCDHbiXX8iwIx9osAPZEAAMB3Qz2NAADAclu+AQAAAMcEJAg$144xwIlEJATopAgAAIP4AXRshcB0KscEJAgAAAD/0Lv/////idiLdfyLXfiJ7F3CBAA9kwAAwHS9PZQAAMB0u4nYi3X8i134iexdwgQAjXYAPQUAAMB16McEJAs$144x9ol0JAToRwgAAIP4AXQ0hcB0zccEJAsAAAD/0OuhxwQkC$144LsB$144iVwkBOgeCAAAhfZ0iOhFAwAAu//////rgccEJAsAAAC5AQAAALv/////iUwkBOj0BwAA6WL////rDZ$134BVieVTg+wkjV34xwQkABBAAOiKCAAAg+wE6PICAADHRfg$145uABAQACNVfSJXCQQiw0AIEAAiUQkBIlUJAiJTCQMxwQkBEBAAOjBBwAAoRBAQACFwHRYoxAgQACLFSRRQACF0g+FiwAAAIP64HQgoRBAQACJRCQEix0kUUAAi0swiQwk6HYHAACLFSRRQACD+sB0G4sdEEBAAIlcJASLDSRRQACLUVCJFCToUAcAAOg7BwAAix0QIEAAiRjoHgIAAIPk8OgGBwAAiwiJTCQIixUAQEAAiVQkBKEEQEAAiQQk6KkAAACJw+jSBgAAiRwk6LoHAACJRCQEixUkUUAAi0IQiQQk6PUGAACLFSRRQADpVf///412AI28Jw$144BVieWD7AjHBCQB$144/xUcUUAA6Mj+//+QjbQm$145FWJ5YPsCMcEJAIAAAD/FRxRQADoqP7//5CNtCY$145VYsNNFFAAInlXf/hjXQmAFWLDShRQACJ5V3/4ZCQkJBVieVd6VcDAACQkJCQkJCQVbgQ$144ieVXVlOD7AyLXQiLdQyD5PDodAUAAOgPAgAAxkXzAIP7Ab/oAwAAD4+C$144g/sCfiqLRggPtgiA+XgPlcIxwID5WA+VwIXCdF+A+WQPlMCA+UQPlMIJ0KgBdWUx9oX/D5TAOf4PnMIJ0KgBD4SL$144uwEAAADrCpBDgfv+$144f2iJHCTobwYAAIPsBGaFwHnngH3zeHRAgH3zZHQoidiNZfRbXl9dw8ZF83jrrYtGBIkEJOjgBQAAicfpbP///8ZF82TrlYlcJATHBCQAMEAA6LMFAADrxolcJATHBCQDMEAA6KEFAADrtMcEJAEAAABG6BIFAADpYf///4B983h0LIB982R0B7j/$14465HHBCQAMEAAuP8AAACJRCQE6GUFAAC4/wAAAOly////xwQkAzBAALr/$144iVQkBOhGBQAA69+QkJCQVbnwMEAAieXrFI22$145ItRBIsBg8EIAYIAAEAAgfnwMEAAcupdw5CQkJCQkJCQVYnl2+Ndw5CQkJCQkJCQkFWJ5YPsCKEgIEAAiwiFyXQm6w2Q$114/xCLDSAgQACLUQSNQQSjICBAAIXSdenJw420Jg$144BVieVTg+wEoQAaQACD+P90KYXAicN0E4n2jbwn$145P8UnQAaQABLdfbHBCQgFEAA6Mr9//9bW13Diw0EGkAAMcCFyesKQIsUhQQaQACF0nX0672Ntg$144CNvw$144BVieVTg+wEoSBAQACFwHU2oQAaQAC7AQAAAIkdIEBAAIP4/3QlhcCJw3QPkI10JgD/FJ0AGkAAS3X2xwQkIBRAAOha/f//W1tdw4sNBBpAADHAhcnrCkCLFIUEGkAAhdJ19OvB$114VaFwQEAAieVdi0gE/+GJ9lW6QgAAAInlUw+3wIPsZIlUJAiNVagx24lUJASJBCT/FfRQQAC6HwAAALkB$144g+wMhcB1B+tGAclKeA6AfCqoQXX0CcsByUp58oM7PHUHidiLXfzJw7k0MEAAuuoAAACJTCQMiVQkCMcEJGEwQAC4gDBAAIlEJATokgIAALisMEAAu+QAAACJRCQMiVwkCOvXjbQm$145I28Jw$144BVieVXVlOB7MwAAACLDXBAQACFyXQIjWX0W15fXcPHRZhBQUFBoRAwQACNdZjHRZxBQUFBx0WgQUFBQYlFuKEUMEAAx0WkQUFBQcdFqEFBQUGJRbyhGDBAAMdFrEFBQUHHRbBBQUFBiUXAoRwwQADHRbRBQUFBiUXEoSAwQACJRcihJDBAAIlFzKEoMEAAiUXQoSwwQACJRdQPtwUwMEAAZolF2Ik0JP8V8FBAAA+3wIPsBIXAiYVE////D4U7AQAAxwQkP$144OijAgAAhcCJww+EWQEAAPyJx4uFRP///7kP$14486vHQwRgGUAAuQEAAADHQwgwFUAAoUBAQADHAzwAAACLFURAQADHQyg$145iUMUoTAgQACJUxiLFTQgQACJQxyhUEBAAIlTIMdDMP////+JQyyLFTwgQAChOCBAAIlTOLof$144iUM0ifaJ2CHIg/gBGcAkIAHJBEGIhCpI////SnnnoRAwQACJhWj///+hFDBAAImFbP///6EYMEAAiYVw////oRwwQACJhXT///+hIDBAAImFeP///6EkMEAAiYV8////oSgwQACJRYChLDBAAIlFhA+3BTAwQABmiUWIjYVI////iQQk/xXoUEAAD7f4g+wEhf91QjHShdJ1HokcJOhzAQAAiTQk/xXwUEAAg+wED7fA6F/9//+Jw4kdcEBAAI1DBKNgQEAAjUMIo4BAQACNZfRbXl9dw4n46Dj9//852In6dbHrsehLAQAAkJCQkJCQkJCQkJBRieGDwQg9ABAAAHIQgekAEAAAgwkALQAQAADr6SnBgwkAieCJzIsIi0AE/+CQkJBVieWD7BiLRRSJRCQQi0@2akDItFDIlEJAiLRQiJRCQEoSRRQACDwECJBCTo/gAAAKEkUUAAg8BAiQQk6N4AAADoyQAAAJCQkJCQkJCQkP8lBFFAAJCQ$14aD/JRxRQACQk$14b/yUgUUAAkJ$14bP8lFFFAAJCQ$14aD/JVBRQACQk$14b/yUYUUAAkJ$14bP8lLFFAAJCQ$14aD/JRBRQACQk$14b/yVMUUAAkJ$14bP8lOFFAAJCQ$14aD/JURRQACQk$14b/yVIUUAAkJ$14bP8lMFFAAJCQ$14aD/JTxRQACQk$14b/yVAUUAAkJ$14bP8lXFFAAJCQ$14aD/JfhQQACQk$14b/yXsUEAAkJ$14bP8l9FBAAJCQ$14aD/JfBQQACQk$14b/yXoUEAAkJ$14bFWJ5V3ph/j//5CQkJCQkJD/////8Bl$147D/////$20i$14dP////8$14hQ$14jEBp$14nD/////$145P////8$20g$14lJWQAJXg$14eC1MSUJHQ0NXMzItRUgtMi1TSkxKLUdUSFItTUlOR1czMgAAAHczMl9zaGFyZWRwdHItPnNpemUgPT0gc2l6ZW9mKFczMl9FSF9TSEFSRUQpACVzOiV1OiBmYWlsZWQgYXNzZXJ0aW9uIGAlcycKAAAuLi8uLi9nY2MvZ2NjL2NvbmZpZy9pMzg2L3czMi1zaGFyZWQtcHRyLmMAAEdldEF0b21OYW1lQSAoYXRvbSwgcywgc2l6ZW9mKHMpKSAhPSAw$20b$146BoU$14dDAUgAA6FAAAIRQ$14dNRSAAAEUQAAkF$14eJFMAABBRAADcU$14e0UwAAXFE$14yGRRAABwUQAAgFEAAIxRAACcUQ$14cC8UQ$14cDIUQAA2FEAAOhRAAD4UQAADFIAABhSAAAgUgAALFIAADhSAABAUgAATFIAAFRSAABgUgAAbFIAAHRSAACAUgAAjFI$14dmFI$14dZFEAAHBRAACAUQAAjFEAAJxR$14dLxR$14dMhRAADYUQAA6FEAAPhRAAAMUgAAGFIAACBSAAAsUgAAOFIAAEBSAABMUgAAVFIAAGBSAABsUgAAdFIAAIBSAACMUg$14cCYUg$148EAQWRkQXRvbUEAAJsARXhpdFByb2Nlc3MAAACvAEZpbmRBdG9tQQDcAEdldEF0b21OYW1lQQAA3wJTZXRVbmhhbmRsZWRFeGNlcHRpb25GaWx0ZXIAAABIAF9zbGVlc$146nAF9fZ2V0bWFpbmFyZ3MAPABfX3BfX2Vudmlyb24AAD4AX19wX19mbW9kZQ$144BQAF9fc2V0X2FwcF90eXBl$145HkAX2NleGl0$145OkAX2lvYgAAXgFfb25leGl0$144hAFfc2V0bW9kZQAAFQJhYm9ydAAcAmF0ZXhpd$146eAmF0b2kAADACZmZsdXNo$145DkCZnByaW50ZgAAAD8CZnJlZQAAcgJtYWxsb2M$145fwJwcmludGY$145kAJzaWduYWw$1453gBHZXRBc3luY0tleVN0YXRl$@26F$144BQ$@26FAAAEtFUk5FTDMyLmRsb$146UUAAAbXN2Y3J0LmRsbAAA$105KFAAAChQAABtc3ZjcnQuZGxsAAA8UAAAVVNFUjMyLmRsb$207$147
复制代码
基本思路:
模仿卷积神经网络的原理,将压缩流程分成采样层和“卷积层”(什么鬼)交替的结构
第一层采样 -> 第一层压缩 -> 第二层采样 -> 第二层压缩 -> 以此类推,如加入参数变量,理论上可扩展到无限层采样

初次使用时,先将特殊字符转义(第零层)
第一层优先进行 AAAAAAA 模式的匹配
从第二层开始,同时匹配 AAAAAAA 或 AAABAAACDAAAEAAA 两种模式

采样层负责解析统计 AAAAAAA 或 AAABAAACDAAAEAAA 这两种可压缩的基本形式,并预估压缩比,对压缩比排序后,保留压缩效果最靠前的部分样本
由于采样内容也包括映射表,所以事实上只要层数够多、参数够大,任何重复的字符串的最终都可以归纳为这两种基本形式

处理层负责根据采样层的建议进行压缩,将每个匹配的样本压缩为索引格式,索引分两种:
-----------------------------------------------------------------------------------------------------------
将 AAAAAAA 映射为 $117,其意义为:
模式  层数  该层序号  重复次数
$     1       1            7
$117 的映射表为 $11A,此处的 A 为其原始字符串
-----------------------------------------------------------------------------------------------------------
将 AAABAAACDAAAEAAA 映射为 @12,其意义为:
模式  层数  该层序号
@     1       2
@12 的映射表为 @12AAA@B@CD@E@,此处的 AAA 为其重复的字符串,@B@CD@E@ 为其所在的序列
该模式下,根据 AAA 的长度,对附近范围的字符串做采样测试,以寻找压缩效果最佳的样本
-----------------------------------------------------------------------------------------------------------
例如将:
AAAAAAAAAAAAAAAAAAEFAAABAAACAAADAAAEFAAAGAAAHHAAAAI
压缩为(红字为映射表,蓝字为压缩后的编码):
@10AAA@@B@C@D@EF@G@HH@$11A|$11iEF@10AI
-----------------------------------------------------------------------------------------------------------


没写解压脚本,只写了压缩脚本,默认进行 3 层采样/压缩:
  1. 1>1/* :
  2. @echo off
  3. set "Input=原始文件.txt"
  4. set "Output=压缩后.txt"
  5. cscript /nologo /e:jscript %0 <"%Input%" 2>"%Output%"
  6. pause
  7. exit /b
  8. */
  9. var DEBUG = true
  10. var maxdeep = 3
  11. var base64 = WSH.StdIn.ReadAll()
  12. var map = []
  13. var len = base64.length
  14. var text = compress(base64.replace(/\r\n/gm,''), maxdeep)
  15. WSH.StdOut.WriteLine('')
  16. WSH.StdOut.WriteLine(text)
  17. WSH.StdOut.WriteLine('')
  18. WSH.StdOut.WriteLine('#Before = #' + len)
  19. WSH.StdOut.WriteLine('#After  = #' + text.length)
  20. WSH.StdErr.WriteLine(text)
  21. function compress(text, deep){
  22. deep = deep || 3
  23. if(deep>36)deep = 36
  24. var from_list = [
  25. [
  26. {from:'#', mode:'#'},
  27. {from:'$', mode:'#'},
  28. {from:'@', mode:'#'},
  29. {from:'|', mode:'#'}
  30. ]
  31. ]
  32. text = convolution(text,from_list[0],0)
  33. var len = text.length
  34. for(var i=1; i<=deep; i++){
  35. var $len = text.length
  36. var from_arr = sample(text, i)
  37. from_list.push(from_arr)
  38. text = convolution(text,from_arr,i)
  39. text = getHead(from_arr,i) + text
  40. if(DEBUG)WSH.Echo('\r\n'+len +' -> '+$len+' -> '+text.length+'\r\n')
  41. }
  42. return text.replace(/^\|+/,'').replace(/\|+/,'|')
  43. function getHead(from_arr){
  44. if(!from_arr.length)return ''
  45. var head=''
  46. for(var i=0; i<from_arr.length; i++){
  47. switch(from_arr[i].mode){
  48. case '$':
  49. head+='$'+from_arr[i].map+from_arr[i].from
  50. break
  51. case '@':
  52. head+='@'+from_arr[i].map+from_arr[i].from+from_arr[i].list
  53. break
  54. }
  55. }
  56. head+='|'
  57. return head
  58. }
  59. function sample(text, index_deep){
  60. var from_map_repeat = {}
  61. var from_map_like = {}
  62. var from_map_like_stack = []
  63. if(index_deep==1){
  64. var pattern = /(.+?)\1{2,36}/gm
  65. } else {
  66. var pattern = /(.+?)\1{2,36}|(..+)(?:[^@]{1,5}?\2)+/gm
  67. }
  68. pattern.lastIndex = 0
  69. while((matches=pattern.exec(text)) != null){
  70. if(DEBUG)WSH.StdOut.Write('\r\t\t\t\rpattern.lastIndex = ' + pattern.lastIndex)
  71. if(matches[1]){
  72. checkrepeat(pattern,matches[0],matches[1])
  73. } else {
  74. checklike(pattern,matches[0],matches[2])
  75. }
  76. }
  77. function checkrepeat(pattern,str,$1){
  78. var cutoff = str.length - $1.length - 7
  79. if('$'+$1 in from_map_repeat){
  80. cutoff = str.length - 4
  81. from_map_repeat['$'+$1].cutoff += cutoff
  82. } else {
  83. cutoff = str.length - $1.length - 7
  84. from_map_repeat['$'+$1] = {from:$1, mode:'$', cutoff:cutoff}
  85. }
  86. from_map_like_stack = []
  87. }
  88. function checklike(pattern,str,$2){
  89. var $$2 = $2.replace(/\W/gm,'\\$&')
  90. var nextIndex = $2.length<2 ? pattern.lastIndex : pattern.lastIndex - str.length + 1
  91. str = str.replace(
  92. new RegExp('('+$$2+')(?='+$$2+')$','gm'),
  93. function(repeat){pattern.lastIndex-=repeat.length;return ''}
  94. )
  95. var list = convolution(str,from_list[0],index_deep).replace(new RegExp($2.replace(/\W/gm,'\\$&'),'gm'),'@')
  96. var cutoff
  97. if(str in from_map_like){
  98. cutoff = str.length - 4
  99. from_map_like[str].cutoff += str.length - 4
  100. } else {
  101. str=list.replace(/@/g,$2.replace(/\W/g,'\\$&'))
  102. cutoff = str.length - list.length - 7
  103. from_map_like[str] = {from:$2, mode:'@', str:str, list:list, cutoff:cutoff}
  104. }
  105. from_map_like[str].$length = $2.length+list.substr(1).search('@')
  106. var thisstack = {lastIndex:pattern.lastIndex, $length:$2.length+list.substr(1).search('@'), flag:true, cutoff:cutoff, ref:from_map_like[str]}
  107. from_map_like_stack.push(thisstack)
  108. for(var i=from_map_like_stack.length;i--;){
  109. var stack = from_map_like_stack[i]
  110. var endof = stack.lastIndex+stack.$length
  111. if(endof<pattern.lastIndex){
  112. from_map_like_stack.splice(i+1)
  113. break
  114. } else if(stack.cutoff > cutoff){
  115. if(stack.ref.flag)stack.ref.cutoff -= cutoff
  116. stack.ref.flag = false
  117. } else {
  118. thisstack.ref.cutoff -= cutoff
  119. thisstack.flag = false
  120. }
  121. }
  122. pattern.lastIndex = nextIndex
  123. return str
  124. }
  125. var from_arr = []
  126. for(var from in from_map_repeat)from_arr.push(from_map_repeat[from])
  127. for(var from in from_map_like)from_arr.push(from_map_like[from])
  128. for(var i=from_arr.length;i--;)if(from_arr[i].cutoff<2)from_arr.splice(i,1)
  129. from_arr = from_arr.sort(
  130. function(a,b){
  131. return b.cutoff - a.cutoff
  132. }
  133. ).sort(
  134. function(a,b){return b.from.length - a.from.length}
  135. )
  136. if(DEBUG){
  137. WSH.Echo('')
  138. WSH.Echo('')
  139. WSH.Echo('Deep = '+ index_deep)
  140. for(var i in from_arr){
  141. WSH.Echo(from_arr[i].from+'->'+ from_arr[i].mode+index_deep+'(?)')
  142. for(var j in from_arr[i]){
  143. WSH.Echo(j + '\t=  '+ from_arr[i][j])
  144. }
  145. WSH.Echo('')
  146. }
  147. }
  148. return from_arr
  149. }
  150. function convolution(text,from_arr,index_deep){
  151. for(var i=0,count=0; i<from_arr.length; i++){
  152. from_arr[i].done = false
  153. switch(from_arr[i].mode){
  154. case '$':
  155. from_arr[i].map = index_deep.toString(36) + count.toString(36)
  156. text = text.replace(
  157. new RegExp('('+(from_arr[i].from.replace(/\W/gm,'\\$&'))+'){4,36}','gm'),
  158. function(str,from){count++;from_arr[i].done=true;return '$'+from_arr[i].map+parseInt(str.length / from.length).toString(36)}
  159. )
  160. break
  161. case '@':
  162. from_arr[i].map = index_deep.toString(36) + count.toString(36)
  163. text = text.replace(
  164. new RegExp(from_arr[i].str.replace(/\W/gm,'\\$&'),'gm'),
  165. function(str,from){count++;from_arr[i].done=true;return '@'+from_arr[i].map}
  166. )
  167. break
  168. case '#':
  169. text = text.replace(
  170. new RegExp(from_arr[i].from.replace(/\W/gm,'\\$&'),'gm'),
  171. function(str,from){count++;from_arr[i].done=true;return '#'+from_arr[i].map}
  172. )
  173. break
  174. }
  175. if(count>=36){
  176. from_arr.splice(i)
  177. break
  178. }
  179. }
  180. for(var i=from_arr.length;i--;){
  181. if(!from_arr[i].done)from_arr.splice(i,1)
  182. }
  183. return text
  184. }
  185. }
复制代码
3

评分人数

TOP

这年头, 有几天没冒泡的人肯定搞 AI 去了

TOP

回复 16# CrLf

感谢分享;

没怎么看懂,不过你可以把原始数据用rar最小体积压缩一下,然后*4/3和你这个体积比较下,就大概能知道你这个算法的威力。

还有个问题,你在替换重复串时,控制字符后面的数字,怎么和没有被压缩的原始数据的数字区分?

TOP

回复 16# CrLf

我不知道这个的原数据究竟是啥, 你就不要说了, 解压代码也暂时不要发了, 大家有兴趣的可以尝试写出解压代码, 瞅瞅能不能 还原 出原始数据

有点意思吧

TOP

本帖最后由 CrLf 于 2016-10-7 02:06 编辑

回复 18# plp626


因为是针对 Exe 的 Base64 编码在可见字符范围内进行压缩,跟 7z、rar 实际上是不能比的,实测 rar 压缩同一个文件的结果为 2934 字节,7Z 为 2973 字节
在一定程度上借鉴了霍夫曼编码的思路,只不过具体实现以正则为主,很多地方为提高速度做了简化,然而因为无论是压缩还是解压缩都需要逐层进行,所以速度肯定是很慢的
目测还有些地方明显重复,如果加大参数,应该可以再优化掉约 500 字节,当然那样压缩就更慢了,正则引擎不停地贪婪匹配和回溯...想想都恐怖

特殊字符后面字数是可预期或有终止符的

正文索引定长:
转义的字符定长为 2,正则表达式为 #\d
正文部分被替换的 repeat 索引定长为 4,正则表达式为 \$\d\d\w
正文部分被替换的 like 索引定长为 3,正则表达式为 @\d\d

映射表不定长:
每层映射表终止于 |,正则表达式为 [^|]+\|
repeat 模式的映射表可以用正则表达式表达为 \$\d\d[^$@|]
like 模式的映射表可以用正则表达式表达为 @\d\d(@[^$@|]*)+@

TOP

回复 19# aa77dd@163.com


    原来的映射表有歧义,我再调整下表达

TOP

本帖最后由 523066680 于 2016-10-6 22:05 编辑

回复 19# aa77dd@163.com

    应该就是你1楼里面那堆base64

觉得这种有大量重复信息的压缩处理都适合借用图片的压缩算法(行程编码、LZW编码、霍夫曼编码 —— 我只是熟悉这些词汇的拼写    )

回复 20# CrLf

    感觉已经被甩了10086条街这么远

回复 18# plp626
   
    卷积神经网络现在是热门了,图像处理方面(模糊识别、手势识别)和机器学习方面应用广泛。但是只听过,未曾接触细节。

卷积神经网络及其在图像处理中的应用

TOP

本帖最后由 CrLf 于 2016-10-7 02:06 编辑

回复 22# 523066680

我扯淡啊,看起来像而已,哪有卷什么积...

算法已优化,实测对 Base64 的压缩比大约在 55%~65% 左右浮动

例如 576 字节长的编码:
  1. TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAEFAJOHz1cAAAAAAAAAAOAADwMLAQI4AAwAAAAUAAAAAgAAIBIAAAAQAAAAIAAAAABAAAAQAAAAAgAABAAAAAEAAAAEAAAAAAAAAABgAAAABAAAUV0AAAMAAAAAACAAABAAAAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAAABQAABAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC50ZXh0AAAAFAoAAAAQAAAADAAAAAQAAAAAAAAAAAAAAAAAAGAAAGAuZGF0YQAAAEAAAAAAIAAA
复制代码
压缩后是 345 字节:
  1. $20$1010|$10A|TVqQAAM$104E$104//8AALg$109Q$1010$10bg$1054fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJ$109BQRQAATAEFAJOHz1c$10aOAADwMLAQI4AAw$104U$105gAAIBI$104Q$104I$105B$104Q$105gAAB$105E$104E$10aBg$104BAAAUV0AAAM$106CAAAB$106EAAAE$108B$10gBQAABAAw$204$107C50ZXh0$104FAo$104Q$104D$105Q$10iGAAAGAuZGF0YQAAAE$106IAAA
复制代码
目测如果不引入更多可用字符,剩余的优化空间大约在 5% 左右。

另外找了个 .xls 文件(37.5KB)来测试,将其 Base64 编码(50KB)压缩至 27.5KB,压缩率 55%,不过嘛...
毕竟该算法只用到 68 种字符,压缩比还是有瓶颈,而且效率是慢的一逼
winrar 直接压缩原文件为 15%,压缩 Base64 为 31%

TOP

回复 23# CrLf
多了4个字符,转码比为16/17,省掉%6的存储,根据字母频率打表,为何不直接转成二进制,根据二进制组合频率构建二进制动态码表。那样理论上会达到原始文件的rar压缩体积。

TOP

本帖最后由 aa77dd@163.com 于 2016-10-7 10:41 编辑

回复 24# happy886rr

英语为什么要用 26 个字母呢,  汉语为什么要用数千甚至上万汉字呢, 即使拆成字根也有好几十甚至上百

最初的程序都是由机器码, 也就是 看起来 只用 0 和 1 这样形式的代码来表达的, 为什么要把 8 位编成一组做一个字节呢,

即使编成一个字节的机器码, 为什么又要用汇编的形式来助记呢,  

文件系统为什么要簇, 区等方式来实现呢

除了是人机接口的问题, 也还有信息管理的层次规划问题


直接用二进制, 换言之, 只用两个元字符作为基本语言单位

理论上是可以实现任何程序, 但对人类而言并不是好的方案

计算和存储的基本单位都是 字节, 而不是位,

即便用汇编语言, 寄存器能操作的最小存储单元也一样是 字节, 而不是位

比如 C 语言中你想检测哪一位是 1 还是 0,

你能用的最小数据类型无非是 byte,  但没有 bit 这样的数据类型

最终检测某一个位上是 0 还是 1 却还是通过至少一个字节以上的数据类型来实现的

byte v;

v = 23;

if ((v >> 3) & 1) {
   // 若定义位序号是从最右开始,往左依次是 0, 1, 2, ...
   // 此处即是检测第 3 位是 1
} else {
   // 第 3 位是 0
}

TOP

本帖最后由 happy886rr 于 2016-10-7 10:46 编辑

回复 25# aa77dd@163.com
我只是针对base64的压缩,因为base64一般只传输比较小的文件,对于小文件可以尝试直接转为0和1来深度压缩。对于超过1M的大文件已经没有必要用base64压缩了,直接上rar。

还有这里无需直接读取位,base64已经按位转码了一次,base64的每个字符都是6位bit,我们已经得到可bit的结构。只需要统计01000000或者其他什么的01101000001的位组合,哪个出现的多,就把哪个用一个码替换,然后设置一个非可打印字符开关码,遇到这个码,就开启非可打印字符开关编码。只是这个流程我需要用C语言构思一下。

TOP

回复 26# happy886rr

简单来说, 你的想法是要 把  信息处理单位用最小的 位 ( bit ), 我觉得并不是不能实现,

问题是无论压缩还是解压缩, 一 代码的复杂度将增大很多, 二, 代码的执行效率上也会严重的降低

TOP

本帖最后由 happy886rr 于 2016-10-7 10:55 编辑

回复 27# aa77dd@163.com
转化成二进制,就只需要移位了,连正则都省了。这里需要对文件流lines做个自身比对
比如line1=1010111111110000000000001,再复制个line2=line1,让line2在line1下方不断移动
比如此时line2=1010111111110000000000001
他们的重合区域就出现↑↑↑↑↑       ↑↑↑↑↑↑↑↑↑↑
这样不断移位,找重合区域来设置新码表

TOP

本帖最后由 aa77dd@163.com 于 2016-10-7 11:03 编辑

回复 28# happy886rr

无论你的算法是怎样的, 在现在的数字电子计算机上, 你算法中的一切数据变量都只能用最小 一个字节 的数据类型 来实现, 算法处理的结果也 只能 转化成 字节 来输出存储

从原始数据中, 你要将 字节流 看成 位流 来处理, 这需要一次转化,

最终的 位流 的结果, 你仍然要再逆转化还原成 字节流, 这样两次转化将增加很多复杂度, 另外, 时间耗费也将严重增加

信息压缩 是以时间来换取空间的, 在时间和空间的矛盾上, 需要权衡, 为了空间上的极限, 却要面对过度的时间牺牲的话, 不可取

TOP

回复 29# aa77dd@163.com
不过对于批处理中的base64,应该用几行简短的批处理去实现base64的压缩还原。就那你getkey的base64码来说,那些代码中只有A最多,只需替换A即可。

TOP

返回列表