C++ 使文件指针读/写到内存中的位置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5135854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:29:04  来源:igfitidea点击:

Make a file pointer read/write to an in-memory location

c++c

提问by Leo Izen

I can make a file pointer write to a file with fopen(). But can I make a file pointer that will make it so calling functions such as fputc or fprintf will write to a pointer in memory? An example of this is ByteArrayOutputStream in java. Also: could I run it in reverse, where a library needs a file pointer to read from, so I allocate memory, and make a new file pointer that will read from this memory location but return EOF when the size of the chunk runs out? (like ByteArrayInputStream in Java). Is there a way to do this in C? For example:

我可以使用 fopen() 将文件指针写入文件。但是我可以创建一个文件指针,这样调用函数(如 fputc 或 fprintf )将写入内存中的指针吗?这方面的一个例子是 java 中的 ByteArrayOutputStream。另外:我可以反向运行它吗,库需要一个文件指针来读取,所以我分配内存,并创建一个新的文件指针,该指针将从这个内存位置读取,但在块的大小用完时返回 EOF?(如 Java 中的 ByteArrayInputStream)。有没有办法在 C 中做到这一点?例如:

FILE *p = new_memory_file_pointer();
fprintf(p, "Hello World!\n");
char *data = get_written_stuff(p);
printf("%s", data); //will print Hello World!

&& / ||

&& / ||

char s[] = "Hello World!\n";
FILE *p = new_memory_file_pointer_read(s, sizeof(s));
char *buffer = (char *)malloc( 1024*sizeof(char) );
fread((void *)buffer, 1, sizeof(s), p);
printf("%s", buffer); //prints Hello World!

EDIT:To those reading this question years later, in addition to the accepted answer, you should look at open_memstream(3), which behaves more like these Java classes than fmemopendoes.

编辑:对于多年后阅读此问题的人,除了已接受的答案之外,您还应该查看open_memstream(3),它的行为更像这些 Java 类而不是fmemopen

采纳答案by Ise Wisteria

If your operating system provides fmemopen, probably it will meet your purpose.

如果您的操作系统提供fmemopen,它可能会满足您的目的。

回答by phlipsy

In C++ (and you added the C++ tag) you can write a function accepting an arbitrary input/output stream. Since std::stringstreamor std::ofstreamare derived classes you can pass both of them equally into this function. An example:

在 C++ 中(并且您添加了 C++ 标记),您可以编写一个接受任意输入/输出流的函数。由于std::stringstreamstd::ofstream是派生类,您可以将它们均等地传递给此函数。一个例子:

#include <iostream> // for std::cout
#include <fstream> // for std::ofstream
#include <sstream> // for std::stringstream

void write_something(std::ostream& stream) {
  stream << "Hello World!" << std::endl;
}

int main() {
  write_something(std::cout); // write it to the screen
  {
    std::ofstream file("myfile.txt");
    write_something(file); // write it into myfile.txt
  }
  {
    std::stringstream stream;
    write_something(stream); // write it into a string
    std::cout << stream.str() << std::endl; // and how to get its content
  }
}

And analogously with std::istreaminstead of std::ostreamif you want to read the data:

如果你想读取数据std::istreamstd::ostream则与而不是类似:

void read_into_buffer(std::istream& stream, char* buffer, int length) {
  stream.read(buffer, length);
}

int main() {
  char* buffer = new char[255];

  {
    std::ifstream file("myfile.txt");
    read_into_buffer(file, buffer, 10); // reads 10 bytes from the file
  }
  {
    std::string s("Some very long and useless message and ...");
    std::stringstream stream(s);
    read_into_buffer(stream, buffer, 10); // reads 10 bytes from the string
  }
}

回答by Michael Aaron Safyan

As Ise aptly points out, there is a function for this fmemopenin POSIX 2008and that is supported on Linux. Using POSIX 2004, probably the closest thing to that would be to use a temporary file:

作为伊势很贴切地指出,没有此功能fmemopen2008年POSIX和支持在Linux上。使用POSIX 2004,可能最接近的是使用临时文件:

// This is for illustration purposes only. You should add error checking to this.
char name[] = "/tmp/name-of-app-XXXXXX";
int temporary_descriptor = mkstemp(name);
unlink(temporary_descriptor);
FILE* file_pointer = fdopen(temporary_descriptor, "r+");
// use file_pointer ...

It's easier to do the reverse; that is, to have a function that writes into memory, and then to use that both to write into memory and also to write to a file. You can use mmapso that a chunk of memory ends up being backed by a file, and writing into that memory writes the data to the associated file.

反过来更容易;也就是说,有一个写入内存的函数,然后使用它既写入内存又写入文件。您可以使用mmap以便一块内存最终由文件支持,并且写入该内存会将数据写入关联的文件。

If you use std::istreamand std::ostreaminstead of low-level C FILE* objects, then C++ conveniently provides std::istringstreamand std::ostringstreamfor reading/writing strings.

如果您使用std::istreamandstd::ostream而不是低级 C FILE* 对象,则 C++ 可以方便地提供std::istringstreamandstd::ostringstream用于读取/写入字符串。

You will note that almost all of the functions in C that begin with an "f" and that operate on files, have equivalents beginning with "s" that operate on strings. A perhaps better approach would be to design an interface for I/O that is not specific to either files or strings, and then provide implementations that connect to files and strings, respectively. Then implement your core logic in terms of this interface, instead of in terms of low-level C and C++ I/O. Doing that also has the benefit of allowing for future extensions, such as supporting network files with builtin support for compression, duplication, etc.

您会注意到,C 中几乎所有以“f”开头并对文件进行操作的函数都有以“s”开头的对字符串进行操作的等效函数。也许更好的方法是为 I/O 设计一个不特定于文件或字符串的接口,然后分别提供连接到文件和字符串的实现。然后根据此接口而不是低级 C 和 C++ I/O 来实现您的核心逻辑。这样做还具有允许未来扩展的好处,例如支持具有压缩、复制等内置支持的网络文件。

回答by Edward Strange

With a memory mapped file. This is platform specific so you'll need to find the information about creating mem-mapped files on your target system(s). I believe the posix version is mmap. At any rate, searching for "memory mapped file" on google should turn up a bunch of help.

带有内存映射文件。这是特定于平台的,因此您需要找到有关在目标系统上创建内存映射文件的信息。我相信 posix 版本是mmap. 无论如何,在谷歌上搜索“内存映射文件”应该会得到很多帮助。