Board logo

标题: [系统增强] 按键获取工具 neoGetKey [打印本页]

作者: aa77dd@163.com    时间: 2016-9-7 12:26     标题: 按键获取工具 neoGetKey

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

获取当前被按下的 按键虚拟键值 组合, 支持全键盘按键, 以及鼠标 左 右 中键

工具用 C 语言编写, 可以用 BASE64 编码包含进 批处理 文件

已测试通过环境: 中文 WIN7 64位


最多可获取同时按下的 4 个按键, 最小的按键虚拟键值放在最低字节, 更大的按键虚拟键值依次放在更高的字节
如果设置了超时参数, 或者以默认超时运行时, 程序将等待直到有任何按键按下 或者 运行时间达到 超时时间 为止
如果在超时前有按键按下, 将返回相应的按键组合值; 否则, 因超时而结束运行, 将返回 255.

例1:

同时按下 A S D F 四个键, 返回值:

    0x53464441 = 1397113921 = (83 << 24) + (70 << 16) + (68 << 8) + 65

四个键 的 虚拟键值分别是: A: 65  S: 83  D: 68   F:70

测试程序显示:    pressed key value is : 83 + 70 + 68 + 65

例2:

同时按下 右Ctrl 和 N 两个键, 返回值:

    0xA34E = 41806 = (163 << 8) + 78

两个键 的 虚拟键值分别是: 右Ctrl: 163  N: 78

测试程序显示:    pressed key value is : 0 + 0 + 163 + 78

例3:

按下 右方向键, 返回值:

    0x27 = 39

右方向键的虚拟键值是 39

测试程序显示:    pressed key value is : 0 + 0 + 0 + 39


测试用批处理程序
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. REM certutil 在 Windows XP 环境不是原生程序, 需要其他 BASE64 解码器
  4. certutil -f -decode "%~0" neoGetKey.exe.cab
  5. expand neoGetKey.exe.cab neoGetKey.exe
  6. for /L %%a in () do (
  7.     echo;neoGetKey:
  8.     neoGetKey.exe 1 X           &  rem 超时 1ms, 以十六进制显示返回值
  9.     REM 其他示例用法
  10.     REM neoGetKey.exe 37        &  rem 超时 37ms, 不显示返回值
  11.     REM neoGetKey.exe 500 D     &  rem 超时 500ms, 以十进制显示返回值
  12.     REM neoGetKey.exe 0         &  rem 无限等待直到按键按下, 不显示返回值
  13.     REM neoGetKey.exe           &  rem 无参数运行, 默认超时 1000ms, 并且不显示返回值
  14.     REM neoGetKey.exe X         &  rem 未设定超时参数, 第一个参数会被视为超时参数, 但参数不是数字, 将按默认超时 1000ms 处理, 并且不显示返回值
  15.     set "err=!errorlevel!"
  16.     if !err! equ 255 (echo;   time out) else (
  17.         set /a "k1=err & 0xFF, k2=err>>8 & 0xFF, k3=err>>16 & 0xFF, k4=err>>24 & 0xFF"
  18.         echo;   pressed key value is : !k4! + !k3! + !k2! + !k1!
  19.     )
  20.     echo;pause 3s
  21.     ping -n 2 localhost >nul
  22. )
  23. exit
  24. C 源码
  25. neoGetKey.exe
  26. aa77dd@163.com @ 20161007_161916
  27. 获取当前被按下的 按键 值, 支持全键盘按键, 以及鼠标 左 右 中键
  28. 参数说明:
  29.     neoGetKey.exe [timeout [showMethod]]
  30.     timeout         超时数, 单位 ms, 在运行超过此时间后自动退出, 并返回 255
  31.                     如果 此项是 0  将一直等到检测到有键按下, 程序才会结束并返回键值.
  32.                     如果 此项不存在, 最长将等到默认值 1000ms 后退出
  33.     showMethod      返回值的显示方式, 此项为 D 以十进制显示, 此项为 X 以十六进制显示
  34.                     如果此项不存在, 将不会显示返回值
  35.                     此项 要么不指定, 否则必须和 timeout 同时指定
  36. ::BEGIN:neoGetKey.C
  37. #include <Windows.h>
  38. #include <stdio.h>
  39. int main(int argc, char** argv) {
  40.     int i, t = 1000, r = 0, kshift = -8;
  41.     char show[3] = "%\0\0";
  42.     if (argc >= 2) t = atoi(argv[1]);
  43.     if (argc >= 3)
  44.         show[1] = (**(argv + 2) >= 'a') ? **(argv + 2) : **(argv + 2) + 'a' - 'A';
  45.     show[1] = ( show[1] == 'x' || show[1] == 'd') ? show[1] : '\0';
  46.     for (i = 0; t == 0 || i < t; i++) {
  47.         int x;
  48.         for (x = 1; x <= 0xFE; x++) {
  49.             if (x == VK_SHIFT || x == VK_CONTROL || x == VK_MENU)
  50.                 continue;
  51.             if (GetAsyncKeyState(x) & 0x8000) {
  52.                 r |= x << (kshift += 8);
  53.                 if (kshift >= 24) {
  54.                     if (show[1]) printf(show, r);
  55.                     return r;
  56.                 }
  57.             }
  58.         }
  59.         if (r != 0) {
  60.             if (show[1]) printf(show, r);
  61.             return r;
  62.         }
  63.         sleep(1);
  64.     }
  65.     if (show[1]) printf(show, 0xFF);
  66.     return 0xFF;
  67. }
  68. ::END:neoGetKey.C
  69. ::neoGetKey.exe.cab.b64
  70. -----BEGIN CERTIFICATE-----
  71. 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
  72. -----END CERTIFICATE-----
复制代码
虚拟键值表, 转自微软官方文档 Virtual-Key Codes
https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx

Constant/valueDescription
VK_LBUTTON
0x01
Left mouse button
VK_RBUTTON
0x02
Right mouse button
VK_CANCEL
0x03
Control-break processing
VK_MBUTTON
0x04
Middle mouse button (three-button mouse)
VK_XBUTTON1
0x05
X1 mouse button
VK_XBUTTON2
0x06
X2 mouse button
-
0x07
Undefined
VK_BACK
0x08
BACKSPACE key
VK_TAB
0x09
TAB key
-
0x0A-0B
Reserved
VK_CLEAR
0x0C
CLEAR key
VK_RETURN
0x0D
ENTER key
-
0x0E-0F
Undefined
VK_SHIFT
0x10
SHIFT key
VK_CONTROL
0x11
CTRL key
VK_MENU
0x12
ALT key
VK_PAUSE
0x13
PAUSE key
VK_CAPITAL
0x14
CAPS LOCK key
VK_KANA
0x15
IME Kana mode
VK_HANGUEL
0x15
IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
VK_HANGUL
0x15
IME Hangul mode
-
0x16
Undefined
VK_JUNJA
0x17
IME Junja mode
VK_FINAL
0x18
IME final mode
VK_HANJA
0x19
IME Hanja mode
VK_KANJI
0x19
IME Kanji mode
-
0x1A
Undefined
VK_ESCAPE
0x1B
ESC key
VK_CONVERT
0x1C
IME convert
VK_NONCONVERT
0x1D
IME nonconvert
VK_ACCEPT
0x1E
IME accept
VK_MODECHANGE
0x1F
IME mode change request
VK_SPACE
0x20
SPACEBAR
VK_PRIOR
0x21
PAGE UP key
VK_NEXT
0x22
PAGE DOWN key
VK_END
0x23
END key
VK_HOME
0x24
HOME key
VK_LEFT
0x25
LEFT ARROW key
VK_UP
0x26
UP ARROW key
VK_RIGHT
0x27
RIGHT ARROW key
VK_DOWN
0x28
DOWN ARROW key
VK_SELECT
0x29
SELECT key
VK_PRINT
0x2A
PRINT key
VK_EXECUTE
0x2B
EXECUTE key
VK_SNAPSHOT
0x2C
PRINT SCREEN key
VK_INSERT
0x2D
INS key
VK_DELETE
0x2E
DEL key
VK_HELP
0x2F
HELP key
0x300 key
0x311 key
0x322 key
0x333 key
0x344 key
0x355 key
0x366 key
0x377 key
0x388 key
0x399 key
-
0x3A-40
Undefined
0x41A key
0x42B key
0x43C key
0x44D key
0x45E key
0x46F key
0x47G key
0x48H key
0x49I key
0x4AJ key
0x4BK key
0x4CL key
0x4DM key
0x4EN key
0x4FO key
0x50P key
0x51Q key
0x52R key
0x53S key
0x54T key
0x55U key
0x56V key
0x57W key
0x58X key
0x59Y key
0x5AZ key
VK_LWIN
0x5B
Left Windows key (Natural keyboard)
VK_RWIN
0x5C
Right Windows key (Natural keyboard)
VK_APPS
0x5D
Applications key (Natural keyboard)
-
0x5E
Reserved
VK_SLEEP
0x5F
Computer Sleep key
VK_NUMPAD0
0x60
Numeric keypad 0 key
VK_NUMPAD1
0x61
Numeric keypad 1 key
VK_NUMPAD2
0x62
Numeric keypad 2 key
VK_NUMPAD3
0x63
Numeric keypad 3 key
VK_NUMPAD4
0x64
Numeric keypad 4 key
VK_NUMPAD5
0x65
Numeric keypad 5 key
VK_NUMPAD6
0x66
Numeric keypad 6 key
VK_NUMPAD7
0x67
Numeric keypad 7 key
VK_NUMPAD8
0x68
Numeric keypad 8 key
VK_NUMPAD9
0x69
Numeric keypad 9 key
VK_MULTIPLY
0x6A
Multiply key
VK_ADD
0x6B
Add key
VK_SEPARATOR
0x6C
Separator key
VK_SUBTRACT
0x6D
Subtract key
VK_DECIMAL
0x6E
Decimal key
VK_DIVIDE
0x6F
Divide key
VK_F1
0x70
F1 key
VK_F2
0x71
F2 key
VK_F3
0x72
F3 key
VK_F4
0x73
F4 key
VK_F5
0x74
F5 key
VK_F6
0x75
F6 key
VK_F7
0x76
F7 key
VK_F8
0x77
F8 key
VK_F9
0x78
F9 key
VK_F10
0x79
F10 key
VK_F11
0x7A
F11 key
VK_F12
0x7B
F12 key
VK_F13
0x7C
F13 key
VK_F14
0x7D
F14 key
VK_F15
0x7E
F15 key
VK_F16
0x7F
F16 key
VK_F17
0x80
F17 key
VK_F18
0x81
F18 key
VK_F19
0x82
F19 key
VK_F20
0x83
F20 key
VK_F21
0x84
F21 key
VK_F22
0x85
F22 key
VK_F23
0x86
F23 key
VK_F24
0x87
F24 key
-
0x88-8F
Unassigned
VK_NUMLOCK
0x90
NUM LOCK key
VK_SCROLL
0x91
SCROLL LOCK key
0x92-96OEM specific
-
0x97-9F
Unassigned
VK_LSHIFT
0xA0
Left SHIFT key
VK_RSHIFT
0xA1
Right SHIFT key
VK_LCONTROL
0xA2
Left CONTROL key
VK_RCONTROL
0xA3
Right CONTROL key
VK_LMENU
0xA4
Left MENU key
VK_RMENU
0xA5
Right MENU key
VK_BROWSER_BACK
0xA6
Browser Back key
VK_BROWSER_FORWARD
0xA7
Browser Forward key
VK_BROWSER_REFRESH
0xA8
Browser Refresh key
VK_BROWSER_STOP
0xA9
Browser Stop key
VK_BROWSER_SEARCH
0xAA
Browser Search key
VK_BROWSER_FAVORITES
0xAB
Browser Favorites key
VK_BROWSER_HOME
0xAC
Browser Start and Home key
VK_VOLUME_MUTE
0xAD
Volume Mute key
VK_VOLUME_DOWN
0xAE
Volume Down key
VK_VOLUME_UP
0xAF
Volume Up key
VK_MEDIA_NEXT_TRACK
0xB0
Next Track key
VK_MEDIA_PREV_TRACK
0xB1
Previous Track key
VK_MEDIA_STOP
0xB2
Stop Media key
VK_MEDIA_PLAY_PAUSE
0xB3
Play/Pause Media key
VK_LAUNCH_MAIL
0xB4
Start Mail key
VK_LAUNCH_MEDIA_SELECT
0xB5
Select Media key
VK_LAUNCH_APP1
0xB6
Start Application 1 key
VK_LAUNCH_APP2
0xB7
Start Application 2 key
-
0xB8-B9
Reserved
VK_OEM_1
0xBA
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the ';:' key
VK_OEM_PLUS
0xBB
For any country/region, the '+' key
VK_OEM_COMMA
0xBC
For any country/region, the ',' key
VK_OEM_MINUS
0xBD
For any country/region, the '-' key
VK_OEM_PERIOD
0xBE
For any country/region, the '.' key
VK_OEM_2
0xBF
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '/?' key
VK_OEM_3
0xC0
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '`~' key
-
0xC1-D7
Reserved
-
0xD8-DA
Unassigned
VK_OEM_4
0xDB
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '[{' key
VK_OEM_5
0xDC
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '\|' key
VK_OEM_6
0xDD
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the ']}' key
VK_OEM_7
0xDE
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the 'single-quote/double-quote' key
VK_OEM_8
0xDF
Used for miscellaneous characters; it can vary by keyboard.
-
0xE0
Reserved
0xE1OEM specific
VK_OEM_102
0xE2
Either the angle bracket key or the backslash key on the RT 102-key keyboard
0xE3-E4OEM specific
VK_PROCESSKEY
0xE5
IME PROCESS key
0xE6OEM specific
VK_PACKET
0xE7
Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in
-
0xE8
Unassigned
0xE9-F5OEM specific
VK_ATTN
0xF6
Attn key
VK_CRSEL
0xF7
CrSel key
VK_EXSEL
0xF8
ExSel key
VK_EREOF
0xF9
Erase EOF key
VK_PLAY
0xFA
Play key
VK_ZOOM
0xFB
Zoom key
VK_NONAME
0xFC
Reserved
VK_PA1
0xFD
PA1 key
VK_OEM_CLEAR
0xFE
Clear key

作者: CrLf    时间: 2016-9-7 14:02

timeout 没有起作用,win7 x64
作者: aa77dd@163.com    时间: 2016-9-7 14:45

本帖最后由 aa77dd@163.com 于 2016-9-7 14:56 编辑

回复 2# CrLf

第一个参数会被看成是 timeout   即使是 x  或者 d  这样解析成数字就会失败, 从而在程序内部 t=0, 而造成无限等待, 直到有任意按键被按下

neoGetKey.exe d

neoGetKey.exe 0
等效, 将无限等待有键被按下, 并且不会显示返回值

要让 timeout 是 1 秒, 要么一个参数也没有, 要么 必须明确指定 1000

无任何参数
neoGetKey.exe

或者明确指定:
neoGetKey.exe 1000 d
或者
neoGetKey.exe 1000 x

我的运行结果示例,
注意 timeout 单位是 ms, 不是秒,  500 就是半秒

2   pressed key value is : 2             <-     点鼠标右键的信息

1   pressed key value is : 1             <-     点鼠标左键的信息
  1. 输入长度 = 8504
  2. 输出长度 = 6144
  3. CertUtil: -decode 命令成功完成。
  4. ff   time out
  5. ff   time out
  6. ff   time out
  7. ff   time out
  8. 2   pressed key value is : 2
  9. 2   pressed key value is : 2
  10. 2   pressed key value is : 2
  11. 2   pressed key value is : 2
  12. 2   pressed key value is : 2
  13. 2   pressed key value is : 2
  14. ff   time out
  15. ff   time out
  16. 1   pressed key value is : 1
  17. 1   pressed key value is : 1
  18. 1   pressed key value is : 1
  19. 1   pressed key value is : 1
  20. ff   time out
  21. ff   time out
  22. ff   time out
复制代码

作者: codegay    时间: 2016-9-7 15:01

:BEGIN:getKEY.B64
这个标签应该也是没有必要加的。

certutil 会忽略其它内容。
作者: aa77dd@163.com    时间: 2016-9-7 15:21

回复 4# codegay


试了一下, 直接把批处理文件给它去 decode, 还真是忽略了, 那么只要 不包含 多个 文件在里面, 就真没必要 生成新文件 再来 decode 了
作者: codegay    时间: 2016-9-7 15:25

回复 5# aa77dd@163.com


   我这篇是前几天写的: http://bbs.bathome.net/thread-41604-1-1.html
作者: 523066680    时间: 2016-9-7 15:28

-----BEGIN CERTIFICATE----- 里面好多连续的A 我猜可以再压缩一下。
作者: codegay    时间: 2016-9-7 15:48

回复 7# 523066680


    可是加壳工具容易报毒。
作者: 523066680    时间: 2016-9-7 15:55

回复 8# codegay


    就简单的字符处理一下  A{数量},用到的时候提取,扩展。
作者: CrLf    时间: 2016-9-7 18:39

回复 6# codegay


    难道没人好奇 certutil -downloadOcsp 怎么用吗?说不定又是黑科技
作者: happy886rr    时间: 2016-9-7 20:15

GetAsyncKeyState(x)比kbhit()强多了,只是觉得好像有点延迟,按键反应不是很快,360会拦住
作者: codegay    时间: 2016-9-7 20:43

回复 10# CrLf


    我这没这参数。
作者: CrLf    时间: 2016-9-7 21:49

回复 9# 523066680


    先 upx,再 encode,就不会有这么多重复字符了,杀毒引擎会认 upx 的吧
作者: codegay    时间: 2016-9-7 22:00

回复 13# CrLf


    按照几年前的印象。凡是加壳的程序都容易报提示。
作者: plp626    时间: 2016-10-4 22:08

回复 7# 523066680


    我猜是大量连续nul字符的base64编码;

你这话,让我又想起了文本可见范围的字符压缩,老帖子出题区。
作者: CrLf    时间: 2016-10-5 18:09

本帖最后由 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. }
复制代码

作者: aa77dd@163.com    时间: 2016-10-5 18:52

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

作者: plp626    时间: 2016-10-6 20:51

回复 16# CrLf

感谢分享;

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

还有个问题,你在替换重复串时,控制字符后面的数字,怎么和没有被压缩的原始数据的数字区分?
作者: aa77dd@163.com    时间: 2016-10-6 21:10

回复 16# CrLf

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

有点意思吧
作者: CrLf    时间: 2016-10-6 21:40

本帖最后由 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(@[^$@|]*)+@
作者: CrLf    时间: 2016-10-6 21:40

回复 19# aa77dd@163.com


    原来的映射表有歧义,我再调整下表达
作者: 523066680    时间: 2016-10-6 21:43

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

回复 19# aa77dd@163.com

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

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

回复 20# CrLf

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

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

卷积神经网络及其在图像处理中的应用
作者: CrLf    时间: 2016-10-7 01:48

本帖最后由 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%
作者: happy886rr    时间: 2016-10-7 10:09

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

本帖最后由 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
}
作者: happy886rr    时间: 2016-10-7 10:39

本帖最后由 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语言构思一下。
作者: aa77dd@163.com    时间: 2016-10-7 10:46

回复 26# happy886rr

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

问题是无论压缩还是解压缩, 一 代码的复杂度将增大很多, 二, 代码的执行效率上也会严重的降低
作者: happy886rr    时间: 2016-10-7 10:52

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

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

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

回复 28# happy886rr

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

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

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

信息压缩 是以时间来换取空间的, 在时间和空间的矛盾上, 需要权衡, 为了空间上的极限, 却要面对过度的时间牺牲的话, 不可取
作者: happy886rr    时间: 2016-10-7 11:08

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

回复 30# happy886rr

如果原始数据就是已经过高度压缩的, 我相信再经 BASE64 编码后也不会有大的压缩空间了, 换言之, 不会出现大量重复的 子串 (包括若干连续重复的 A 那种形式)
作者: aa77dd@163.com    时间: 2016-10-7 14:52

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

提供一个先压缩后 BASE64 编码的样本

BASE64 编码文件大小 3,428 字节, 其中是包括 100+ 个非编码字节(如 CR, LF 以及首尾两个注释行)

处理流程:

    C 源码在 Code::Blocks 以 Release 方式编译(其它各种编译设置均默认)
   
     -> neoGetKey.exe  (6,144 字节)

    Windows 原生压缩工具 makecab 压缩  (Windows 也提供了原生的解压工具 expand,   makecab 和 expand 都是 XP 就有的, 经 makecab 打的包, expand 能很好的支持)

    makecab neoGetKey.exe  neoGetKey.exe.cab  (2,450 字节)

    Windows 原生 BASE64 编码器 certutil 编码

    certutil -encode neoGetKey.exe.cab neoGetKey.exe.cab.B64  (3,428 字节)
  1. -----BEGIN CERTIFICATE-----
  2. TVNDRgAAAACSCQAAAAAAACwAAAAAAAAAAwEBAAEAAAAAAAAASgAAAAEAAQAAGAAA
  3. AAAAAAAAR0krdCAAbmVvR2V0S2V5LmV4ZQDuJZB/QAkAGENL7RhtbFPX9dp5DEMT
  4. bDFnS1loH5IDASXBgawKbdI5OI+kkFAnwWMbBMckL4m1xLbsZ0hWKGaO1by+Wss2
  5. pCGNSfXYD6YhjUooDR/tDJlm0oGWMqSFUbWgwfZSR1q2RZn5GG/n3GcnjlHXTaum
  6. IXGVk3u+7jnnnnPuvbYbvzFEcgghDICiEDJC1GEhnz6CAMuePbuMnF5yZdWIpuHK
  7. qh3dLj/r9Xm6fM5ett3pdnsEdi/P+gJu1uVma19uYXs9HXxZXt5SU8qGjSOkQbOI
  8. nKr5+8603ZtEn/OURltJcoEwAmgJYZfDbABgU9EZVD7GrUnFT0ebSpyEOYcyWFUX
  9. /xlUFUPmJmxgLeff2OxnPMoEvk+AecfSVEC5mZuY20pbWYdTcKbrwap7XrgBKouV
  10. +VTFaWSYU3rLH9GzlO31+xE/9S+KHER7LtUezY0tFZvxUb//+8w9GZ/lsIt3QlMF
  11. YmtSsuvKb4iBB5K2fFYi1d+F2u63Vkdg8u16F09YnDHpYCqPibUmRr4NeCipEXrC
  12. MWFdSqSMn1NgiBMSmGlNilOtFxlS/X0wIbxTfQSncwtlkX2kehHwAzJYeAqNz4oC
  13. GH8tZbwCjF9JiZTxRDTl5xyGI+4GxT1AhmeFQTkMbUqdJw6n9M+gkhpPA2hWgObk
  14. XlTIG8ocsP+W0JQp0pqEdcRgIfJ76HyKkTeAyTiXxCSNEIuFROwz4NMg5RHWQjAH
  15. 4g6TDmznwkIG5LIGFkYNgEHUXztuAC0p39QE5FV9WAIroXs3BZYq4GppJcqkbWYx
  16. 1yQPLyYp5dC9mPAlaSXVgh1KeVSrySYaTfIQaMmvoOpKtC4WyHvglIduT8tbkInB
  17. 6KR8jBVCY6IYlMiY5J9itkbl5aAjFprkezhjANSftNmAOl+eC2DSDkmCwkTOr5nr
  18. Dx1sEdOp5BeChnzpoaIMRU6vXiDXzstPZMqlvArgiXdalVsRYTXSxWk6lf/WyR9A
  19. qtP1GMHLTbyz86tQliqpVYfbexuaRG4GD3rAzBZSrsS5cRkWhe5r3k1CvJ0iN6Ef
  20. XqQF2SD3e/13/ojpvq999QtSY65Uo9MPk6q2wYuHcoIX2cH3E4x+uPF68G6f/kgs
  21. eLdDf+TikvETmsH3Atryq4P261Lr+OD7ce4aRi/Zx8M3QG2T/Zr+GFUTDtLuSxhS
  22. +7Mevv8QpkOVEet0KKnd92dM8f7P0RbqDMf6Pwr9SidOiH/57c0l8dDDL776m+DB
  23. 6yTgiPAzYnLXHkfraFgJHEylV34Z9qlw18Cr1DgObQOOG9OOA69h1ANjgYoReKYJ
  24. GKDLJXuutJnBEv4YFovc+CSDLX/AxES4CWS/AuzEEF2DVU9xeeBSXmIYA9IPfDO9
  25. yj6BrcaBfHIn8Oxnps1YroQxMkwz0sRImtAFnebbeP8fvotS38etoxnn6cYf5skh
  26. tT+iLJ4GXXhMWJ11/hQ4UFTYxERqmOOIhq8GJsdG5/sLGoGJWlbA2UgqwtpwTBwV
  27. Pi/OpvpTMf4IRdsCs5DENiN03+v/UJRduyAzebUgKI+FxxJLLZIxjBSYnkm8o+4k
  28. 8otM+yw9t4HnqCP1glmJPPRZRH3qh7B/H/W34tP8XVhw30S9Ftr+Uj2j3BJn7Wc3
  29. 035v0b8dC0114J0SsZ+AmxhOMBRKyZ+xWcjZZ9MXWmgqF6JcnNiiGdvatyx4YN2J
  30. msDMkl8D1f/X0AtVgcVwwbY+GBs9UwF1OfsxmoYbCq1CuE7gjQTN6v0jfw/O08hJ
  31. oM7dVnsjFy4cXeJ3qcTPn384ioenLmPt8zB2KKIu3X1x7mgNjKgBzEQCR+PcMSTj
  32. 3Js4idxI1AiCOPcTlXtC5Z6PFlDuSZV7SuXGooWUe1olfxllMVDuUtRE58vRYjqP
  33. R0vofA2uAjNgePLFCsjTNOSJ5pCBaoVroXX14Rc09NmqwrN1HLaLddQPfB24D8S4
  34. RJXO6EH4t5/FrcybT1vUHMetOm++hUQtsNl4Di6W8msRtxZjRkSrMWrG67elQMqv
  35. QMRaGLVhUVvYuNVMXxxriZRfBaJoJVWspAUUrRXirDix6hI8bU/HTKxmjKkZHFhX
  36. Dwu29v+J5lAMdwNFsyaGexAtoKgX0UKKCojS3IT7EKXpCR9AVM1QMJWhgfkMDUbC
  37. 6IX2k0zzlMQ8KYHN5VehRZ/BO8sPW59LJEghl7IDWlscFVdi2SNW5ngbnXXHgzin
  38. WkBMypWgtmlCvBd4K/GWvE0zd5fjaBJvwW1RjR9ZfYbDkziHlpBSnBOTay8ALt4U
  39. L0s6ycIoN9P3RYHEGaEhDRJnwL6UuFyYdBKnw8aN0mcyZsFrDK/eTPpDrPQYyYhA
  40. KWJAPDSU/ryjFBVm0WwWbcyibVl0QRZdkkUbsuiGLLoyi67NouuzaHMWXZVFW7Lo
  41. 3Vl00raQnsqiZ7Lo6SxaXkDT97oO3tx0fmGYV6hfJBB/8on68RqP1CzrO6FtheUT
  42. 1zyp9+M/irLo0oaXNtdZrTs3bijl6ks3lLZsbdhaWrejvrm08aXtdcAGnf0bNzj8
  43. 3U4f3+EVfKUv+l3f4tnqahZnT2cx6Di4ekdLfU0zV7uWFPmfLwo8z3Y6XT18B+v0
  44. +3mf4PK42bYi/5qlhJSVrYe/rvZ2Cu0ed6era71rY+Vz68FLqeqlFNyUtRNSxws1
  45. gqd3u7OXr2GLnYCWsP6StF//2rXsqmrW/KSm/8nots3jsWZ4PYEeyOBdAx7TBA9q
  46. Bs/UQogBeB9k8CqAt7vpk/10gMwLEAR4A+BYhu75DPwS4BMAMkASIBf8FwCwACUA
  47. lQAWgAaAHQBtAD0AAkAQ4I3meVtHm/8//GtITUcHdm4NIT8kXJ9LsPk87Tz9Ie7n
  48. ZIvLnRJ+sKDDCflI28ILdne3090BZ4fra+e9eHS2uHoE3gdr64nD38PzXvSxhjgc
  49. XbzQ63S5nb4uP6kC2utw8O59Lp/HTciLKt2Jv7+qP3s6HH5ecDi9XofQ76W8fuJo
  50. 5yE6xCeJw+XZS8gejcPjTjEHNLhEtZCvde71+ARSqHUK6TXPAO5xEWLWdnb2BPzd
  51. yNuk7fT6XG6hE/CvaDt9PKz1aXudPT2edpQf0s6JyZDW7+pyO3sQ/5Dmwt/vbt/G
  52. 97cI4CT1O2QWbOOat3MNGzeUdfTQdUbg9fr3tfsElVNs++8h014V0PYWrnne4+M9
  53. /gk=
  54. -----END CERTIFICATE-----
复制代码
C 源码
  1. #include <Windows.h>
  2. #include <stdio.h>
  3. int main(int argc, char** argv) {
  4.     int i, t = 1000, r = 0, kshift = -8;
  5.     char show[3] = "%\0\0";
  6.     if (argc >= 2) t = atoi(argv[1]);
  7.     if (argc >= 3)
  8.         show[1] = (**(argv + 2) >= 'a') ? **(argv + 2) : **(argv + 2) + 'a' - 'A';
  9.     show[1] = ( show[1] == 'x' || show[1] == 'd') ? show[1] : '\0';
  10.     for (i = 0; t == 0 || i < t; i++) {
  11.         int x;
  12.         for (x = 1; x <= 0xFE; x++) {
  13.             if (x == VK_SHIFT || x == VK_CONTROL || x == VK_MENU)
  14.                 continue;
  15.             if (GetAsyncKeyState(x) & 0x8000) {
  16.                 r |= x << (kshift += 8);
  17.                 if (kshift >= 24) {
  18.                     if (show[1]) printf(show, r);
  19.                     return r;
  20.                 }
  21.             }
  22.         }
  23.         if (r != 0) {
  24.             if (show[1]) printf(show, r);
  25.             return r;
  26.         }
  27.         sleep(1);
  28.     }
  29.     if (show[1]) printf(show, 0xFF);
  30.     return 0xFF;
  31. }
复制代码

作者: plp626    时间: 2016-10-7 16:09

回复 31# aa77dd@163.com

原始数据的熵(信息量)经过base64编码后,熵不会变
理论上极限压缩体积 base64字符集是rar这种通用压缩工具选择的扩展ascii字符集的4/3 (64^x = 256^y => x/y=log(256)/log(64))
作者: happy886rr    时间: 2016-10-7 16:29

回复 23# CrLf
那个js对单纯的A压缩的不够好,还是你的那条数据,例如 576 字节长的编码js版压缩为345 字节,但我用批能压缩到243字节,远超rar和7z
Base64压缩机
  1. @echo off
  2. REM 原始数据
  3. set "LINE=TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAEFAJOHz1cAAAAAAAAAAOAADwMLAQI4AAwAAAAUAAAAAgAAIBIAAAAQAAAAIAAAAABAAAAQAAAAAgAABAAAAAEAAAAEAAAAAAAAAABgAAAABAAAUV0AAAMAAAAAACAAABAAAAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAAABQAABAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC50ZXh0AAAAFAoAAAAQAAAADAAAAAQAAAAAAAAAAAAAAAAAAGAAAGAuZGF0YQAAAEAAAAAAIAAA"
  4. REM 压缩数据
  5. setlocal enabledelayedexpansion
  6. for /l %%i in (1,1,10000) do (
  7. if "!LINE:~0,1!"=="A" (
  8. set/a i+=1
  9. ) else (
  10. if !i! neq 0 (
  11. set M=512
  12. for %%Z in (@,-,#,$,_,},{,],[,A) do (
  13.     if !i! geq !M! (
  14. set "S=!S!%%Z"
  15. set/a "i-=M"
  16. )
  17. set/a "M>>=1"
  18. )
  19. )
  20. if "!LINE!"=="" (echo !S!>压缩.txt&exit) else (set "S=!S!!LINE:~0,1!")
  21. )
  22. set "LINE=!LINE:~1!"
  23. )
复制代码
Base64解压机
  1. REM 解压数据
  2. set/p LINE=<压缩.txt
  3. setlocal enabledelayedexpansion
  4. set "Z=A"&(for %%Z in ([,],{,},_,$,#,-,@) do (set "Z=!Z!!Z!"&for %%S in (!Z!) do (set "LINE=!LINE:%%Z=%%S!")))&echo !LINE!>解压.txt
复制代码

作者: happy886rr    时间: 2016-10-7 16:39

回复 33# plp626
base64会增加一些数据,用6位来表示一个字节,也就是6x=8y。故信息量比为x/y=8/6=4/3,也就是体积涨到133%,所以只能从转码前压缩入手。
作者: codegay    时间: 2016-10-7 16:55

回复 35# happy886rr


    要不要用批处理实现一个 base92
作者: aa77dd@163.com    时间: 2016-10-7 16:56

回复 33# plp626

BASE64 取 64 个字符, 而不取 其它数字:

1. ASCII 码值 0x80 ~ 0xFF 最高位都是 1, 将与多字节编码冲突 (比如汉字编码), 所以这个范围内的字符都不好用, 最好不用

2. 0x0 ~ 0x7F 共 128 个字符 有好几十个是控制字符, 所以 128 (= 2 ^ 7) 字符也不成

3. 好吧, 2 的幂 比 128 小的 又最大的就是 64 (= 2 ^ 6),  也能找到 64 个 不关控制字符事的可打印字符, 64 就能定了.

4. 64 = 2 ^ 6, 也就是只有 6 个二进位的信息容量, 而任何字符都是要占 8 位的, 也就是信息位利用率只有 6/8 = 3/4,  倒过来, 我们就必须最少要用 4/3 的体积才能编码原始的数据

6 位 X 4 字节 = 8 位 X 3 字节,  整整好, 实现最大化利用, 位数不多不少, 编码解码也方便


BASE64 编码增长率 4/3 - 1 = 33%


而 Ascii85 和 basE91 利用更多的字符来编码, 但因为字符总数 在 2^6 ~ 2^7 之间, 编码解码就没有 2^6=64 个字符的便利了, 程序自然就复杂了.

Ascii85 可以将编码增长率降到 25%
https://en.wikipedia.org/wiki/Ascii85


basE91 encoding 可以将编码增长率降到 23%
http://base91.sourceforge.net/
作者: happy886rr    时间: 2016-10-7 17:10

回复 36# codegay
批处理局限性太大,我采取的是用C语言来实现压缩,压缩好的数据用批处理解压,再用那个证书管理certutil变成二进制文件。
压缩费时费力,但解压批处理就能胜任。str=!str:*=*!,效率是很高的。
作者: CrLf    时间: 2016-10-7 18:16

回复 34# happy886rr


    Nice

我发现自己那个算法压缩的结果有问题,无法解码,回头检查下是什么毛病
作者: happy886rr    时间: 2016-10-7 19:44

回复 39# CrLf
大师,如果只用可打印字符来压缩的话,压缩比始终上不去。即便再添加新的符号,都不可能比base64划算。只能去寻找重复的节点。
作者: 523066680    时间: 2016-10-7 20:19

本帖最后由 523066680 于 2016-10-7 20:31 编辑

回复 40# happy886rr


假设有一个非常mini的函数,它所生成的某一段数据,刚好和这一段数据相同。
然后只要直接计算那一段出来就可以了。(我就是瞎扯扯)
这个图像看起来和原不等式一样的不等式是怎么发现的?
作者: happy886rr    时间: 2016-10-7 21:07

回复 41# 523066680
哈哈,原来是mod原理,数学无处不在。
作者: happy886rr    时间: 2016-10-7 21:49

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

回复 39# CrLf
大师,比如如下的数据:
  1. TVqQAAMAAAAEQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAAQAAMAAAA
复制代码
分别用@,-,#,$,_,},{,],[,.表示512个A、256个A、128个A、、、、、1个A,则化为:
  1. TVqQ[M]EQ[M]Q[M]Q[M]Q[M]Q[M]Q[M]Q[M]Q[M]Q[M]Q[M]Q[M]Q[M]
复制代码
然后继续迭代 用@,-,#,$,_,},{,],[,.表示512个、256个、128个、、、、、1个Q[M]则化为:
  1. TVq.E{]
复制代码
用:冒号表示标签切换。化为可解码的格式
  1. TVq.E{]:Q[M]:A
复制代码
如此就实现了用14个字符去表示108个字符的base64字符串。我发现没有任何算法有这个压缩率高。
我正在思考如何用批处理实现,当然用C实现起来会更容易,但是那样就得带个exe。

当然也许有可能产生歧义,不过只要加上层号即可。
如对字串AAAAAAAAAAAAAAAAAAEFAAABAAACAAADAAAEFAAAGAAAHHAAAAI压缩为
  1. }[EF.B.C.D.EF.G.HH]I:[.;1:A
复制代码
其中:[.;1中:[.表示要替换为的标签,分号;1表示只替换一级权签,也就是只替换.,之后的:A表示在上次替换完后再次替换所有权签为A。
基本可以实现可见字符内的最大压缩化。
作者: aa77dd@163.com    时间: 2016-10-8 14:11

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

happy886rr  的二进制权值去 0 表达法


对给定整数范围 [1,63335] (16位二进制能表达的所有正整数),
如果用 16 进制表达这全部 65535 个数,
编码后不要最高位的 0, 比如:        001F 就是 31(十进制), 我们只取 1F 这两个字符,
但编码中间出现 0 仍保留, 比如:  10B 是 267(十进制), 这里中间的 0 仍保留

以此方式将 [1,63335] 范围内所有的整数全部编码, 然后把所有编码全排在一起, 总长将达到

257775 = 16/4 * (2^16 - 2^12) + 12/4 * (2^12 - 2^8) +  8/4 * (2^8 - 2^4) + 4/4*(2^4 - 2^0)


如果我们同样也只用 16 个字符来对此范围内整数编码, 但这 16 个字符全部取 2 的幂的意义:

为免混淆, 我们全部用字母:

ABCDEFGHIJKLNMOP

上面 16 个字母分别表示 2^0, 2^1, 2^2, 2^3, 2^4, ... 2^14, 2^15, 这些 2 的幂

对一个整数编码时, 我们只把这个整数的二进制形式里的所有的 1 提出, 转换成对应权值的字母, 如下:

9   转二进制 -> 1001        -> 2^3 + 2^0 -> DA

359 转二进制 -> 1 0110 0111 -> 2^8 + 2^6 + 2^5 + 2^2 + 2^1 + 2^0 -> IGFCBA

以此方式将 [1,63335] 范围内所有的整数全部编码, 然后把所有编码全排在一起, 总长将达到

65535 = 2^16 - 1 =
C[16, 1] + C[16, 2] + C[16, 3] + C[16, 4] + C[16, 5] + C[16, 6] + C[16, 7] + C[16, 8]
+ C[16, 9] + C[16, 10] + C[16, 11] + C[16, 12] + C[16, 13] + C[16, 14] + C[16, 15] + C[16, 16]

C[m, n] 是组合数, 比如 C[5, 2] = 5*4 / (2*1) = 10


65535 大概只有 257775 的 1/4, 这种编码方式比普通 16 进制编码在空间上节省很多, 关键在于权值舍 0 的方式
  1. @echo off & setlocal enableDelayedExpansion
  2. >AllHexCode.txt (
  3. for %%a in (0 1 2 3 4 5 6 7 8 9 A B C D E F) do ^
  4. for %%b in (0 1 2 3 4 5 6 7 8 9 A B C D E F) do ^
  5. for %%c in (0 1 2 3 4 5 6 7 8 9 A B C D E F) do ^
  6. for %%d in (0 1 2 3 4 5 6 7 8 9 A B C D E F) do (
  7.     set "HEX=##%%a%%b%%c%%d"
  8.     set "HEX=!HEX:#0000=!"
  9.     set "HEX=!HEX:#000=!"
  10.     set "HEX=!HEX:#00=!"
  11.     set "HEX=!HEX:#0=!"
  12.     set "HEX=!HEX:#=!"
  13.     title !HEX! / FFFF
  14.     <nul set /p "=!HEX!"
  15. )
  16. )
  17. for %%a in (AllHexCode.txt) do echo;[1,63335]范围内所有整数HEX编码总长:%%~za
  18. pause
  19. exit /b
复制代码





欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2