【问题标题】:Reading block by block from file then split test line by line从文件中逐块读取,然后逐行拆分测试
【发布时间】:2017-03-20 13:46:29
【问题描述】:

我正在从文件读取到缓冲区,然后我将读取的文本划分为字符串,其中每个文本以新行结尾形成一个新字符串。

这是我的代码:

int ysize = 20000;
char buffer2[ysize];
int flag = 0;
string temp_str;
vector<string> temp;
while(fread(buffer2, ysize, 1, fp2)>0){
    //printf("%s", buffer2);
    std::string str(buffer2);
    //push the data into the vect
    std::string::size_type pos = 0;
    std::string::size_type prev = 0;
    /*means the last read did not read a full sentence*/
    if (flag == 1) {
        if (buffer[0] == '\n') {
          //this means we have read the last senstense correctly, directly go to the next
        }
        else{
            if((pos = str.find("\n", prev)) != std::string::npos){
                temp_str+=str.substr(prev, pos - prev);
                temp.push_back(temp_str);
                prev = pos + 1;
            }
            while ((pos = str.find("\n", prev)) != std::string::npos)
            {
                temp.push_back(str.substr(prev, pos - prev));
                prev = pos + 1;
            }

            // To get the last substring (or only, if delimiter is not found)
            temp.push_back(str.substr(prev));

            if (buffer2[19999] != '\n') {
                //we did not finish readind that query
                flag = 1;
                temp_str = temp.back();
                temp.pop_back();
            }
            else{
                flag = 0;
            }


        }
    }
    else{

        while ((pos = str.find("\n", prev)) != std::string::npos)
        {
            temp.push_back(str.substr(prev, pos - prev));
            prev = pos + 1;
        }

        // To get the last substring (or only, if delimiter is not found)
        temp.push_back(str.substr(prev));

        if (buffer2[19999] != '\n') {
            //we did not finish readind that query
            flag = 1;
            temp_str = temp.back();
            temp.pop_back();
        }
        else{
            flag = 0;
        }}
}

问题是这不能正确读取数据,它几乎消除了一半的文本。

我不确定我在这里缺少什么。我的想法是逐块读取数据,然后逐行分割,这就是while循环中发生的事情。我正在使用标志处理溢出案例。

【问题讨论】:

  • while (std::getline(myFileStream, lineStr)) {...},并相信您的 std::ifstream 实现会进行合理的缓冲。
  • 我做到了,但性能很糟糕。我正在尝试读取数据块以提高性能,当我测试时这是一个显着的差异,但分割字符串有点进退两难
  • 我同意 BoBTFish,但也许你可以试试 std::regexstd::stringstream

标签: c++ c++11 iostream


【解决方案1】:

首先请注意,fread 不会神奇地创建以空字符结尾的字符串,这意味着 std::string str(buffer2) 将导致未定义的行为。所以你应该做类似

int nread = 0; 
while( (nread =fread(buffer2, ysize-1, 1, fp2)) > 0 ){
    buffer2[nread] = 0; 
    std::string str(buffer2);
    ...     

为避免您在此处实现的缓冲方法,您可以使用fgets 逐行读取,然后您只需担心连接比读取缓冲区长的行。

除了我发现的一个问题:如果缓冲区中的第一个字符是换行符并且 flag==1 您跳过整个当前缓冲区并读取下一个如果仍有数据可用的。 (我假设 buffer[0] 实际上是指 buffer2[0])。

【讨论】:

  • 谢谢!,buffer2[nread] = 0; 不是什么意思,这总是会删除我最后读取的字符并将其替换为 0,不是吗? & fgets 不能解决我的问题,我试图一次阅读不止一行
  • 不,因为在 C/C++ 中他的索引是从 0 开始的,因此当 nread 字符被读入缓冲区时,它们将在 buffer[0] 中。 ..buffer[nread-1],并使用 buffer[nread]=0 确保空终止。至于 fgets - 是的,我知道您想一口气阅读多于一行的内容,但也许 fgets 可以为您节省一些拆分缓冲区的麻烦稍后,fgets 也做了一些缓冲,所以使用它很可能不会损失性能。
猜你喜欢
  • 2013-09-08
  • 2023-02-10
  • 1970-01-01
  • 2012-06-22
  • 2019-05-14
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多