[C++] 纯文本查看 复制代码
#include "stdafx.h"
#define STRING_SIZE 256
/* 文件记录结构 */
typedef struct _RECORD {
DWORD referenceCount; /* 该值为 0 时表示为空记录 */
SYSTEMTIME recordCreationTime;
SYSTEMTIME recordLastRefernceTime;
SYSTEMTIME recordUpdateTime;
TCHAR dataString[STRING_SIZE];
} RECORD;
/* 文件头部描述符 */
typedef struct _HEADER {
DWORD numRecords; /* 记录条数 */
DWORD numNonEmptyRecords; /* 非空记录条数 */
} HEADER;
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile;
LARGE_INTEGER currentPtr;
DWORD OpenOption, nXfer, recNo;
RECORD record;
TCHAR string[STRING_SIZE], command, extra;
OVERLAPPED ov = {0, 0, 0, 0, NULL}, ovZero = {0, 0, 0, 0, NULL}; /* 重叠结构 */
HEADER header = {0, 0};
SYSTEMTIME currentTime; /* 当前系统时间 */
BOOLEAN headerChange, recordChange;
int prompt = (argc <= 3) ? 1 : 0;
if (argc < 2) {
printf ("Usage: RecordAccess file [nrec [prompt]]\n");
exit (1);
}
/* 如果 nrec > 2 则创建文件,同名原文件会被删除;否则打开文件*/
OpenOption = ((argc > 2 && _ttoi(argv[2]) <= 0) || argc <= 2) ? OPEN_EXISTING : CREATE_ALWAYS;
hFile = CreateFile (argv[1], GENERIC_READ | GENERIC_WRITE, 0, NULL, OpenOption, FILE_FLAG_RANDOM_ACCESS, NULL);
if (hFile == INVALID_HANDLE_VALUE)
printf ("RecordAccess Error: Cannot open existing file.\n");
if (argc >= 3 && _ttoi(argv[2]) > 0) {
if(!DeviceIoControl (hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &nXfer, NULL)) /*将文件设置为稀疏文件*/
printf ("RecordAccess Error: Making new file sparse.\n");
header.numRecords = _ttoi(argv[2]); /*命令行中给出记录条数*/
if (!WriteFile(hFile, &header, sizeof (header), &nXfer, &ovZero)) /* 写入文件头 */
printf ("RecordAccess Error: WriteFile header.\n");
currentPtr.QuadPart = (LONGLONG)sizeof(RECORD) * _ttoi(argv[2]) + sizeof(HEADER); /* 到文件末尾(文件头 + 记录信息) */
if (!SetFilePointerEx (hFile, currentPtr, NULL, FILE_BEGIN)) /* 移动文件指针到文件尾 */
printf("RecordAccess Error: Set Pointer.\n");
if (!SetEndOfFile(hFile)) /* 设置文件末尾 */
printf ("RecordAccess Error: Set End of File.\n");
if (prompt) /* 打印提示信息 */
printf ("Empty file with %d records created.\n", header.numRecords);
return 0;
}
/* 检查文件头以查看总的记录条数与非空记录条数 */
if (!ReadFile(hFile, &header, sizeof (HEADER), &nXfer, &ovZero))
printf("RecordAccess Error: ReadFile header.\n");
if (prompt)
_tprintf (_T("File %s contains %d non-empty records of size %d.\n Total capacity: %d\n"),
argv[1], header.numNonEmptyRecords, sizeof(RECORD), header.numRecords);
while (TRUE) {
headerChange = FALSE; recordChange = FALSE;
/* 操作提示(读,写,删除,退出) */
if (prompt)
printf ("Enter r(ead)/w(rite)/d(elete)/qu(it) record#\n");
_tscanf (_T("%c%u%c"), &command, &recNo, &extra);
if (command == _T('q'))
break;
if (recNo >= header.numRecords) { /* 指定的记录条数太大 */
if (prompt)
printf ("record Number is too large. Try again.\n");
continue;
}
currentPtr.QuadPart = (LONGLONG)recNo * sizeof(RECORD) + sizeof(HEADER); /* 定位到指定的记录处 */
ov.Offset = currentPtr.LowPart; /* 重叠结构设置 */
ov.OffsetHigh = currentPtr.HighPart;
if (!ReadFile (hFile, &record, sizeof (RECORD), &nXfer, &ov))
printf("RecordAccess: ReadFile failure.\n");
GetSystemTime (¤tTime); /* 需要更新记录时间 */
record.recordLastRefernceTime = currentTime;
if (command == _T('r') || command == _T('d')) {
if (record.referenceCount == 0) { /* 该标志表示记录是否为空,为0时表明记录此时已经为空 */
if (prompt)
printf ("record Number %d is empty.\n", recNo);
continue;
}else {
if (prompt) {
_tprintf (_T("record Number %d. Reference Count: %d \n"), recNo, record.referenceCount);
_tprintf (_T("Data: %s\n"), record.dataString);
}
}
if (command == _T('d')) { /* 删除记录 */
record.referenceCount = 0;
header.numNonEmptyRecords--;
headerChange = TRUE;
recordChange = TRUE;
}
} else if (command == _T('w')) { /* 写记录 */
if (prompt)
printf ("Enter new data string for the record.\n");
_fgetts (string, sizeof(string), stdin); /* 不要使用 _getts() 以防缓冲区溢出 */
string[_tcslen(string)-1] = _T('\0'); /* 移除换行 */
if (record.referenceCount == 0) {
record.recordCreationTime = currentTime; /* 从没写过,则是创建时间 */
header.numNonEmptyRecords++; /* 非空记录数加 */
headerChange = TRUE; /* 头部信息需要改变 */
}
record.recordUpdateTime = currentTime; /* 之前已有过写记录,所以是更新时间*/
record.referenceCount++; /* 写入记录时增加修改次数计数值 */
_tcsncpy (record.dataString, string, STRING_SIZE-1);
recordChange = TRUE;
} else {
if (prompt)
printf ("command must be r, w, or d. Try again.\n");
}
if (recordChange && !WriteFile (hFile, &record, sizeof (RECORD), &nXfer, &ov))
printf("RecordAccess: WriteFile update failure.\n");
if (headerChange) {
if (!WriteFile (hFile, &header, sizeof (header), &nXfer, &ovZero))
printf ("RecordAccess: WriteFile update failure.\n");
}
}
if (prompt)
_tprintf (_T("Computed number of non-empty records is: %d\n"), header.numNonEmptyRecords);
if (!ReadFile(hFile, &header, sizeof (HEADER), &nXfer, &ovZero))
printf("RecordAccess Error: ReadFile header.\n");
if (prompt)
_tprintf (_T("File %s NOW contains %d non-empty records.\nTotal capacity is: %d\n"),
argv[1], header.numNonEmptyRecords, header.numRecords);
CloseHandle (hFile);
return 0;
}