简体   繁体   English

C ++ ifstream.getline()明显慢于Java的BufferedReader.readLine()?

[英]C++ ifstream.getline() significantly slower than Java's BufferedReader.readLine()?

I'm in the process of rewriting one of my Android applications to take advantage of the NDK and one of the first things it has to do every time is open a 1.5MB text file (approximately 150k lines) and put every line in a data structure. 我正在重写我的一个Android应用程序以利用NDK,每次打开一个1.5MB文本文件(大约150k行)时,首先要做的事情之一就是将每一行放在一个数据中结构体。 When I did this operation using Java's BufferedReader.readLine(), reading the file from the SD card takes ~2.5 seconds. 当我使用Java的BufferedReader.readLine()执行此操作时,从SD卡读取文件大约需要2.5秒。 Here's the code I used for this: 这是我用于此的代码:

try {
    BufferedReader br = new BufferedReader(new FileReader("/sdcard/testfile.txt"));
    String thisLine;
    while ((thisLine = br.readLine()) != null) {
        Log.d(TAG, thisLine);
    }
} catch (IOException e) {
    //Log error
}

Using C++ with ifstream takes MUCH longer...around 3 minutes for the same file. 在ifstream中使用C ++需要更长的时间......对于同一个文件大约需要3分钟。 Here's the code I used in C++: 这是我在C ++中使用的代码:

char buffer[256];
ifstream ifs;
ifs.open("/sdcard/testfile.txt", ifstream::in);
if (ifs.is_open()) {
    while (!ifs.eof()) {
        ifs.getline (buffer,100);
        LOGD(buffer);
    }
}

I'm pretty rusty on C++, but can't think of any logical explanation for the increased read time. 我对C ++很生疏,但是对于增加的读取时间没有任何合理的解释。 For a while I thought it might be the LOGD function, but I tried taking that out altogether and the read time wasn't really helped much at all. 有一段时间我认为它可能是LOGD功能,但我尝试完全取消它,读取时间根本没有多大帮助。 Does anyone have any ideas on what the issue could be? 有没有人对这个问题有什么想法? Is there any faster way to read a file line by line in C++? 有没有更快的方法在C ++中逐行读取文件? Thanks. 谢谢。

One thought is the stdio synchronization might be slowing you down. 一个想法是stdio同步可能会减慢你的速度。 That can be turned off. 那可以关掉。 I don't know if that would account for all of the difference, but you could try. 我不知道这是否会解释所有的差异,但你可以试试。 Also, you're not using eof() correctly. 此外,您没有正确使用eof() Finally, I'd use the std::string version of getline() 最后,我使用std :: string版本的getline()

std::ios::sync_with_stdio(false);
ifstream ifs("/sdcard/testfile.txt");
std::string line;
while (getline(ifs, line))
{
    LOGD(line);
}

I haven't tested this code, but you can try it and see if it makes a difference. 我没有测试过这段代码,但你可以尝试一下,看看它是否有所作为。

Is it possible that the stream is unbuffered, and it's doing an SD access for each byte of data? 流是否可能是无缓冲的,并且它正在为每个数据字节进行SD访问? To provide a buffer, do the following (size as you feel appropriate). 要提供缓冲区,请执行以下操作(根据需要调整大小)。

ifstream ifs;
char stream_buffer[4096];
ifs.rdbuf()->pubsetbuf(stream_buffer, sizeof(stream_buffer) );
ifs.open(argv[1]);

C++ does not buffer streams for you (edit: they won't by default , see Dave Smith's solution). C ++不会为您缓冲流(编辑: 默认情况下不会这样,请参阅Dave Smith的解决方案)。 I will tell you that your code will be slow on a normal platter based disk. 我会告诉你,你的代码在基于普通盘片的磁盘上会很慢。 I don't have a lot of experience with android, fwiw. 我没有很多android,fwiw的经验。

I generally use something like this: 我通常使用这样的东西:

struct buffered_reader {
    buffered_reader(std::istream &data_) : data(data_), done(false) {}
    bool next(std::string &line) {
        if (!lines.size()) {
            if (done)
                return false;
            std::string line;
            for (size_t i = 0; i < 500; i++) {
                std::getline(data, line);
                if (data.eof()) {
                    done = true;
                    break;
                }
                lines.push_back(line);
            }
        }
        line = lines.front();
        lines.pop_front();
        return true;
    }
    std::istream &data;
    bool done;

    std::deque<std::string> lines;
};

TEST(blah) {
    std::stringstream ss;
    ss << "a" << std::endl;
    ss << "a" << std::endl;
    ss << "a" << std::endl;
    ss << "a" << std::endl;

    buffered_reader reader(ss);
    std::string line;
    while(reader.next(line)) {
        std::cout << line << std::endl;
    }
}

This isn't in production anywhere, so no warranties beyond the testing you see here ;) 这在任何地方都没有生产,所以除了你在这里看到的测试之外没有任何保证;)

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

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