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

[系统增强] 按键获取工具 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
2

评分人数

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

TOP

本帖最后由 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。
基本可以实现可见字符内的最大压缩化。
2

评分人数

TOP

回复 41# 523066680
哈哈,原来是mod原理,数学无处不在。

TOP

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

回复 40# happy886rr


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

TOP

回复 39# CrLf
大师,如果只用可打印字符来压缩的话,压缩比始终上不去。即便再添加新的符号,都不可能比base64划算。只能去寻找重复的节点。

TOP

回复 34# happy886rr


    Nice

我发现自己那个算法压缩的结果有问题,无法解码,回头检查下是什么毛病

TOP

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

TOP

回复 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/

TOP

回复 35# happy886rr


    要不要用批处理实现一个 base92
去学去写去用才有进步。安装python3代码存为xx.py 双击运行或右键用IDLE打开按F5运行

TOP

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

TOP

回复 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
复制代码

TOP

回复 31# aa77dd@163.com

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

TOP

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

TOP

回复 30# happy886rr

如果原始数据就是已经过高度压缩的, 我相信再经 BASE64 编码后也不会有大的压缩空间了, 换言之, 不会出现大量重复的 子串 (包括若干连续重复的 A 那种形式)
1

评分人数

TOP

返回列表