快速比较输入流的方法

dac*_*cwe 23 java compare inputstream

我有一个问题,我需要快速比较两个输入流.

今天我有这样的功能:

private boolean isEqual(InputStream i1, InputStream i2) throws IOException {

    try {
        // do the compare
        while (true) {
            int fr = i1.read();
            int tr = i2.read();

            if (fr != tr)
                return false;

            if (fr == -1)
                return true;
        }

    } finally {
        if (i1 != null)
            i1.close();
        if (i2 != null)
            i2.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

但它真的很慢.我想使用缓冲读取,但还没有想出一个好方法.

一些额外的东西使它更难:

  • 我不想将其中一个输入流读入内存(整个)
  • 我不想使用第三方库

我需要一个实用的解决方案 - 代码!:)

Sni*_*las 75

到目前为止,我最喜欢的是使用Apache Commons IO库中org.apache.commons.io.IOUtilshelper类:

IOUtils.contentEquals( is1, is2 );
Run Code Online (Sandbox Code Playgroud)


aio*_*obe 16

这样的事可能会:

private static boolean isEqual(InputStream i1, InputStream i2)
        throws IOException {

    ReadableByteChannel ch1 = Channels.newChannel(i1);
    ReadableByteChannel ch2 = Channels.newChannel(i2);

    ByteBuffer buf1 = ByteBuffer.allocateDirect(1024);
    ByteBuffer buf2 = ByteBuffer.allocateDirect(1024);

    try {
        while (true) {

            int n1 = ch1.read(buf1);
            int n2 = ch2.read(buf2);

            if (n1 == -1 || n2 == -1) return n1 == n2;

            buf1.flip();
            buf2.flip();

            for (int i = 0; i < Math.min(n1, n2); i++)
                if (buf1.get() != buf2.get())
                    return false;

            buf1.compact();
            buf2.compact();
        }

    } finally {
        if (i1 != null) i1.close();
        if (i2 != null) i2.close();
    }
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*rey 9

使用缓冲读取只需使用BufferedInputStreams包装InputStreams.但是,您可能会同时获得读取大块的最佳性能.

private boolean isEqual(InputStream i1, InputStream i2) throws IOException {
    byte[] buf1 = new byte[64 *1024];
    byte[] buf2 = new byte[64 *1024];
    try {
        DataInputStream d2 = new DataInputStream(i2);
        int len;
        while ((len = i1.read(buf1)) > 0) {
            d2.readFully(buf2,0,len);
            for(int i=0;i<len;i++)
              if(buf1[i] != buf2[i]) return false;
        }
        return d2.read() < 0; // is the end of the second file also.
    } catch(EOFException ioe) {
        return false;
    } finally {
        i1.close();
        i2.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 哇,我使用了你的解决方案,用 Arrays#equals 替换了 for 循环。对于 200mb 文件,速度是原来的两倍。我认为这是因为该方法是 HotSpotIntrinsicCandidate。 (2认同)