【问题标题】:Copy data from fstream to stringstream with no buffer?将数据从 fstream 复制到没有缓冲区的 stringstream?
【发布时间】:2011-05-03 03:37:53
【问题描述】:

我是否可以将数据从fstream(文件)传输到stringstream(内存中的流)?

目前,我使用的是缓冲区,但这需要双倍的内存,因为你需要将数据复制到缓冲区,然后将缓冲区复制到字符串流,直到你删除缓冲区,数据才会复制到记忆。

std::fstream fWrite(fName,std::ios::binary | std::ios::in | std::ios::out);  
    fWrite.seekg(0,std::ios::end); //Seek to the end  
    int fLen = fWrite.tellg(); //Get length of file  
    fWrite.seekg(0,std::ios::beg); //Seek back to beginning  
    char* fileBuffer = new char[fLen];  
    fWrite.read(fileBuffer,fLen);  
    Write(fileBuffer,fLen); //This writes the buffer to the stringstream  
    delete fileBuffer;`

有谁知道如何在不使用中间缓冲区的情况下将整个文件写入字符串流?

【问题讨论】:

  • 有什么意义?您是否正在尝试提高吞吐量?在这种情况下,您可能需要放弃fstream,iostream 很慢。您是否正在尝试减少内存占用?分块读取文件而不是一次性读取文件可能会有所帮助。

标签: c++ stl buffer fstream stringstream


【解决方案1】:
 ifstream f(fName);
 stringstream s;
 if (f) {
     s << f.rdbuf();    
     f.close();
 }

【讨论】:

    【解决方案2】:
    // need to include <algorithm> and <iterator>, and of course <fstream> and <sstream>
    ifstream fin("input.txt");
    ostringstream sout;
    copy(istreambuf_iterator<char>(fin),
         istreambuf_iterator<char>(),
         ostreambuf_iterator<char>(sout));
    

    【讨论】:

    • @Charles -- 尽管如此,我认为这就是他的意图。他不想分配一个新的 char 数组。他想直接从fstream对象读取到stringstream对象。
    • @BenVoigt,你是对的 - 我误读了 OP。我以为他们在问如何直接读入字符串流。
    • 这似乎就是我要找的东西! @PigBen 你对我来说是对的,不想使用 char 数组。我有一个问题:复制方法是否考虑了字符串流的当前写入位置?如果我使用tellp(8),那么使用copy()它仍然可以工作,还是会从字符串流的开头写入?编辑:我自己试过了,它似乎工作得很好。谢谢!
    • 不过,我更喜欢 pinkfloydx 的解决方案(由 Andre 制作成一个完整的示例)。 std::copy 将不得不一次移动一个元素,而 operator &lt;&lt;(istream&amp;) 可能会更快。
    • @Ben Voigt:我也是。我真的不知道你可以这么容易地做到这一点。我的测试显示略有不同。在一个 50k 的文件上,两种方法各复制 10 次,他的平均每次复制 1.45 秒,我的平均 1.62 秒。
    【解决方案3】:

    ostream 的文档中,有several overloads for operator&lt;&lt;。其中一个接受streambuf* 并读取所有流缓冲区的内容。

    这是一个示例使用(编译和测试):

    #include <exception>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    
    int main ( int, char ** )
    try
    {
            // Will hold file contents.
        std::stringstream contents;
    
            // Open the file for the shortest time possible.
        { std::ifstream file("/path/to/file", std::ios::binary);
    
                // Make sure we have something to read.
            if ( !file.is_open() ) {
                throw (std::exception("Could not open file."));
            }
    
                // Copy contents "as efficiently as possible".
            contents << file.rdbuf();
        }
    
            // Do something "useful" with the file contents.
        std::cout << contents.rdbuf();
    }
    catch ( const std::exception& error )
    {
        std::cerr << error.what() << std::endl;
        return (EXIT_FAILURE);
    }
    

    【讨论】:

      【解决方案4】:

      使用 C++ 标准库的唯一方法是使用 ostrstream 而不是 stringstream

      您可以使用自己的 char 缓冲区构造一个 ostrstream 对象,然后它将获得缓冲区的所有权(因此不需要更多的复制)。

      但是请注意,strstream 标头已被弃用(尽管它仍然是 C++03 的一部分,而且很可能在大多数标准库实现中始终可用),如果您使用忘记以空值终止提供给 ostrstream 的数据。这也适用于流运算符,例如:ostrstreamobject &lt;&lt; some_data &lt;&lt; std::ends;std::ends 以空值终止数据)。

      【讨论】:

        【解决方案5】:

        如果您使用的是Poco,这很简单:

        #include <Poco/StreamCopier.h>
        
        ifstream ifs(filename);
        string output;
        Poco::StreamCopier::copyToString(ifs, output);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-09-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-08
          • 1970-01-01
          相关资源
          最近更新 更多