正在读取可能不完整的文件C++
Reading a Potentially incomplete File C++
我正在编写一个程序来重新格式化DNS日志文件,以便插入数据库。日志文件中当前写入的行可能不完整。如果是,我想丢弃它。
我开始相信eof
函数可能非常适合我的应用程序,但我注意到很多程序员都不赞成使用eof
函数。我还注意到feof
函数似乎非常相似。
如果你们能提供关于这些功能副作用的任何建议/解释,我们将不胜感激,对于更合适的方法的任何建议也将不胜感激!
编辑:我当前正在使用istream::peek
函数跳过最后一行,无论它是否完整。虽然可以接受,但最好是确定最后一行是否完整的解决方案。
我使用的具体比较是:logFile.peek() != EOF
我会考虑使用
int fseek ( FILE * stream, long int offset, int origin );
带SEEK_END
然后
long int ftell ( FILE * stream );
以确定文件中的字节数,从而确定文件的结束位置。我发现这在检测文件末尾(以字节为单位)时更可靠。
你能在文件的最后两三个字节中检测到(记录结束/行)EOR标记(可能是CRLF)吗?(3个字节可能用于CRLF^Z…取决于文件类型)。这将验证您是否有完整的最后一行
fseek (stream, -2,SEEK_END);
fread (2 bytes... etc
如果你试图用独占锁打开文件,你可以检测到(通过打开失败)文件正在使用中,然后再试一次。。。(或任何时候)
如果您需要在编写文件时捕获文件内容,那么如果您在逻辑和文件中实际数据字节之间消除尽可能多的间接和缓冲层,则会容易得多。
不要使用任何类型的C++IO流-您无法真正控制它们。不要使用基于FILE *
的函数,如fopen()
和fread()
,它们是缓冲的,即使禁用缓冲,代码和数据之间也有代码层,而这些代码层又一次无法控制,也不知道发生了什么。
在POSIX环境中,可以使用低级C样式的open()
和read()
/pread()
调用。使用fstat()
可以知道文件内容何时发生了更改——您将看到struct stat
参数的st_size
成员在调用fstat()
后发生了更改。
你可以这样打开文件:
int logFileFD = open( "/some/file/name.log", O_RDONLY );
在一个循环中,你可以做这样的事情(省略错误检查和实际数据处理):
size_t lastSize = 0;
while ( !done )
{
struct stat statBuf;
fstat( logFileFD, &statBuf );
if ( statBuf.st_size == lastSize )
{
sleep( 1 ); // or however long you want
continue; // go to next loop iteration
}
// process new data - might need to keep some of the old data
// around to handle lines that cross boundaries
processNewContents( logFileFD, lastSize, statBuf.st_size );
}
processNewContents()
可能看起来像这样:
void processNewContents( int fd, size_t start, size_t end )
{
static char oldData[ BUFSIZE ];
static char newData[ BUFSIZE ];
// assumes amount of data will fit in newData...
ssize_t bytesRead = pread( fd, newData, start, end - start );
// process the data that was read read here
return;
}
您还可能会发现,您需要向close()
添加一些代码,然后重新创建文件open()
,以防您的应用程序似乎没有"看到"写入文件的数据。我在一些系统上看到过这种情况——应用程序不知何故在某个地方看到了文件大小的缓存副本,而在另一个上下文中运行的ls
则获得了更准确、更新的大小。例如,如果您知道日志文件每10-15秒写入一次,如果您在30秒内没有看到文件的任何更改,请尝试重新打开该文件。
您还可以跟踪struct stat
结果中的inode编号,以捕获日志文件旋转。
在非POSIX环境中,您可以用低级别的等效操作系统替换open()
、fstat()
和pread()
调用,尽管Windows提供了您所需的大部分功能。在Windows上,lseek()
和read()
将取代pread()
。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 如何确定我已使用非编码文件到达 EOF?
- 命名空间中具有.h和.cpp文件的类
- 如何使用ndk-build.cmd构建Android.so文件
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 读取文件并输入到矢量中
- 在C++中查找文件
- c++库的公共头文件中应该包含什么
- 用c++从输入文件中读取另一行
- Cppcheck生成xml转储文件
- 读取文件的最后一行并输入到链接列表时出错
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 如何将内容数组写入文本文件?
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到