繁体   English   中英

从 Java NIO 套接字通道读取字节,直到到达标记

[英]Read bytes from Java NIO socketchannel until marker is reached

我正在寻找一种使用 Java NIO 从套接字通道读取字节的有效方法。 这个任务很简单,我有一个解决方案,尽管我正在寻找一种更清洁、更有效的方法来解决这个问题。 这是场景:

  1. 从套接字通道读取数据
  2. 此数据是 UTF-8 编码字符串
  3. 每行以\r\n结尾,长度未知
  4. 读完每一行后,我想对消息做点什么

我的解决方案按字节读取数据字节并将每个字节与我的标记(在 UTF-8 代码页中的值为 10)进行比较。 这是代码:

ByteBuffer res = ByteBuffer.allocate(512);
boolean completed = false;
try {
    while (true) {
        ByteBuffer tmp = ByteBuffer.allocate(1);
        if(soc.read(tmp) == -1) {
             break;
        }

        // set marker back to index 0
        tmp.rewind();
        byte cur = tmp.get();
        res.put(cur);

        // have we read newline?
        if (cur == 10) {
            doSomething(res);
            res.clear();
        }
    }

} catch(Exception ex) {
     handle(ex);
}

即使这样做了,也可能有更好的方法,不需要在每次迭代后进行每字节比较。

谢谢你的帮助!

我这样做的方法是尽可能多地读取,例如32 KB,一旦你读完了它,你就将数据逐字节复制到另一个缓冲区,例如StringBuilder。 如果上次读取时缓冲区中仍有数据,则可以继续使用缓冲区,直到它全部消耗完为止,此时您将读取更多数据。

注意:每次系统调用都很昂贵。 它可能需要2-5微秒。 这听起来不是很多,除非你打电话数百万次,它会增加读取1 MB的秒数。

这是我最终解决方案的代码。

ByteBuffer res = ByteBuffer.allocate(maxByte);
while (true) {
    ByteBuffer tmp = ByteBuffer.allocate(maxByte);

    int bytesRead = clientSocket.read(tmp);
    if (bytesRead == -1) {
        break;
    }

    // rewind ByteBuffer to get it back to start
    tmp.rewind();

    for (int i = 0; i < bytesRead; i++) {
        byte cur = tmp.get(i);
        res.put(cur);
        if (cur == marker) {
            processMessage(res);
            res = ByteBuffer.allocate(maxByte);
        }
    }

    // reached end of message, break loop
    if (bytesRead < tmpSize) {
        break;
    }
}

也许这是一个愚蠢的问题,但不会阻止 IO 解决这个问题? (inputstream.readAllBytes()) 无论如何你都在阻塞线程,因为你必须等待标记

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM