[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]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. TVNDRgAAAACSCQAAAAAAACwAAAAAAAAAAwEBAAEAAAAAAAAASgAAAAEAAQAAGAAAAAAAAAAAR0krdCAAbmVvR2V0S2V5LmV4ZQDuJZB/QAkAGENL7RhtbFPX9dp5DEMTbDFnS1loH5IDASXBgawKbdI5OI+kkFAnwWMbBMckL4m1xLbsZ0hWKGaO1by+Wss2pCGNSfXYD6YhjUooDR/tDJlm0oGWMqSFUbWgwfZSR1q2RZn5GG/n3GcnjlHXTaumIXGVk3u+7jnnnnPuvbYbvzFEcgghDICiEDJC1GEhnz6CAMuePbuMnF5yZdWIpuHKqh3dLj/r9Xm6fM5ett3pdnsEdi/P+gJu1uVma19uYXs9HXxZXt5SU8qGjSOkQbOInKr5+8603ZtEn/OURltJcoEwAmgJYZfDbABgU9EZVD7GrUnFT0ebSpyEOYcyWFUX/xlUFUPmJmxgLeff2OxnPMoEvk+AecfSVEC5mZuY20pbWYdTcKbrwap7XrgBKouV+VTFaWSYU3rLH9GzlO31+xE/9S+KHER7LtUezY0tFZvxUb//+8w9GZ/lsIt3QlMFYmtSsuvKb4iBB5K2fFYi1d+F2u63Vkdg8u16F09YnDHpYCqPibUmRr4NeCipEXrCMWFdSqSMn1NgiBMSmGlNilOtFxlS/X0wIbxTfQSncwtlkX2kehHwAzJYeAqNz4oCGH8tZbwCjF9JiZTxRDTl5xyGI+4GxT1AhmeFQTkMbUqdJw6n9M+gkhpPA2hWgObkXlTIG8ocsP+W0JQp0pqEdcRgIfJ76HyKkTeAyTiXxCSNEIuFROwz4NMg5RHWQjAH4g6TDmznwkIG5LIGFkYNgEHUXztuAC0p39QE5FV9WAIroXs3BZYq4GppJcqkbWYx1yQPLyYp5dC9mPAlaSXVgh1KeVSrySYaTfIQaMmvoOpKtC4WyHvglIduT8tbkInB6KR8jBVCY6IYlMiY5J9itkbl5aAjFprkezhjANSftNmAOl+eC2DSDkmCwkTOr5nrDx1sEdOp5BeChnzpoaIMRU6vXiDXzstPZMqlvArgiXdalVsRYTXSxWk6lf/WyR9AqtP1GMHLTbyz86tQliqpVYfbexuaRG4GD3rAzBZSrsS5cRkWhe5r3k1CvJ0iN6EfXqQF2SD3e/13/ojpvq999QtSY65Uo9MPk6q2wYuHcoIX2cH3E4x+uPF68G6f/kgseLdDf+TikvETmsH3Atryq4P261Lr+OD7ce4aRi/Zx8M3QG2T/Zr+GFUTDtLuSxhS+7Mevv8QpkOVEet0KKnd92dM8f7P0RbqDMf6Pwr9SidOiH/57c0l8dDDL776m+DB6yTgiPAzYnLXHkfraFgJHEylV34Z9qlw18Cr1DgObQOOG9OOA69h1ANjgYoReKYJGKDLJXuutJnBEv4YFovc+CSDLX/AxES4CWS/AuzEEF2DVU9xeeBSXmIYA9IPfDO9yj6BrcaBfHIn8Oxnps1YroQxMkwz0sRImtAFnebbeP8fvotS38etoxnn6cYf5skhtT+iLJ4GXXhMWJ11/hQ4UFTYxERqmOOIhq8GJsdG5/sLGoGJWlbA2UgqwtpwTBwVPi/OpvpTMf4IRdsCs5DENiN03+v/UJRduyAzebUgKI+FxxJLLZIxjBSYnkm8o+4k8otM+yw9t4HnqCP1glmJPPRZRH3qh7B/H/W34tP8XVhw30S9Ftr+Uj2j3BJn7Wc3035v0b8dC0114J0SsZ+AmxhOMBRKyZ+xWcjZZ9MXWmgqF6JcnNiiGdvatyx4YN2JmsDMkl8D1f/X0AtVgcVwwbY+GBs9UwF1OfsxmoYbCq1CuE7gjQTN6v0jfw/O08hJoM7dVnsjFy4cXeJ3qcTPn384ioenLmPt8zB2KKIu3X1x7mgNjKgBzEQCR+PcMSTj3Js4idxI1AiCOPcTlXtC5Z6PFlDuSZV7SuXGooWUe1olfxllMVDuUtRE58vRYjqPR0vofA2uAjNgePLFCsjTNOSJ5pCBaoVroXX14Rc09NmqwrN1HLaLddQPfB24D8S4RJXO6EH4t5/FrcybT1vUHMetOm++hUQtsNl4Di6W8msRtxZjRkSrMWrG67elQMqvQMRaGLVhUVvYuNVMXxxriZRfBaJoJVWspAUUrRXirDix6hI8bU/HTKxmjKkZHFhXDwu29v+J5lAMdwNFsyaGexAtoKgX0UKKCojS3IT7EKXpCR9AVM1QMJWhgfkMDUbC6IX2k0zzlMQ8KYHN5VehRZ/BO8sPW59LJEghl7IDWlscFVdi2SNW5ngbnXXHgzinWkBMypWgtmlCvBd4K/GWvE0zd5fjaBJvwW1RjR9ZfYbDkziHlpBSnBOTay8ALt4UL0s6ycIoN9P3RYHEGaEhDRJnwL6UuFyYdBKnw8aN0mcyZsFrDK/eTPpDrPQYyYhAKWJAPDSU/ryjFBVm0WwWbcyibVl0QRZdkkUbsuiGLLoyi67NouuzaHMWXZVFW7Lo3Vl00raQnsqiZ7Lo6SxaXkDT97oO3tx0fmGYV6hfJBB/8on68RqP1CzrO6FtheUT1zyp9+M/irLo0oaXNtdZrTs3bijl6ks3lLZsbdhaWrejvrm08aXtdcAGnf0bNzj83U4f3+EVfKUv+l3f4tnqahZnT2cx6Di4ekdLfU0zV7uWFPmfLwo8z3Y6XT18B+v0+3mf4PK42bYi/5qlhJSVrYe/rvZ2Cu0ed6era71rY+Vz68FLqeqlFNyUtRNSxws1gqd3u7OXr2GLnYCWsP6StF//2rXsqmrW/KSm/8nots3jsWZ4PYEeyOBdAx7TBA9qBs/UQogBeB9k8CqAt7vpk/10gMwLEAR4A+BYhu75DPwS4BMAMkASIBf8FwCwACUAlQAWgAaAHQBtAD0AAkAQ4I3meVtHm/8//GtITUcHdm4NIT8kXJ9LsPk87Tz9Ie7nZIvLnRJ+sKDDCflI28ILdne3090BZ4fra+e9eHS2uHoE3gdr64nD38PzXvSxhjgcXbzQ63S5nb4uP6kC2utw8O59Lp/HTciLKt2Jv7+qP3s6HH5ecDi9XofQ76W8fuJo5yE6xCeJw+XZS8gejcPjTjEHNLhEtZCvde71+ARSqHUK6TXPAO5xEWLWdnb2BPzdyNuk7fT6XG6hE/CvaDt9PKz1aXudPT2edpQf0s6JyZDW7+pyO3sQ/5Dmwt/vbt/G97cI4CT1O2QWbOOat3MNGzeUdfTQdUbg9fr3tfsElVNs++8h014V0PYWrnne4+M9/gk=
  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-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
复制代码

TOP

回复 4# codegay


试了一下, 直接把批处理文件给它去 decode, 还真是忽略了, 那么只要 不包含 多个 文件在里面, 就真没必要 生成新文件 再来 decode 了

TOP

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

TOP

回复 16# CrLf

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

有点意思吧

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

回复 26# happy886rr

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

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

TOP

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

回复 28# happy886rr

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

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

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

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

TOP

回复 30# happy886rr

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

评分人数

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

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

本帖最后由 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

返回列表