0

我已经实现了自己的类来读取pcap文件。(二进制文件,即tcpdump、wireshark)

public class PcapReader implements Iterator<PcapPacket> {
    private InputStream is;

    public PcapReader (File file) throws FileNotFoundException, IOException {
        is = this(new DataInputStream(
             new BufferedInputStream(
                 new FileInputStream(file))));
    }

    @Override
    public boolean hasNext () {
        try {
            return (is.available() > 0);
        } catch (IOException e) {
            return false;
        }
    }

    //pseudo code!
    @Override
    public PcapPacket next () {
        is.read(header);
        is.read(body);

        return new PcapPacket(header, body);
    }

    //more code here
}

然后我像这样使用它:

PcapReader reader = new PcapReader(file);
while (reader.hasNext()) {
    PcapPacket pcapPacket = reader.next();
    //process packet
}

被测文件有 190 Mb。而且我还使用 JVisualVM 进行分析。

  • hasNext()被调用170万次,时间为7.7

  • next()被调用的次数相同,时间为3.6

我的主要问题是为什么hasNext()在绝对值上如此耗时并且还大于两倍next

4

3 回答 3

2

当您is.available()在您的hasNext()方法中调用 时,它会归结为FileInputStream.available()实现。这是一种本地方法,从FileInputStream 源代码中可以看出。

最后,这确实是一个耗时的操作,因为文件操作的操作系统实现必须提前检查是否有更多数据可供读取。因此,它实际上会执行读取操作而不更新文件指针(或将其更新回原始位置),只是为了检查是否有“下一个”字节。

于 2013-03-06T14:22:21.820 回答
1

我敢肯定,available()方法的内部(本机)实现不仅仅是返回 some return availableSize;,而是更复杂。Stream 使用 OS API 计算可用数据;特别是,例如,对于日志文件,由于 Stream 读取它们而写入。

于 2013-03-06T14:23:01.043 回答
1

我已经实现了自己的类来读取pcap文件。

因为您没有使用jNetPcap,或者因为您正在使用 jNetPcap 但需要可以从File?

如果是后者,您可能想要使用具有“更多数据可用”方法和单独的“所以读取该数据”方法的模式以外的模式;读取数据并返回“可用数据包”/“文件结尾”/“错误”指示或为后一种情况或两种情况DataInputStream引发异常的东西(似乎为 I/O 错误和 EOF 引发异常,所以对你的班级做同样的事情可能是有意义的)。

是的,这意味着它不能是 an Iterator,但也许Iterators 最初并不打算表示顺序文件中的记录(此外,如果您真的希望它是 an Iterator,您将如何处理该remove方法?)。

如果您可以避免需要从 a 读取File,则可以使用 jNetPcap 自己的例程来读取捕获文件,在 libpcap 1.1.0 及更高版本中,它还可以读取一些 pcap-ng 文件。

于 2013-03-07T01:31:16.010 回答