如何在Clojure中实时读取Linux下/dev/input/js0的游戏控制器数据?
解决Clojure实时读取游戏控制器事件的问题
你的代码出现批量输出的核心原因是输出流缓冲:Clojure的print默认使用缓冲机制,不会立即将内容刷到控制台,只有当缓冲区满或者遇到换行时才会输出。另外,直接逐个读取字节也不符合游戏手柄事件的结构(/dev/input/js0的每个事件是固定8字节的二进制数据)。
修复方案
以下代码会解决缓冲问题,同时正确读取完整的手柄事件并实时输出:
(with-open [is (clojure.java.io/input-stream "/dev/input/js0")] (let [buffer (byte-array 8)] ; 每个js事件固定8字节 (loop [] (.read is buffer) ; 一次性读取完整事件 (println (vec buffer)) ; 将字节数组转为向量方便查看 (.flush *out*) ; 强制刷新输出流,确保实时显示 (recur))))
关键改进点
- 使用8字节数组一次性读取完整的游戏手柄事件,符合
/dev/input/js0的设备数据格式(每个事件包含时间戳、事件类型、按键/轴编号、数值)。 - 每次输出后调用
.flush *out*,强制清空输出缓冲区,让内容立即显示在控制台。 - 用
println替代print,既添加换行让输出更易读,也能辅助触发缓冲刷新(不过核心还是手动调用.flush)。
贴近cat命令的原始输出版本
如果需要完全模仿cat /dev/input/js0的原始字节输出效果,可以直接将字节写入标准输出流,避免字符串转换的缓冲:
(with-open [is (clojure.java.io/input-stream "/dev/input/js0") os (clojure.java.io/output-stream System/out)] (let [buffer (byte-array 1024)] (loop [] (let [read-bytes (.read is buffer)] (when (> read-bytes 0) (.write os buffer 0 read-bytes) (.flush os) (recur))))))
这个版本直接将读取到的字节写入标准输出,实时性和输出效果和cat /dev/input/js0完全一致。
内容的提问来源于stack exchange,提问作者epalma
相关产品推荐
相关产品推荐

