问题描述
全部,
我有一个打印到流的程序.我需要在内存中缓冲这个流,然后根据需要将每一行打印到一个实际文件中.
I have a program that prints to a stream. I need to buffer this stream in memory, and then print each line as necessary to an actual file later.
由于fprintf()
函数调用必须有一个FILE *
指针,所以我需要在内存中指定指针寻址空间.我使用了 open_memstream()
函数,但 Windows 不支持此功能.
Since the fprintf()
function calls must have a FILE *
pointer, I need to have said pointer addressing space in memory. I had used the open_memstream()
function, but this is not supported on windows.
由于 malloc()
返回一个 void *
指针,该指针根据需要神奇地转换为必要的指针,我可以将其用作我的 FILE *
指针?如果是这样,有哪些注意事项?我需要注意空间不足吗?
Since malloc()
returns a void *
pointer that magically casts to the necessary pointer as needed, could I use that as my FILE *
pointer? If so, what caveats are there? Do I need to watch out for running out of space?
更新:
在找到 open_memstream()
的源代码后,这比本来应该的更难,看起来他们正在对 malloc 的空间执行文件流.
After finding the source for open_memstream()
, which was harder than it should have been, it looks like they are doing a file stream to malloc'd space.
既然是这样,而且我有他们的源代码,我将看看是否无法获得一个工作版本来使用 mingw 为 windows 进行交叉编译.
Since that is the case, and I've got their source, I'm going to se if I can't get a working version to cross compile for windows with mingw.
推荐答案
对于那些追我的人,有希望!有一个解决方案.正如我的问题所述,我使用的是 open_memstream()
,它在 Windows 上不受支持.
For those who come after me, have hope! There is a solution. As noted in my question, I was using open_memstream()
, which is unsupported on windows.
因为我有一个 File *
指针(这不能更改为 char *
),我需要将它重定向到内存直到稍后.由于我正在处理内存中的文件,因此我查看了 mmap()
.它轻松地解决了问题,但同样,它仅适用于 linux.
Since I have a File *
pointer (this cannot be changed to char *
), I needed to redirect it to memory until later. Since I'm dealing with a file in memory, I looked into mmap()
. It handily solves the problem, but again, it is linux only.
但是,windows 包含一个名为 MapViewOfFile()
的 mmap()
的推论.通过 #ifdef
的魔力,我可以使用任何必要的方法:
But, windows includes a corollary to mmap()
called MapViewOfFile()
. Through the magic of #ifdef
I've got it using whichever is necessary:
#ifdef WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#endif
稍后,在 main 方法中,我调用了两个平台都支持的 tmpfile()
.这为我打开了一个有保证的唯一临时文件的流.现在我有了 FILE *
指针,我需要 mmap()
空间.但是 mmap()
需要一个文件描述符,而不是一个流,所以我使用了 fileno()
函数来获取新的文件描述符.
Later on, in the main method, I call tmpfile()
which is supported on both platforms. This opens a stream to a guaranteed unique temporary file for me. Now that I have my FILE *
pointer, I need to mmap()
the space. But mmap()
needs a file descriptor, not a stream, so I used the fileno()
function to get the new file descriptor.
/* create tmp file and get file descriptor */
int fd;
yyout = tmpfile();
fd = fileno(yyout);
现在我有更多的 #ifdef
代码来确定需要使用哪个内存映射代码集.请注意两个版本之间映射空间的差异.Windows 映射 16384 字节
,Linux 映射 4096 字节
.这是因为 Windows 上的较小值段错误,如我的问题中所述.
Now I have some more #ifdef
code to determine which memory mapping codeset needs to be used. Note the difference in the mapped space between the two versions. Windows maps 16384 bytes
and linux maps 4096 bytes
. This is because the smaller value segfaults on windows, as noted in my question here.
#ifdef WIN32
HANDLE fm;
HANDLE h = (HANDLE) _get_osfhandle (fd);
fm = CreateFileMapping(
h,
NULL,
PAGE_READWRITE|SEC_RESERVE,
0,
16384,
NULL);
if (fm == NULL) {
fprintf (stderr, "%s: Couldn't access memory space! %s
", argv[0], strerror (GetLastError()));
exit(GetLastError());
}
bp = (char*)MapViewOfFile(
fm,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if (bp == NULL) {
fprintf (stderr, "%s: Couldn't fill memory space! %s
", argv[0], strerror (GetLastError()));
exit(GetLastError());
}
#else
bp = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
if (bp == MAP_FAILED) {
fprintf (stderr, "%s: Couldn't access memory space! %s
", argv[0], FileName, strerror (errno));
exit(errno);
}
#endif
现在发生了一系列工作,将数据发送到 yyout
流.最终 flushData()
方法被调用.它使用空终止字符结束流,刷新它,然后倒带它.然后指向内存空间的指针通过一个函数指针,连同要打印到的正确流.
A bunch of work now happens, wherin data is sent to the yyout
stream. Eventually the flushData()
method gets called. It finalizes the stream with a null terminated character, flushes it, and then rewinds it. Then the pointer to the memory space is passed through a function pointer, along with the proper stream to print to.
void flushData(void) {
/* write out data in the stream and reset */
while (currFields < headerFields) { fprintf(yyout, ","""); currFields++; }
currFields = 0;
fprintf(yyout, "%c%c%c", 13, 10, ' ');
fflush(yyout);
rewind(yyout);
if (faqLine == 1) {
faqLine = 0; /* don't print faq's to the data file */
}
else {
(*printString)(outfile, bp);
fflush(outfile);
}
fflush(yyout);
rewind(yyout);
}
这是可以指向打印的功能之一.它遍历内存空间并打印每个字符,直到遇到之前打印的空值.
This is one of the functions that could be pointed to for printing. It walks the memory space and prints each char until it hits the null printed earlier.
int printAnsi( FILE *outstream, char *string) {
/* loop over the chars in string and print them to the outputstream as ansi */
char * ps = string;
while (*ps != ' ') {
fprintf(outstream, "%c", *ps);
ps++;
}
return 0;
}
所有这一切的最终结果是,我有一个流到内存空间的流,就像 open_memstream()
一样,直到还有一个字符指针,我可以在必要时用来遍历内存空间.它是跨平台的,并且(看似)功能齐全.
The end result of all this being that I have a stream to memory space just like open_memstream()
, up to also having a char pointer I can use to walk through the memory space if necessary. It is cross platform, and (seemingly) fully functional.
如果有人想了解更多详细信息或有关于我应该解决的问题的说明,请添加评论.
If anyone wants more details or have notes about problems I should fix, please add a comment.
这篇关于我可以用 malloc 和隐式强制转换替换对 open_memstream 的调用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!