ReadStream跳过字节?

时间:2017-11-16 13:35:36

标签: node.js linux-kernel keyboard-events

我正在使用node.js为Linux编写键盘事件解析器。它工作得有点好,但有时似乎节点正在跳过几个字节。我正在使用ReadStream来获取数据,处理数据,处理它,并在遇到分隔符时最终输出它(在我的例子中,\n)。

以下是我的类中处理读取数据的部分:

// 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占用一些字节吗?如果是,我应该使用哪种替代方案?

提前致谢!

1 个答案:

答案 0 :(得分:0)

好吧,事实证明我的循环已经烂了。

我假设数据只有16个字节的数据块......显然情况并非如此。所以有时候,我在两个'data'事件回调之间留下了<16字节的数据包并丢失了。

我添加了excessBuffer字段给我的课程,并在接收数据时使用它来填充我的初始slicedBuffer