避免 C++ 中的 memcpy缓冲输出

发布于 2024-11-03 16:31:58 字数 687 浏览 1 评论 0原文

我试图直接写入 fstream 输出缓冲区以避免 memcpy

为什么下面的代码不起作用?

它在 Linux 上编译、运行并生成正确长度的输出文件。但输出文件不包含正确的文本。另请注意,由于某种原因,当我注释掉涉及 str2 的两行时,会生成一个长度为零的输出文件。

注意:此示例并未避免 memcpy,但如果它有效,它将帮助我避免应用程序中的 memcpy

#include <fstream>

int main(int argc, char *argv[]) {
  std::fstream out;
  char buffer[512];
  out.rdbuf()->pubsetbuf(buffer, 512);
  out.open("file.txt", std::fstream::out);
  char *str1 = "test text.";
  strcpy(buffer, str1);
  out.rdbuf()->pubseekpos(strlen(str1), std::ios_base::out);
  char *str2 = "why?";
  out << str2;
  out.flush();
  out.close();
}

I am trying to write directly to an fstream output buffer to avoid a memcpy.

Why does the following code not work?

It compiles, runs and produces the right length output file on Linux. But the output file does not contain correct text. Also note that for some reason, when I comment out the two lines involving str2, then an output file of zero length is produced.

Note: This example does not avoid memcpy, but if it works, it will help me avoid a memcpy in my application.

#include <fstream>

int main(int argc, char *argv[]) {
  std::fstream out;
  char buffer[512];
  out.rdbuf()->pubsetbuf(buffer, 512);
  out.open("file.txt", std::fstream::out);
  char *str1 = "test text.";
  strcpy(buffer, str1);
  out.rdbuf()->pubseekpos(strlen(str1), std::ios_base::out);
  char *str2 = "why?";
  out << str2;
  out.flush();
  out.close();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

紫竹語嫣☆ 2024-11-10 16:31:58

您为流提供一个缓冲区供内部使用。然后你就不给它任何东西可写。

事实上,您将某些内容复制到缓冲区而不告诉流不会在文件中提供任何内容。

您可能已经注意到,seekpos 用于在文件中定位,而不是在缓冲区中移动。缓冲区仅供流内部使用!

You give the stream a buffer for its internal use. Then you don't give it anything to write.

The fact that you copy something to the buffer without telling the stream doesn't give you anything in the file.

As you might have noticed, the seekpos is for positioning in the file, not for moving in the buffer. The buffer is for the stream's internal use only!

短暂陪伴 2024-11-10 16:31:58

当您 out.rdbuf()->pubseekpos(strlen(str1), std::ios_base::out); 时,这会要求流向前跳过新创建的文件。您能期望它从您指定的缓冲区中获取内容吗?线索:您是否见过任何涉及指定缓冲区的示例,表明您需要以某种方式初始化它或指定它包含的非垃圾字符的初始数量?不...因为流本身跟踪缓冲区的哪些部分正在使用。因此,当您获取假定的空缓冲区并向前跳时,它会生成中间的 NUL。将它们设置在缓冲区中是没有意义的(因此,在 pubseekpos 之后简单地执行 memcpy 也不起作用) - 如果您跳转了怎么办超过一个缓冲区大小的转发?

希望这至少可以说明问题,尽管我在现阶段还没有考虑如何强制流改变它对有意义的缓冲区内容的“跟踪”......

When you out.rdbuf()->pubseekpos(strlen(str1), std::ios_base::out);, this asks the stream to skip forwards through the newly created file. Can you expect it to take stuff from the buffer you specified? A clue: have you seen any examples involving specifying a buffer that said you needed to initialise it in some way or specify the initial number of non-garbage characters it contained? No... because the stream itself tracks which parts of the buffer are in use. Hence - when you take the presumed empty-buffer and skip forwards, it generates the intervening NULs. It wouldn't make sense for them to be set in the buffer (so simply doing a memcpy after the pubseekpos won't work either) - what if you've jumped more than a buffer-size forwards?

Hopefully this serves to at least illustrate the problem, although I haven't given any thought at this stage to how you might force the stream to change it's "tracking" of meaningful buffer content....

过期以后 2024-11-10 16:31:58

现在还早,但你基本上都在做吗

#include <fstream>

int main(int argc, char *argv[]) 
{

  std::fstream out;
  out.open("file.txt", std::fstream::out);

  out << "test text";
  out << "why?";

  out.flush();
  out.close();
}

It's still early, but aren't you basically doing

#include <fstream>

int main(int argc, char *argv[]) 
{

  std::fstream out;
  out.open("file.txt", std::fstream::out);

  out << "test text";
  out << "why?";

  out.flush();
  out.close();
}

?

月下伊人醉 2024-11-10 16:31:58

我对 C++ iostream 库不够熟悉,无法说出您的程序出了什么问题,我只想提一下,如果您想自己进行缓冲,那么使用 read() 和 write() 接口可能会更直接直接(man 2 写)。如果您自己进行缓冲,iostream 库可能不会给您带来太多好处,并且只会掩盖实际发生的情况。

I'm not familiar enough with the C++ iostream library to say what is wrong with your program, I would only mention that if you want to do your own buffering it would likely be more straightforward to use the read() and write() interfaces directly (man 2 write). If you're doing your own buffering the iostream libraries probably won't buy you much, and will only obscure what's actually going on.

赠我空喜 2024-11-10 16:31:58

我看到三种可能性

  1. 实现您自己的流缓冲区类
  2. 使用本机文件 API 使用
  3. pubsetbuf(0, 0) 禁用缓冲

实现流缓冲区实际上并不那么困难,并且会给您机会将 C++ 风格的流插入与直接内存访问混合在一起,无需
牺牲性能。

I see three possibilities

  1. Implement your own stream-buffer class
  2. Use the native file API
  3. Disable buffering with pubsetbuf(0, 0)

Implementing a stream-buffer is really not that difficult, and would give you the opportunity to mix C++ style stream insertion with direct memory access, without
sacrificing performance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文