我可以使用 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!
编辑: 对于多年后阅读此问题的人,除了已接受的答案之外,您还应该查看
open_memstream(3)
,它的行为比 fmemopen
更像这些 Java 类。
如果您的操作系统提供fmemopen, 也许它会满足你的目的。
在 C++ 中(并且添加了 C++ 标签),您可以编写一个接受任意输入/输出流的函数。由于
std::stringstream
或 std::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
}
}
类似地,如果您想读取数据,请使用
std::istream
而不是 std::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
}
}
正如 Ise 恰当地指出的那样,POSIX 2008 中有一个用于此功能 fmemopen 的函数,并且 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 ...
反过来更容易;也就是说,有一个写入内存的函数,然后使用它既写入内存又写入文件。您可以使用 mmap 以便一块内存最终由文件支持,并且写入该内存会将数据写入关联的文件。
如果您使用
std::istream
和 std::ostream
而不是低级 C FILE* 对象,那么 C++ 可以方便地提供 std::istringstream
和 std::ostringstream
来读取/写入字符串。
您会注意到,C 中几乎所有以“f”开头且对文件进行操作的函数,都有以“s”开头且对字符串进行操作的等效函数。也许更好的方法是设计一个不特定于文件或字符串的 I/O 接口,然后提供分别连接到文件和字符串的实现。然后根据该接口(而不是低级 C 和 C++ I/O)实现核心逻辑。这样做的好处还在于允许未来扩展,例如通过内置的压缩、复制等支持来支持网络文件。
带有内存映射文件。这是特定于平台的,因此您需要查找有关在目标系统上创建内存映射文件的信息。我相信 posix 版本是
mmap
。无论如何,在谷歌上搜索“内存映射文件”应该会得到很多帮助。
fmemopen
的示例,适用于 Linux。显然 有人还为 Windows 编写了 fmemopen
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const char *fakeStdin = "The fake stdin input\n"
"The end of the stream will be at the null ->";
size_t streamBytes = strlen( fakeStdin );
FILE *f = fmemopen( (void*)fakeStdin, streamBytes, "rb" );
if( !f ) {
puts( "Couldn't open FILE* to memory" );
return 1;
}
char* buf = (char*)malloc( streamBytes + 1 );
size_t readBytes = fread( buf, 1, streamBytes, f );
printf( "Read %zu bytes from stream:\n", readBytes );
puts( buf );
free( buf );
fclose( f );
return 0;
}