【问题标题】:Directly use c++ stream buffer直接使用c++流缓冲区
【发布时间】:2020-04-29 09:24:58
【问题描述】:

这是this question 的改进版本。我希望我通过一个例子成功地让我的问题更清楚。

以下程序将流式传输文本文件并打印其内容:

size_t constexpr Buffer_size = 8;

char my_buffer[Buffer_size];

std::ifstream stream("text.txt");

for (; stream;) {
    stream.read(my_buffer, Buffer_size)
    std::cout.write(my_buffer, stream.gcount());
}

// output
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. In mi risus, eleifend ac sapien sed, sollicitudin auctor neque.

据我所知,流将有一个内部缓冲区来填充,然后将块复制到my_buffer。 my_buffer 只是短暂使用,在这种情况下用于打印,然后再次被覆盖。

我的问题是,是否可以使用流内部缓冲区来执行此类临时操作。这个程序很接近,但输出不太正确。

size_t constexpr Buffer_size = 8;

char my_buffer[Buffer_size];

std::ifstream stream;
stream.rdbuf()->pubsetbuf(my_buffer, Buffer_size);
stream.open("text.txt");

for (; stream;) {
    stream.peek();
    std::cout.write(my_buffer, Buffer_size);
    stream.ignore(Buffer_size);
}

// output
// Lorem i.psum do.lor sit. amet, .consect.etur ad.ipiscin. In mi .risus, .eleifen.d ac sa.pien se.d, soll.icitudi.r neque..
// neque..
// neque.

这个想法可行吗?省略read() 调用是否会像我希望的那样保存副本?

编辑: 另一方面,考虑这个程序:

size_t constexpr Buffer_size = 8;

char my_buffer_a[Buffer_size];
char my_buffer_b[Buffer_size];

std::memset(my_buffer_a, 'A´, Buffer_size);

std::ifstream stream;
stream.rdbuf()->pubsetbuf(my_buffer_a, Buffer_size);
stream.open("text.txt");

for (; stream;) {
   stream.read(my_buffer_b, Buffer_size);
   std::cout.write(my_buffer_a, Buffer_size);
}

// output  
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

输出表明设置为流的内部缓冲区的 my_buffer_a 从未被触及。这意味着我不明白何时实际使用内部流缓冲区。

【问题讨论】:

    标签: c++ stream


    【解决方案1】:

    您的程序在我看来不错,但实际上您使用的是依赖于实现的行为。 您实际上应该保存一份副本,但 std::cout.write(my_buffer, Buffer_size); 可能会在 std::cout 内部缓冲区 (write infos) 内进行复制

    我更喜欢使用操作系统功能来实现您想要做的事情。

    【讨论】:

    • cout.write() 在这种情况下仅用作示例。我想证明我需要的数据已经存在,为什么要复制它。什么是依赖于实现的部分?也许我想要的不能用可移植的 stdlib 函数来完成,但我想了解原因。
    • 经过进一步研究,它看起来像是使用缓冲区的标准状态(实现无法绕过它)。因此,从您之前写的内容来看,您实际上是通过执行peek 而不是read 来保存副本,但是write 的过程相同,因为它将缓冲区复制到您的输出流内部缓冲区。您可以尝试的一种解决方案是为两个对象使用相同的缓冲区,但您必须自己处理缓冲区位置。
    • 请忽略输出流。我用另一个例子编辑了这个问题。显然内部缓冲区并不总是被使用。如果您一次读取足够大的块,也许没有不必要的复制。
    • 我建议你尝试使用小于buffer_a 的大小的buffer_b,看看它是否在读取大小大于或等于缓冲区大小时避免复制,我不确定你得到的行为是标准行为。
    • 只要读取大小大于内部缓冲区,内部似乎没有被触及。至少在这个简单的实验中。
    猜你喜欢
    • 2011-11-14
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多