我应该使用什么c++ Write函数
What C++ Write function should I use?
我不喜欢使用XML库解析器,所以你能给我建议用哪个好的写函数来写数据到XML文件吗?我将对write函数进行大量的调用,因此write函数应该能够跟踪最后的写入位置,并且它不应该占用太多资源。我在下面有两个不同的写入,但我不能跟踪最后一个写入位置,除非我必须读取文件直到文件结束。
案例# 1
FILE *pfile = _tfopen(GetFileNameXML(), _T("w"));
if(pfile)
{
_fputts(TEXT(""), pfile);
}
if(pfile)
{
fclose(pfile);
pfile = NULL;
}
案例# 2
HANDLE hFile = CreateFile(GetFileNameXML(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
WriteFile(hFile,,,,,);
}
CloseHandle(hFile);
谢谢。
如果您所需要的只是编写一些文本文件,请使用c++的标准库文件工具。下面的示例很有帮助:http://www.cplusplus.com/doc/tutorial/files/
首先,您不喜欢使用标准XML处理库的原因是什么?
接下来,如果你决定自己开发,绝对不要直接使用Win32 api——至少除非你要把生成的XML大块大块地写出来,或者你要实现你自己的缓冲层。
对于处理小文件来说,这并不重要,但是您特别提到了良好的性能和对write函数的多次调用。WriteFile有相当多的开销,它做了很多工作,并且涉及到用户->内核->用户模式切换,这是非常昂贵的。如果您处理的是"正常大小"的XML文件,您可能看不出太大的区别,但如果您生成的是超大大小的转储文件,这绝对是要记住的事情。
你提到跟踪最后一个写入位置-首先,它应该很容易…与文件缓冲区,你有ftell,与原始的Win32 API,你有SetFilePointerEx -调用它与liDistanceToMove=0
和dwMoveMethod=FILE_CURRENT
,你得到当前文件的位置后写。但你为什么需要这个?如果要输出一个XML文件,通常应该继续流式传输,直到完成写入—是否关闭并重新打开该文件?或者您正在编写一个稍后想要插入更多数据的有效XML文件?
至于Win32文件函数的开销,它可能与您的情况有关,也可能与您的情况无关(取决于您正在处理的文件的大小),但是对于较大的文件,它非常重要-下面包含的是一个微基准测试,它使用ReadFile简单地将文件读入内存,允许您从命令行指定不同的缓冲区大小。在运行该工具时,查看Process Explorer的IO选项卡会很有趣。以下是我的小笔记本电脑(Win7-SP1 x64, core2duo P7350@2.0GHz, 4GB ram, 120GB Intel-320 SSD)的一些统计数据。
就当它是一个微基准吧。在您的特定情况下,性能可能很重要,也可能不重要,但我相信这些数字表明Win32文件api有相当大的开销,并且您自己做一点缓冲是有帮助的。
使用完全缓存的2GB文件:
<>之前BlkSz速度32 14.4 mb/s64年28.6 mb/s128 56 mb/s256 107 mb/s512 205 mb/s1024 350 mb/s4096 800 mb/s32768 ~ 2 gb/s之前使用"so big there will only be cache misses" 4GB文件:
<>之前BlkSz速度CPU32 13MB/s 49%64 26MB/s 49%128 52MB/s 49%25699mb/s 49%512 180MB/s 49%1024 200MB/s 32%4096 185MB/s 22%32768 205MB/s 13%之前请记住,49%的CPU使用率意味着一个CPU核心几乎完全固定-单个线程不能真正使机器更加困难。请注意第二个表中4kb缓冲区的异常行为——它是可重复的,我对此没有任何解释。
蹩脚的微基准代码在这里:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <string>
#include <assert.h>
unsigned getDuration(FILETIME& timeStart, FILETIME& timeEnd)
{
// duration is in 100-nanoseconds, we want milliseconds
// 1 millisecond = 1000 microseconds = 1000000 nanoseconds
LARGE_INTEGER ts, te, res;
ts.HighPart = timeStart.dwHighDateTime; ts.LowPart = timeStart.dwLowDateTime;
te.HighPart = timeEnd.dwHighDateTime; te.LowPart = timeEnd.dwLowDateTime;
res.QuadPart = ((te.QuadPart - ts.QuadPart) / 10000);
assert(res.QuadPart < UINT_MAX);
return res.QuadPart;
}
int main(int argc, char* argv[])
{
if(argc < 2) {
puts("Syntax: ReadFile [filename] [blocksize]");
return 0;
}
char *filename= argv[1];
int blockSize = atoi(argv[2]);
if(blockSize < 1) {
puts("Please specify a blocksize larger than 0");
return 1;
}
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
if(INVALID_HANDLE_VALUE == hFile) {
puts("error opening input file");
return 1;
}
std::vector<char> buffer(blockSize);
LARGE_INTEGER fileSize;
if(!GetFileSizeEx(hFile, &fileSize)) {
puts("Failed getting file size.");
return 1;
}
std::cout << "File size " << fileSize.QuadPart << ", that's " << (fileSize.QuadPart / blockSize) <<
" blocks of " << blockSize << " bytes - reading..." << std::endl;
FILETIME dummy, kernelStart, userStart;
GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &kernelStart, &userStart);
DWORD ticks = GetTickCount();
DWORD bytesRead = 0;
do {
if(!ReadFile(hFile, &buffer[0], blockSize, &bytesRead, 0)) {
puts("Error calling ReadFile");
return 1;
}
} while(bytesRead == blockSize);
ticks = GetTickCount() - ticks;
FILETIME kernelEnd, userEnd;
GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &kernelEnd, &userEnd);
CloseHandle(hFile);
std::cout << "Reading with " << blockSize << " sized blocks took " << ticks << "ms, spending " <<
getDuration(kernelStart, kernelEnd) << "ms in kernel and " <<
getDuration(userStart, userEnd) << "ms in user mode. Hit enter to countinue." << std::endl;
std::string dummyString;
std::cin >> dummyString;
return 0;
}
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- BLE gattServer.write()重载函数
- 使用 insertion(<<) 运算符和 "write" 函数在 C++ 中显示数据有什么区别?
- 如何使用write()函数将结构写入文件
- 没有匹配函数来调用"std::basic_ofstream<char>::write(std::string*, long long unsigned int)"
- 仅在我退出应用程序后,使用Cout.write()函数在控制台上打印字符串
- 为什么即使对于 "copy on write" 的 const 成员函数也返回一个代理类?
- 瓦尔格林德给出"Invalid write of size 8"空析构函数
- 为什么在 C++ 的 write() 函数中使用 (char *)
- 在Linux上使用C/C++中的write()函数通过UART Beaglebone Black写入70kB
- 像 read() 、write() 这样的函数调用在 Linux 中是实际的系统调用吗?
- 当发生错误(拒绝访问)时调用Curl-headerfunction和write函数
- 我应该使用什么c++ Write函数
- 为什么使用write函数而不是整数将奇怪的符号写入二进制文件
- 为什么函数'x'.write(frame)对我不起作用?
- 等效于 VB DLL 函数声明的 C# 返回并返回'Attempted to read or write protected memory'错误
- 没有匹配的函数调用 std::basic_ofstream<char>::write()