如何从fstream读取128字节到string对象?(复制)

时间:2022-01-17 20:10:20

This question already has an answer here:

这个问题已经有了答案:

How do I read exactly 128 bytes from an fstream into a string object?

如何从fstream读取128字节到string对象?

I wrote some code to read the first 128 bytes of a file and print it and then the last 128 bytes of the file and print that. The last part works, since you can easily iterate to EOF, but how do I get exactly 128 bytes from the front? The code below doesn't work since you can't add 128 to an ifstream iterator, it's not indexable, only incrementable (it seems).

我编写了一些代码来读取文件的前128个字节并打印它,然后输出文件的最后128个字节并打印它。最后一部分是有效的,因为您可以轻松地迭代到EOF,但是如何从前面得到确切的128个字节呢?下面的代码不起作用,因为您不能将128添加到ifstream迭代器中,它是不可索引的,只能是递增的(看起来)。

Sure I could make an iterator and *++ it 128 times, but there must be a single line straightforward way to do it, right?

当然我可以让一个迭代器和*+它重复128次,但是必须有一个简单的方法,对吧?

#include <iostream>
#include <fstream>
#include <string>

int main(int argc, char **argv)
{
    std::ifstream ifs ("input.txt",std::ifstream::in | std::ifstream::binary);

    if (ifs.good())
    {
    // read first 128 bytes into a string
        ifs.seekg(0,std::ifstream::beg);
        std::string first128((std::istreambuf_iterator<char>(ifs)),
                             (std::istreambuf_iterator<char>(ifs))+128);

        std::cout << first128 << std::endl;

    // read last 128 bytes into a string
        ifs.seekg(-128,std::ifstream::end);
        std::string last128((std::istreambuf_iterator<char>(ifs)),
                            std::istreambuf_iterator<char>());

        std::cout << last128 << std::endl;

        return 0;
    }

    return 1;
}

3 个解决方案

#1


1  

char buffer[129];
ifs.read (buffer,128);
buffer[128] = '\0';
first128 = buffer;

How about this then:

这个怎么样:

template <typename Itr, typename Out>
void copy_n(Itr it, size_t count, Out out)
{
    for(size_t i=0;i<count;++i)
      out = *it++;
} 

...

std::string first128; 
std::istreambuf_iterator<char> it(ifs);
copy_n( it, 128,
  std::back_inserter<std::string>(first128) );

#2


1  

My answer uses an intermediate buffer, but perhaps you will be happy that it uses iterators to initialize the string from the buffer.

我的回答使用了一个中间缓冲区,但是您可能会很高兴它使用迭代器来初始化来自缓冲区的字符串。

std::vector<char> buffer(128); // create a buffer
ifs.read( &buffer[0], buffer.size() ); // read to buffer
std::string first128( buffer.begin(), buffer.end() ); // copy from vector

To me it seems like they got a little too cute with the implementation of iostreams. Trying to use iterators for stream I/O is overly complicated.

在我看来,他们对iostreams的实现有点太可爱了。尝试为流I/O使用迭代器是非常复杂的。

By the way, I suspect the implementation that you were attempting will, under the covers, do a variety of intermediate buffering (perhaps some in the kernel, some in the library) as well as re-allocating and copying the string several times as it grows.

顺便说一下,我怀疑您正在尝试的实现将在幕后进行各种中间缓冲(可能是内核中的一些缓冲区,一些在库中),以及在它增长时多次重新分配和复制字符串。

One other idea: Do you really need the result in a standard string? You might just work from the vector -- avoiding the final step of copying to a string. Or, if you are feeling adventurous, you could create your own string class that does allow you to expose the internal buffer in the same way that vector does.

另一个想法是:你真的需要一个标准字符串的结果吗?你可以从向量开始——避免最后一步复制到字符串。或者,如果您喜欢冒险,您可以创建自己的字符串类,它允许您以与vector相同的方式公开内部缓冲区。

#3


0  

Here i have some of researching over streambuffer, read directly to string from istream by constructor:

这里我有一些关于streambuffer的研究,通过构造函数直接从istream读取到string:

class mystringbuf : public std::stringbuf
{
public:
    explicit mystringbuf(std::istream& istr, size_t n,
                        std::ios_base::openmode __mode = std::ios_base::in )
    {
        _M_string.resize(n);
        std::stringbuf::_M_stringbuf_init(__mode);
        istr.read(gptr(), n);
    }
public:
    std::stringbuf::char_type* gptr() const
    {
        return std::stringbuf::gptr();
    }
    std::string& str_ref(){
        return _M_string;
    }
};
std::ostream& operator << (std::ostream& ostr, mystringbuf& buf){
    ostr << buf.str_ref();
    return ostr;
}

Example to use:

使用示例:

using std::cout;
using std::endl;

int main()
{
    std::stringbuf buffer;          // empty buffer
    buffer.str("abc def ABC DEF "); // not empty now
    std::istream is (&buffer);      // associate stream buffer to stream
    mystringbuf data(is, 10);       // read 10 bytes
    cout << "data=" <<  data << endl;
    return 0;
}

Output:

输出:

data=abc def AB

Please forward me if i`am somewhere was wrong.

如果我说错了,请转告我。

#1


1  

char buffer[129];
ifs.read (buffer,128);
buffer[128] = '\0';
first128 = buffer;

How about this then:

这个怎么样:

template <typename Itr, typename Out>
void copy_n(Itr it, size_t count, Out out)
{
    for(size_t i=0;i<count;++i)
      out = *it++;
} 

...

std::string first128; 
std::istreambuf_iterator<char> it(ifs);
copy_n( it, 128,
  std::back_inserter<std::string>(first128) );

#2


1  

My answer uses an intermediate buffer, but perhaps you will be happy that it uses iterators to initialize the string from the buffer.

我的回答使用了一个中间缓冲区,但是您可能会很高兴它使用迭代器来初始化来自缓冲区的字符串。

std::vector<char> buffer(128); // create a buffer
ifs.read( &buffer[0], buffer.size() ); // read to buffer
std::string first128( buffer.begin(), buffer.end() ); // copy from vector

To me it seems like they got a little too cute with the implementation of iostreams. Trying to use iterators for stream I/O is overly complicated.

在我看来,他们对iostreams的实现有点太可爱了。尝试为流I/O使用迭代器是非常复杂的。

By the way, I suspect the implementation that you were attempting will, under the covers, do a variety of intermediate buffering (perhaps some in the kernel, some in the library) as well as re-allocating and copying the string several times as it grows.

顺便说一下,我怀疑您正在尝试的实现将在幕后进行各种中间缓冲(可能是内核中的一些缓冲区,一些在库中),以及在它增长时多次重新分配和复制字符串。

One other idea: Do you really need the result in a standard string? You might just work from the vector -- avoiding the final step of copying to a string. Or, if you are feeling adventurous, you could create your own string class that does allow you to expose the internal buffer in the same way that vector does.

另一个想法是:你真的需要一个标准字符串的结果吗?你可以从向量开始——避免最后一步复制到字符串。或者,如果您喜欢冒险,您可以创建自己的字符串类,它允许您以与vector相同的方式公开内部缓冲区。

#3


0  

Here i have some of researching over streambuffer, read directly to string from istream by constructor:

这里我有一些关于streambuffer的研究,通过构造函数直接从istream读取到string:

class mystringbuf : public std::stringbuf
{
public:
    explicit mystringbuf(std::istream& istr, size_t n,
                        std::ios_base::openmode __mode = std::ios_base::in )
    {
        _M_string.resize(n);
        std::stringbuf::_M_stringbuf_init(__mode);
        istr.read(gptr(), n);
    }
public:
    std::stringbuf::char_type* gptr() const
    {
        return std::stringbuf::gptr();
    }
    std::string& str_ref(){
        return _M_string;
    }
};
std::ostream& operator << (std::ostream& ostr, mystringbuf& buf){
    ostr << buf.str_ref();
    return ostr;
}

Example to use:

使用示例:

using std::cout;
using std::endl;

int main()
{
    std::stringbuf buffer;          // empty buffer
    buffer.str("abc def ABC DEF "); // not empty now
    std::istream is (&buffer);      // associate stream buffer to stream
    mystringbuf data(is, 10);       // read 10 bytes
    cout << "data=" <<  data << endl;
    return 0;
}

Output:

输出:

data=abc def AB

Please forward me if i`am somewhere was wrong.

如果我说错了,请转告我。