java.awt.Robot类
Java提供java.awt.Robot类来模拟操作键盘和鼠标, 下面是一个简单的demo
public static void keyPressByInt(Robot r,int key, int time){
r.keyPress(key);
r.keyRelease(key);
if (time > 0) {
r.delay(time);
}
}
public static void main(String[] args) throws AWTException, CharacterCodingException {
Robot robot = new Robot();
keyPressByInt(robot, KeyEvent.VK_H, 5);
keyPressByInt(robot, KeyEvent.VK_E, 5);
keyPressByInt(robot, KeyEvent.VK_L, 5);
keyPressByInt(robot, KeyEvent.VK_L, 5);
keyPressByInt(robot, KeyEvent.VK_O, 5);
}
执行以上逻辑就会输出字符串 hello, 当然Robot功能不止这些, 示例极其简单, 因为该篇文章目的不是为了说 java.awt.Robot 类的使用
使用Alt码输出汉字
尝试 Alt + 数字 输出汉字
Alt码(Alt code)即在IBM兼容个人电脑上,许多字符没有直接对应的按键,此时就可通过Alt-数字键盘输入法(Alt码)输入,方法是按住Alt键再通过数字键区输入字符代码。DOS、Microsoft Windows等许多操作系统也有类似或增强的功能。
启动你的 windows, 打开 记事本, 之后按住 Alt 不放, 同时依次点击 数字键盘 中的 1、2、3、4、5、6, 再松开 Alt, 看下能不能打印出汉字 釦 来.
注意事项:
Alt + 数字 是 windows 中的方法, 不知道其它系统支不支持, 有兴趣的话可以试一下.
最好是记事本, 当然也可以是其它简单的编辑器, 甚至任何能够输出字符的文本框, 但是不能是vscode等集成编译器, 因为这些编译器, 会将 Alt + 数字 映射成其它功能, 例如在vscode中, alt + ? 是光标移至尾行, alt + 4 是切换到左边的标签页.
一定要是 数字键盘 上面的 数字按键, 别搞错了.
如果记事本上成功输出了 釦 说明你的电脑是支持 Alt + 数字 形式的输入方法的.
Alt 后面数字代表的意思
首先先说明我们中国大多数电脑默认编码都是GBK, 底层区位码使用的大多都是《国家标准信息交换用的字符编码GB2312-80》(以下简称国标区位码).
注意: 网上很多文章说 Alt+【Unicode编码】对应的十进制数字即可打出该【Unicode编码】对应的字符, 事实上这个是机内码, 不是 Unicode编码
Alt 后面的数字如果在(0-255), 则输出的是数字对应的 ASCII 代码表中对应的字符.
Alt 后面的数字如果大于(255), 则查询的是国标区位码里的字符了,包括我们常用的个汉字也在里面.
如果 Alt 后面的数字 >= 65536, 则会先将数字除以65536, 得到余数, 打印出余数数字对应的国标区位码中的字符.
Alt + 123456 输出汉字 釦 的执行过程:
将 123456 转为16进制 1E240, 取后四位E240到国标区位码中查到汉字 釦输出.
用人话来说就是, 首先因为 123456 >= 65536, 那么对 123456➗65536=1……57920, 取得 57920 后到国标区位码中查到汉字 釦输出.
alt + 188992(2E240H), alt + 57920(E240H), 同样能输出汉字釦
使用java获取一个符号的区位码
java 中的字符默认是Unicode标准中utf-16编码, 标准的utf-16占用二或四个字节, java中的一个char占2个字节, 因此java中一个utf-16字占1或2个char, (例如大多数汉字, 字符都是一个char, 像😀等utf-16中排序较后的占两个char)
想要获取符号的国标区位码, 首先这个符号得先有国标区位码才行, 类似于😀🆒等符号使用两个char表示的符号, 就别想有国标区位码了.
例如一个😀, 在java中就是用两个char表示的, 这两个char单独一个无法表示一个字符, 它们是Unicode中的补充字符单元, java 中判断一个符号是否是补充字符单元的方法是
public final class Character implements java.io.Serializable, Comparable {
public static boolean isSurrogate(char ch) {
return ch >= MIN_SURROGATE && ch < (MAX_SURROGATE + 1);
}
}
假如一个符号有国标区位码, 那么在java里你需要先把编码由 utf-16 转换成 GB2312-80 才行.
我们直接转换成GBK就行了, 直接使用 String.getByte(string str, "GBK")
转换之后的两个byte就是符号的国标区位码了, 但要想转成10进制, 还需要小小的转换.
Byte.toUnsignedInt(array[0]) << 8 | Byte.toUnsignedInt(array[1])
使用java Robot利用键盘输出String的完整代码如下
public class MainTest {
/**
* 使用 Robot 利用键盘 alt 码输出字符
* @param r Robot 对象
* @param gbkCode 待打印的字符的国标区位码
* @param time 每个字符等待的时间
*/
public static void keyPressWithAltCode(Robot r, int gbkCode, int time){
r.keyPress(KeyEvent.VK_ALT);
String s = Integer.toString(gbkCode);
for (char c : s.toCharArray()) {
// 由 ASCII 码 0(48) 转为 VK_NUMPAD0(0x60)
int k = c + 48;
r.keyPress(k);
r.keyRelease(k);
}
r.keyRelease(KeyEvent.VK_ALT);
if (time > 0) {
r.delay(time);
}
}
/**
* 使用 Robot 利用键盘 alt 码输出字符
* @param r Robot 对象
* @param string 待打印的字符
* @param time 每个字符等待的时间
*/
public static void keyPressWithAltCode(Robot r, String string, int time) throws CharacterCodingException {
CharsetEncoder ce = Charset.forName("GBK").newEncoder();
for (char c : string.toCharArray()) {
if (Character.isSurrogate(c)) {
// 跳过补充字符
continue;
}
if (c >>> 8 == 0) {
keyPressWithAltCode(r, c, time);
continue;
}
CharBuffer cb = CharBuffer.wrap(new char[]{c});
final byte[] array = ce.encode(cb).array();
assert array.length == 2;
int code = Byte.toUnsignedInt(array[0]) << 8 | Byte.toUnsignedInt(array[1]);
keyPressWithAltCode(r, code, time);
}
}
public static void main(String[] args) throws AWTException, CharacterCodingException {
// 每隔5毫秒输出一个字符
keyPressWithAltCode(new Robot(), "1a键舣ß→_😀🆒", 5);
}
}
运行上面的代码就能利用键盘输出 1a键舣ß→_.