ReadStream 跳过字节?
ReadStream skipping bytes?
我正在使用 node.js
为 Linux 编写键盘事件解析器。它工作得有点好,但有时节点似乎跳过了几个字节。我正在使用 ReadStream
来获取数据,处理它,处理它,并最终在遇到分隔符时输出它(在我的例子中,\n
)。
这是我的 class 处理读取数据的部分:
// This method is called through this callback:
// this.readStream = fs.createReadStream(this.path);
// this.readStream.on("data", function(a) { self.parse_data(self, a); });
EventParser.prototype.parse_data = function(self, data)
{
/*
* Data format :
* {
* 0x00 : struct timeval time { long sec (8), long usec (8) } (8 bytes)
* 0x08 : __u16 type (2 bytes)
* 0x10 : __u16 code (2 bytes)
* 0x12 : __s32 value (4 bytes)
* } = (16 bytes)
*/
var dataBuffer = new Buffer(data);
var slicedBuffer = dataBuffer.slice(0, 16);
dataBuffer = dataBuffer.slice(16, dataBuffer.length);
while (dataBuffer.length > 0 && slicedBuffer.length == 16)
{
var type = GetDataType(slicedBuffer),
code = GetDataCode(slicedBuffer),
value = GetDataValue(slicedBuffer);
if (type == CST.EV.KEY)
{ // Key was pressed: KEY event type
if (code == 42 && value == 1) { self.shift_pressed = true; }
if (code == 42 && value == 0) { self.shift_pressed = false; }
console.log(type + "\t" + code + "\t" + value + "\t(" + GetKey(self.shift_pressed, code) + ")")
// GetKey uses a static array to get the actual character
// based on whether the shift key is held or not
if (value == 1)
self.handle_processed_data(GetKey(self.shift_pressed, code));
// handle_processed_data adds characters together, and outputs the string when encountering a
// separator character (in this case, '\n')
}
// Take a new slice, and loop.
slicedBuffer = dataBuffer.slice(0, 16);
dataBuffer = dataBuffer.slice(16, dataBuffer.length);
}
}
// My system is in little endian!
function GetDataType(dataBuffer) { return dataBuffer.readUInt16LE(8); }
function GetDataCode(dataBuffer) { return dataBuffer.readUInt16LE(10); }
function GetDataValue(dataBuffer) { return dataBuffer.readInt32LE(12); }
我基本上是在使用 Buffer
填充顶部解释的数据结构。有趣的部分是接近尾声的 console.log
,它将打印回调中传递的所有有趣的内容(与 KEY
事件相关)!这是此类日志的结果,包括预期结果和实际结果:
EventParserConstructor: Listening to /dev/input/event19
/* Expected result: CODE-128 */
/* Note that value 42 is the SHIFT key */
1 42 1 ()
1 46 1 (C)
1 42 0 ()
1 46 0 (c)
1 42 1 ()
1 24 1 (O)
1 42 0 ()
1 24 0 (o)
1 42 1 ()
1 32 1 (D)
1 42 0 ()
1 32 0 (d)
1 42 1 ()
1 18 1 (E)
1 42 0 ()
1 18 0 (e)
1 12 0 (-)
1 2 0 (1)
1 3 1 (2)
1 3 0 (2)
1 9 1 (8)
1 9 0 (8)
1 28 1 (
)
[EventParser_Handler]/event_parser.handle_processed_data: CODE28
/* Actual result: CODE28 */
/* The '-' and '1' events can be seen in the logs, but only */
/* as key RELEASED (value: 0), not key PRESSED */
我们可以清楚地看到经过的 -
和 1
字符事件,但只是按键释放(值:0),而不是按键。最奇怪的是,大多数时候,事件都被正确翻译了。但是有 10% 的时间会发生这种情况。
ReadStream
是否偶尔会占用一些字节?如果是,我应该使用什么替代方案?
提前致谢!
嗯,原来我的循环是烂的。
我假设数据只会以 16 字节的块形式出现...显然情况并非总是如此。所以有时,我有 <16 字节的数据包在两个 'data'
事件回调之间遗留和丢失。
我通过向我的 class 添加一个 excessBuffer
字段来添加它,并在接收数据时使用它来填充我的初始 slicedBuffer
。
我正在使用 node.js
为 Linux 编写键盘事件解析器。它工作得有点好,但有时节点似乎跳过了几个字节。我正在使用 ReadStream
来获取数据,处理它,处理它,并最终在遇到分隔符时输出它(在我的例子中,\n
)。
这是我的 class 处理读取数据的部分:
// This method is called through this callback:
// this.readStream = fs.createReadStream(this.path);
// this.readStream.on("data", function(a) { self.parse_data(self, a); });
EventParser.prototype.parse_data = function(self, data)
{
/*
* Data format :
* {
* 0x00 : struct timeval time { long sec (8), long usec (8) } (8 bytes)
* 0x08 : __u16 type (2 bytes)
* 0x10 : __u16 code (2 bytes)
* 0x12 : __s32 value (4 bytes)
* } = (16 bytes)
*/
var dataBuffer = new Buffer(data);
var slicedBuffer = dataBuffer.slice(0, 16);
dataBuffer = dataBuffer.slice(16, dataBuffer.length);
while (dataBuffer.length > 0 && slicedBuffer.length == 16)
{
var type = GetDataType(slicedBuffer),
code = GetDataCode(slicedBuffer),
value = GetDataValue(slicedBuffer);
if (type == CST.EV.KEY)
{ // Key was pressed: KEY event type
if (code == 42 && value == 1) { self.shift_pressed = true; }
if (code == 42 && value == 0) { self.shift_pressed = false; }
console.log(type + "\t" + code + "\t" + value + "\t(" + GetKey(self.shift_pressed, code) + ")")
// GetKey uses a static array to get the actual character
// based on whether the shift key is held or not
if (value == 1)
self.handle_processed_data(GetKey(self.shift_pressed, code));
// handle_processed_data adds characters together, and outputs the string when encountering a
// separator character (in this case, '\n')
}
// Take a new slice, and loop.
slicedBuffer = dataBuffer.slice(0, 16);
dataBuffer = dataBuffer.slice(16, dataBuffer.length);
}
}
// My system is in little endian!
function GetDataType(dataBuffer) { return dataBuffer.readUInt16LE(8); }
function GetDataCode(dataBuffer) { return dataBuffer.readUInt16LE(10); }
function GetDataValue(dataBuffer) { return dataBuffer.readInt32LE(12); }
我基本上是在使用 Buffer
填充顶部解释的数据结构。有趣的部分是接近尾声的 console.log
,它将打印回调中传递的所有有趣的内容(与 KEY
事件相关)!这是此类日志的结果,包括预期结果和实际结果:
EventParserConstructor: Listening to /dev/input/event19
/* Expected result: CODE-128 */
/* Note that value 42 is the SHIFT key */
1 42 1 ()
1 46 1 (C)
1 42 0 ()
1 46 0 (c)
1 42 1 ()
1 24 1 (O)
1 42 0 ()
1 24 0 (o)
1 42 1 ()
1 32 1 (D)
1 42 0 ()
1 32 0 (d)
1 42 1 ()
1 18 1 (E)
1 42 0 ()
1 18 0 (e)
1 12 0 (-)
1 2 0 (1)
1 3 1 (2)
1 3 0 (2)
1 9 1 (8)
1 9 0 (8)
1 28 1 (
)
[EventParser_Handler]/event_parser.handle_processed_data: CODE28
/* Actual result: CODE28 */
/* The '-' and '1' events can be seen in the logs, but only */
/* as key RELEASED (value: 0), not key PRESSED */
我们可以清楚地看到经过的 -
和 1
字符事件,但只是按键释放(值:0),而不是按键。最奇怪的是,大多数时候,事件都被正确翻译了。但是有 10% 的时间会发生这种情况。
ReadStream
是否偶尔会占用一些字节?如果是,我应该使用什么替代方案?
提前致谢!
嗯,原来我的循环是烂的。
我假设数据只会以 16 字节的块形式出现...显然情况并非总是如此。所以有时,我有 <16 字节的数据包在两个 'data'
事件回调之间遗留和丢失。
我通过向我的 class 添加一个 excessBuffer
字段来添加它,并在接收数据时使用它来填充我的初始 slicedBuffer
。