- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我一直认为 WriteFile 比 fwrite 更高效,因为 fwrite 内部调用了 WriteFile,但下面的测试代码表明 fwrite 比 WriteFile 快得多。
fwrite 花费 2 毫秒,而 WriteFile 需要 27000(FILE_ATTRIBUTE_NORMAL),两者都在每次写入调用后刷新。如果我用 FILE_FLAG_WRITE_THROUGH 调用 WriteFile,并注释 FlushFileBuffers(wfile) 行,WriteFile 会更快,它花费 800。
那么 fwrite 真的调用了 WriteFile 吗?是什么造成如此巨大的差异? fwrite 在内部是如何工作的?如何使用 API 比 fwrite 更有效地将数据写入文件?(无缓冲,同步)。
#include <Windows.h>
#include <stdio.h>
#include <iostream>
int main() {
FILE* cfile = fopen("file1.txt", "w");
HANDLE wfile = CreateFile("file2.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
/*FILE_ATTRIBUTE_NORMAL*/FILE_FLAG_WRITE_THROUGH, NULL);
DWORD written = 0;
DWORD start_time, end_time;
char * text = "test message ha ha ha ha";
int size = strlen(text);
int times = 999;
start_time = timeGetTime();
for(int i = 0; i < times; ++i) {
fwrite(text, 1, size, cfile);
fflush(cfile);
}
end_time = timeGetTime();
std::cout << end_time - start_time << '\n';
start_time = timeGetTime();
for(int i = 0; i < times; ++i) {
WriteFile(wfile, text, size, &written, NULL);
//FlushFileBuffers(wfile);
}
end_time = timeGetTime();
std::cout << end_time - start_time << std::endl;
system("pause");
return 0;
}
更新:感谢您的回答,这里是答案:查看VS目录\VS\crt\src\fflush.c:
//fflush.c
int __cdecl _fflush_nolock (FILE *str) {
//irrelevant codes
if (str->_flag & _IOCOMMIT) {
return (_commit(_fileno(str)) ? EOF : 0);
}
return 0;
}
所以这里有一个_IOCOMMIT标志,然后看...\src\fdopen.c
FILE * __cdecl _tfdopen (int filedes, const _TSCHAR *mode) {
//irrelevant codes
while(*++mode && whileflag)
switch(*mode) {
//...
case _T('c'):
if (cnflag)
whileflag = 0;
else {
cnflag = 1;
fileflag |= _IOCOMMIT;
}
break;
//...
}
_tfopen是fopen内部调用的,引用fopen的文档,我发现是这样的:
"模式:'c'
启用关联文件名的提交标志,以便在调用 fflush 或 _flushall 时将文件缓冲区的内容直接写入磁盘。"因此,只有在调用 fopen 时设置了 'c' 标志时,才会调用 _commit。
_commit 函数最终会调用 FlushFileBuffers。
除此之外,我发现当我只写少量数据到文件时(不超过缓冲区大小),如果没有fflush的fwrite,显然不会写文本,而对于API,WriteFile之后即使我不写' t 调用 FlushFileBuffers,当我打开文件(程序处于 sleep 状态)时,内容会自动写入文件,这也是我对 flush 感到困惑的原因之一,这个操作可能是由操作系统完成的,WriteFile 将数据复制到系统缓存,其文件缓冲区由操作系统管理,因此 fflush() 只在内部调用 WriteFile 而没有真正刷新是合理的,系统知道何时刷新它们,可能是在文件句柄关闭时,或者当另一个 I/O 访问此文件时发生。所以我将基准修改为:
start_time = timeGetTime();
for(int i = 0; i < times; ++i) {
fwrite(text, 1, size, cfile);
fflush(cfile);
}
end_time = timeGetTime();
std::cout << end_time - start_time << '\n';
start_time = timeGetTime();
for(int i = 0; i < times; ++i) {
WriteFile(wfile, text, size, &written, NULL);
}
end_time = timeGetTime();
std::cout << end_time - start_time << std::endl;
结果是次数:99999fwrite:217写入文件:171
所以,总而言之,要加快API文件的写入操作:
不要显式调用FlushFileBuffers,系统缓存中的数据会在需要时刷新到磁盘。
为 WriteFile 获取一个缓冲区,就像 fwrite 一样,因为 API 调用比简单的 memcpy 花费更多的时间,当缓冲区已满时调用 WriteFile。
最佳答案
使用类似 Process Monitor (procmon) 的工具从 Sysinternals 中,您会看到对 fflush()
的调用与 FlushFileBuffers(wfile)
(或 FILE_FLAG_WRITE_THROUGH
标记为 CreateFile()
)。
fwrite()
会将数据写入缓冲区,直到缓冲区填满,这将导致它将缓冲区中的数据发送到 WriteFile()
调用。当您调用 fflush()
时,所发生的只是缓冲区中当前的数据被传递给对 WriteFile()
的调用 - fflush()
不调用 FlushFileBuffers()
:
1:21:32.9391534 AM test.exe 6132 WriteFile C:\temp\file1.txt SUCCESS Offset: 0, Length: 24
1:21:32.9392200 AM test.exe 6132 WriteFile C:\temp\file1.txt SUCCESS Offset: 24, Length: 24
1:21:32.9392340 AM test.exe 6132 WriteFile C:\temp\file1.txt SUCCESS Offset: 48, Length: 24
1:21:32.9392436 AM test.exe 6132 WriteFile C:\temp\file1.txt SUCCESS Offset: 72, Length: 24
1:21:32.9392526 AM test.exe 6132 WriteFile C:\temp\file1.txt SUCCESS Offset: 96, Length: 24
1:21:32.9392623 AM test.exe 6132 WriteFile C:\temp\file1.txt SUCCESS Offset: 120, Length: 24
为了比较,这里有一个来自 fwrite()
循环的跟踪示例,没有 fflush()
调用:
1:27:28.5675034 AM test.exe 3140 WriteFile C:\temp\file1.txt SUCCESS Offset: 0, Length: 1,024
1:27:28.5676098 AM test.exe 3140 WriteFile C:\temp\file1.txt SUCCESS Offset: 1,024, Length: 1,024
1:27:28.5676399 AM test.exe 3140 WriteFile C:\temp\file1.txt SUCCESS Offset: 2,048, Length: 1,024
1:27:28.5676651 AM test.exe 3140 WriteFile C:\temp\file1.txt SUCCESS Offset: 3,072, Length: 1,024
下面是 WriteFile()
循环的跟踪片段(带有 FILE_ATTRIBUTE_NORMAL
标志和对 FlushFileBuffers()
的显式调用 -因为 FlushFileBuffers()
调用显示在跟踪中,而不是仅显示为第二个 4KB WriteFile()
调用,所以它只是使跟踪中发生的事情更容易看到。
1:21:29.0068503 AM test.exe 6132 WriteFile C:\temp\file2.txt SUCCESS Offset: 0, Length: 24, Priority: Normal
1:21:29.0069197 AM test.exe 6132 FlushBuffersFile C:\temp\file2.txt SUCCESS
1:21:29.0069517 AM test.exe 6132 WriteFile C:\temp\file2.txt SUCCESS Offset: 0, Length: 4,096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
1:21:29.0087574 AM test.exe 6132 WriteFile C:\temp\file2.txt SUCCESS Offset: 24, Length: 24
1:21:29.0087798 AM test.exe 6132 FlushBuffersFile C:\temp\file2.txt SUCCESS
1:21:29.0088087 AM test.exe 6132 WriteFile C:\temp\file2.txt SUCCESS Offset: 0, Length: 4,096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
1:21:29.0102260 AM test.exe 6132 WriteFile C:\temp\file2.txt SUCCESS Offset: 48, Length: 24
1:21:29.0102428 AM test.exe 6132 FlushBuffersFile C:\temp\file2.txt SUCCESS
1:21:29.0102701 AM test.exe 6132 WriteFile C:\temp\file2.txt SUCCESS Offset: 0, Length: 4,096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
1:21:29.0113444 AM test.exe 6132 WriteFile C:\temp\file2.txt SUCCESS Offset: 72, Length: 24
1:21:29.0113602 AM test.exe 6132 FlushBuffersFile C:\temp\file2.txt SUCCESS
1:21:29.0113848 AM test.exe 6132 WriteFile C:\temp\file2.txt SUCCESS Offset: 0, Length: 4,096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
所以您的基准测试显示出 WriteFile()
循环的严重劣势的原因仅仅是因为您对 FlushFileBuffers()
进行了大约一千次调用在 fwrite()
循环中。
关于c++ - fwrite 比 Windows 中的 WriteFile 快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14290337/
我遇到一些 fwrite 问题,它以我不明白的方式失败。 在这段代码中,fwrite 都失败并给出 tmp = 0。 if ((file = fopen(filenameout, "wb")) !
好吧,事情是这样的……我记得上周创建了一个程序,要求我以二进制模式打开一个文件并向其中写入数据。首先,我尝试使用fopen函数,检查结果是否正确,然后尝试写入数据。我记得第一次尝试时,fwrite 操
早上好, 我正在尝试将以下结构的内容写入文件(更具体地说是 BMP 文件),并且想知道为什么 fwrite 的二进制输出ing 整个结构和 fwrite结构体的各个项目是不同的。这就是C的工作方式吗?
我在某个地方遇到了这个。 正在写入一个文件,然后rewind(fileptr) 完成,然后写入应该写入文件开头的内容。但是写在开头,不会覆盖文件的内容吗?请指教。 最佳答案 技术上,是 是的,文件将被
fwrite 一个整数取决于字节序,但是有没有一种方法可以将一个整数 0x00000004 写入一个文件,这样无论它运行在什么机器上,它都可以始终被读取为 0x00000004。 一个想法是始终按照特
我在 php 中编写一个函数,在客户端我有一个 Canvas 图像,我使用 toDataUrl() 和一个文件名将图像保存在服务器上。这是代码: 关键是这段代码有效。对于我在其上使用的三分之二的页面
当我运行这个小代码并在控制台上输入 3 个整数时,由于 fwrite 语句,它没有按应有的方式打印出来。只有在我连续按回车键一段时间后,它才会打印出来。帮助?P.S:学习速度比 scanf 和 pri
我的网站在 /var/www/html/hs/ ,我有我的更新.php .它应该写到/var/www/html/hs/json/myFile.json ,但事实并非如此。当我尝试写入 的同一目录时更新
这个函数应该获取一个参数作为文件的指针并将所有文件放入struct anagram ,然后将其写入另一个文件。现在每个数据之间都有很大的空间。 charCompare 工作正常,因为我制作了一个测试文
这是在我的网站上上传带有“var$”内容的“file.txt”的 URL: http://www.mywebsite.com/fwrite.php?stringData=var$&myFile=fil
如果字符串包含 ~,我似乎无法将其打印到标准输出。 > A = "/.git". > io:fwrite(A). /.gitok > B = "~/.git". > io:fwrite(B). **
我发现当我尝试写入一些大数据时 fwrite 失败,如下面的代码所示。 #include #include int main(int argc, char* argv[]) { int s
我正在写这个: $fh = fopen('public/newsletter.txt', 'w'); foreach($entries as $row) { fwrite($fh,
我又来了,这次有一个 PHP 问题...我正忙于制作某种管理面板(非常基本),但是当我试图像我的 slider 或其他东西一样进行更改时,fwrite 会覆盖所有内容。这是我的 PHP 代码: 0)
根据fwrite的手册页: fread() and fwrite() return the number of items successfully read or written (i.e., no
我只是想对一组数字进行排序(虽然我发布的代码不是我要使用的方法,但我确实需要将代码中的输出写入二进制文件). 一切正常,除了“ordenar”的最后一次迭代:当我在订购后再次打印回数字时,除了最后一行
我想使用 data.table::fwrite 以文本日志的形式快速存储和检索状态。这些是通过移动应用程序更新的,该应用程序使用管道工 API 调用到 R 端点。移动应用程序每秒可能会触发许多 API
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 5 年前。 Improve th
我正在尝试使用“fwrite”并制作 snd 文件。我想做 IIR 滤波器。我制作了一个 FIR 滤波器,并使用 IIR 滤波器的代码。(当然,改变系数)但我认为“fwrite”不起作用。因为IIR滤
我正在尝试将 wchar 数组写入 C 中的文件,但是存在某种损坏和不相关的数据,例如这样的变量和路径 c.:.\.p.r.o.g.r.a.m. .f.i.l.e.s.\.m.i.c.r.o.s.o.
我是一名优秀的程序员,十分优秀!