有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

比较两个文件,或者为什么java中的代码比C++快?

为什么java中的代码比C++快? 我需要逐字节比较两个文件。 例如,当比较两个文件大小时,650MB需要40秒到C++,10秒为java。p>

C++代码:

//bufferSize = 8mb
std::ifstream lFile(lFilePath.c_str(), std::ios::in | std::ios::binary);
std::ifstream rFile(rFilePath.c_str(), std::ios::in | std::ios::binary);

std::streamsize lReadBytesCount = 0;
std::streamsize rReadBytesCount = 0;

do {
    lFile.read(p_lBuffer, *bufferSize);
    rFile.read(p_rBuffer, *bufferSize);
    lReadBytesCount = lFile.gcount();
    rReadBytesCount = rFile.gcount();

    if (lReadBytesCount != rReadBytesCount ||
        std::memcmp(p_lBuffer, p_rBuffer, lReadBytesCount) != 0)
    {
        return false;
    }
} while (lFile.good() || rFile.good());

return true;

和Java代码:

InputStream is1 = new BufferedInputStream(new FileInputStream(f1)); 
InputStream is2 = new BufferedInputStream(new FileInputStream(f2)); 

byte[] buffer1 = new byte[64];
byte[] buffer2 = new byte[64];

int readBytesCount1 = 0, readBytesCount2 = 0;

while (
    (readBytesCount1 = is1.read(buffer1)) != -1 &&
    (readBytesCount2 = is2.read(buffer2)) != -1
) {             
    if (Arrays.equals(buffer1, buffer2) && readBytesCount1 == readBytesCount2)
        countItr++;
    else {
        result = false
        break;
    }
}

共 (3) 个答案

  1. # 1 楼答案

    我刚刚拿起你的java程序,写了一个C++程序,两个文件都差不多,比较两个相同的文件,或者给一秒钟。p> <> P>一个可能的、琐碎的解释是,你先运行C++程序,然后运行java程序。如果这是您唯一的测试,那么执行时间的差异可以通过缓存来解释,尽管在今天的硬件上读取650 MB需要40秒的时间

    数据块位于系统文件缓存中,第二次没有磁盘访问来检索文件。为了获得比较的结果,用C++和java程序多次运行测试。p>

    在你的代码中,你有

    lFile.read(p_lBuffer, *bufferSize);
    

    这与你一开始的评论相矛盾

    //bufferSize = 8mb
    

    所以,除非你展示真实的完整的代码,否则任何人的猜测都是正确的

    吃我自己的狗粮

    #include <iostream>
    #include <fstream>
    #include <cstring>
    
    const size_t N = 8 * 1024 * 1024;
    char buf1[N], buf2[N];
    
    int main(int argc, char **argv)
    {
        std::iostream::sync_with_stdio(false);
        std::ifstream f1(argv[1]);
        std::ifstream f2(argv[2]);
        while (f1.read(buf1, sizeof(buf1)) && f2.read(buf2, sizeof(buf2))) {
            size_t n1 = f1.gcount(), n2 = f2.gcount();
            if (n1 != n2 || memcmp(buf1, buf2, n1) != 0)
                return 1;
        }
    
        return 0;
    }
    
  2. # 2 楼答案

    虽然缓冲区大小的答案非常好,而且可能非常重要,但问题的另一个可能来源是使用iostream库。我一般不会用那个图书馆做这种工作。例如,这可能导致的一个问题是额外的复制,因为iostream为您提供了缓冲。我将使用原始的readwrite调用

    例如,在Linux C++11平台上,我会这样做:

    #include <array>
    #include <algorithm>
    #include <string>
    #include <stdexcept>
    
    // Needed for open and close on a Linux platform
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    using ::std::string;
    
    bool same_contents(const string &fname1, const string &fname2)
    {
       int fd1 = ::open(fname1.c_str(), O_RDONLY);
       if (fd1 < 0) {
          throw ::std::runtime_error("Open of " + fname1 + " failed.");
       }
       int fd2 = ::open(fname2.c_str(), O_RDONLY);
       if (fd2 < 0) {
          ::close(fd1);
          fd1 = -1;
          throw ::std::runtime_error("Open of " + fname2 + " failed.");
       }
    
       bool same = true;
       try {
          ::std::array<char, 4096> buf1;
          ::std::array<char, 4096> buf2;
          bool done = false;
    
          while (!done) {
             int read1 = ::read(fd1, buf1.data(), buf1.size());
             if (read1 < 0) {
                throw ::std::runtime_error("Error reading " + fname1);
             }
             int read2 = ::read(fd2, buf2.data(), buf2.size());
             if (read2 < 0) {
                throw ::std::runtime_error("Error reading " + fname2);
             }
             if (read1 != read2) {
                same = false;
                done = true;
             }
             if (same && read1 > 0) {
                const auto compare_result = ::std::mismatch(buf1.begin(),
                                                            buf1.begin() + read1,
                                                            buf2.begin());
                if (compare_result.first != (buf1.begin() + read1)) {
                   same = false;
                }
             }
             if (!same || (buf1.size() > read1)) {
                done = true;
             }
          }
       } catch (...) {
          if (fd1 >= 0) ::close(fd1);
          if (fd2 >= 0) ::close(fd2);
          throw;
       }
       if (fd1 >= 0) ::close(fd1);
       if (fd2 >= 0) ::close(fd2);
       return same;
    }
    
  3. # 3 楼答案

    <>一个可能的答案是C++代码使用8 MB的缓冲区,而java版本使用64字节。如果差异在前几个字节内,会发生什么情况?然后java版本只需要读取64字节,找到差异,C++版本需要读取800万字节。如果您希望比较它们,您应该使用相同的缓冲区大小

    此外,如果文件相同,则可能还有其他原因造成差异。考虑分配8 MB数据(甚至跨越多个页面)所需的时间,而不是简单分配64个字节所需的时间。由于您是按顺序读取的,因此开销实际上在内存方面