#include "stdafx.h" #include #include #include #include #define I_H_V -1 //возможно неправильно - лучше задать прямо INVALID_HANDLE_VALUE #define MAX_PRIME 99971; HANDLE hFile;//дескриптор файлов TCHAR fileName[] = _T("MassageBox.dat"); //байтовый файл (будь готова к проверке через FAR) TCHAR fileName2[] = _T("TEST.dat"); DWORD countMessage = 0, sizeBox = 0, maxSizeBox = 0x100000; DWORD real; LONG hightPart = 0; char answer = 1; int checksum() { //получение контрольных сумм. Если суммы не совпадют - уведомление SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN);//установить указатель чтения в начало int sum = 0; ReadFile(hFile, &countMessage, 4, &real, 0);//считываются первые 4 (байта?) //и понятнее будет messageCount ReadFile(hFile, &sizeBox, 4, &real, 0); // размер сообщения - понятнее messagesSize ReadFile(hFile, &maxSizeBox, 4, &real, 0); //вместимость ящика sum += countMessage + sizeBox + maxSizeBox; TCHAR* buf = new TCHAR[256]; //256 - длина строки int sizeMessage = 0; for (int i = 0; i < countMessage; i++) { ReadFile(hFile, &sizeMessage, 4, &real, 0); //считывается размер сообщения for (int j = 0; j < sizeMessage; j++) { ReadFile(hFile, &buf[j], 2, &real, 0); sum += (int)buf[j]; } } return sum % MAX_PRIME; } int readChecksum() { int checkSum = 0; ReadFile(hFile, &countMessage, 4, &real, 0); //считать количество сообщений //Каретку в конец файла (до контрольных сумм) SetFilePointer(hFile, 12, &hightPart, FILE_BEGIN); int position = 12; //втф? лучше записать в виде произведения for (int i = 0; i < countMessage; i++) //считываются каждые сообщения { int temp = 0; ReadFile(hFile, &temp, 4, &real, 0); position += temp*2 + 4; SetFilePointer(hFile, position, &hightPart, FILE_BEGIN); //каждый раз делаем //отсчет позиции от начала файла } ReadFile(hFile, &checkSum, 4, &real, 0); //контрольные суммы записаны в конце. Читаем SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); //указатель в начало. Нафига - не знаю return checkSum; } void AddChecksum() { SetFilePointer(hFile, 0, &hightPart, FILE_END); //устанавливаем в конец int check = checksum(); //получаем контрольную сумму WriteFile(hFile, &check, 4, &real, 0); //пишем ее SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); //указатель в начало } void DeleteChecksum() { SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); ReadFile(hFile, &countMessage, 4, &real, 0); //Каретку в конец файла (до контрольных сумм) SetFilePointer(hFile, 12, &hightPart, FILE_BEGIN); //о! норм идея int position = 12; for (int i = 0; i < countMessage; i++) { int temp = 0; ReadFile(hFile, &temp, 4, &real, 0); position += temp*2 + 4; SetFilePointer(hFile, position, &hightPart, FILE_BEGIN); } TCHAR* test = _T("chechtest");//ШТА?))) //WriteFile(hFile, &test, 4, &real, 0); SetEndOfFile(hFile); SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); } void AddMessage() { DeleteChecksum(); //перед вставкой сообщения удаляем сумму TCHAR *buf = new TCHAR[255]; //длина строки лучше 256 (?) TCHAR c = 'c';//что это еще такое int i = 0; //для считывания оставшегося от предыдущего считывания '\n' TCHAR temp; scanf_s("%c", &temp, 1); //считали строку while (c != '\n') { //считываем строку до конца (могут придраться, почему не \r\n) scanf_s("%c", &c,1); buf[i] = c; i++; } //обрезаем лишний символ i--; //считали количество сообщений ReadFile(hFile, &countMessage, 4, &real, 0); //Увеличили countMessage++; //Вернули каретку в начало файла SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); //записали изменения WriteFile(hFile, &countMessage, 4, &real, 0); //считали размер ящика ReadFile(hFile, &sizeBox, 4, &real, 0); //Сместили каретку SetFilePointer(hFile, 4, &hightPart, FILE_BEGIN); //Изменили и записали изменения int mailSize = i * 2; if (mailSize + sizeBox > maxSizeBox) { SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); countMessage--; WriteFile(hFile, &countMessage, 4, &real, 0); AddChecksum(); printf("Not added because size overflow. \n"); return; } sizeBox += mailSize; WriteFile(hFile, &sizeBox, 4, &real, 0); //Каретку в конец файла (до контрольных сумм) SetFilePointer(hFile, 0, &hightPart, FILE_END); //Записали количество символов в сообщении WriteFile(hFile, &i, 4, &real, 0); //Записали текст сообщения for (int j = 0; j < i; j++) { WriteFile(hFile, &buf[j], 2, &real, 0); } AddChecksum(); //вернули каретку в начало SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); } void ReadMessage(int messageNumber) { //Считываем количество сообщений в ящике ReadFile(hFile, &countMessage, 4, &real, 0); //проверяем есть сообщение с нужным номером в ящике if (messageNumber > countMessage) { printf("Message is absent! \n"); SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); return; } //Считывание файла до нужного сообщения, включительно. Оно остается в буффере и выводится. ReadFile(hFile, &sizeBox, 4, &real, 0); ReadFile(hFile, &maxSizeBox, 4, &real, 0); TCHAR* buf = new TCHAR[256]; int sizeMessage; for (int i = 0; i < messageNumber; i++) { ReadFile(hFile, &sizeMessage, 4, &real, 0); for (int j = 0; j < sizeMessage; j++) { ReadFile(hFile, &buf[j], 2, &real, 0); } } for (int i = 0; i < sizeMessage; i++) { printf("%c", buf[i]); //всю жизнь использовали _tprintf))) } printf("\n"); SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); } void DeleteAll() { //мб дешевле будет удалить - создать. Главное дескриптор поменять. В целом норм countMessage = 0; sizeBox = 0; WriteFile(hFile, &countMessage, 4, &real, 0); WriteFile(hFile, &sizeBox, 4, &real, 0); ReadFile(hFile, &maxSizeBox, 4, &real, 0); SetEndOfFile(hFile); AddChecksum(); } void DeleteMessage(int messageNumber) { //Обновляем информацию о ящике ReadFile(hFile, &countMessage, 4, &real, 0); ReadFile(hFile, &sizeBox, 4, &real, 0); ReadFile(hFile, &maxSizeBox, 4, &real, 0); if (messageNumber > countMessage) { printf("Message is absent! \n"); SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); return; } DeleteChecksum(); //меняем количество сообщений и обновляем файл countMessage--; SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); WriteFile(hFile, &countMessage, 4, &real, 0); //Ставим pointer перед списком сообщений SetFilePointer(hFile, 12, &hightPart, FILE_BEGIN); DWORD deleteMessageSize; //Если удаляем последний элемент TCHAR* buf = new TCHAR[256]; int* numberBuf = new int[20]; int sizeMessage, deleteFilePosition, count = 0; for (int i = 0; i < countMessage + 1; i++) { //Каретка установленна перед удаляемым, запоминаем позицию if (i == messageNumber - 1) { deleteFilePosition = i * 4 + count * 2; } //Каретка установленна перед сообщением следующим за удаляемым if (i == messageNumber) { buf = new TCHAR[256]; count = 0; } //Создаем два отдальных массива: для информации о количестве символов в собщениях и символов сообщений ReadFile(hFile, &sizeMessage, 4, &real, 0); if (i == messageNumber - 1) deleteMessageSize = sizeMessage; numberBuf[i] = sizeMessage; for (int j = 0; j < sizeMessage; j++) { ReadFile(hFile, &buf[count], 2, &real, 0); count++; } } //Перемещаем каретку на начало удаляемого сообщения SetFilePointer(hFile, 12 + deleteFilePosition, &hightPart, FILE_BEGIN); count = 0; //Выводим по очереди количество символов в сообщении и само сообщение for (int i = messageNumber; i < countMessage + 1; i++) { WriteFile(hFile, &numberBuf[i], 4, &real, 0); for (int j = 0; j < numberBuf[i]; j++) { WriteFile(hFile, &buf[count], 2, &real, 0); count++; } } //Обрезаем остаток файла SetEndOfFile(hFile); SetFilePointer(hFile, 4, &hightPart, FILE_BEGIN); sizeBox = sizeBox - deleteMessageSize * 2; WriteFile(hFile, &sizeBox, 4, &real, 0); AddChecksum(); SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); } WIN32_FIND_DATAW findData; int numberOfMailBox() { HANDLE hNextFile; int i = 1; hNextFile = FindFirstFile(_T("*.dat"), &findData); //думаю можно и захардкодить названия BOOL isFileFound = FindNextFile(hNextFile, &findData); while (isFileFound) { isFileFound = FindNextFile(hNextFile, &findData); i++; } return i; } TCHAR nameBuf[256]; int main() { printf_s("Enter file name\n"); _tscanf(_T("%s"), nameBuf); hFile = CreateFile(nameBuf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS, 0, 0); if (hFile == INVALID_HANDLE_VALUE) { printf("Error"); return -1; } if (GetFileSize(hFile, 0) == 0) { WriteFile(hFile, &countMessage, 4, &real, 0); WriteFile(hFile, &sizeBox, 4, &real, 0); WriteFile(hFile, &maxSizeBox, 4, &real, 0); AddChecksum(); } SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); while (answer) { ReadFile(hFile, &countMessage, 4, &real, 0); ReadFile(hFile, &sizeBox, 4, &real, 0); ReadFile(hFile, &maxSizeBox, 4, &real, 0); SetFilePointer(hFile, 0, &hightPart, FILE_BEGIN); printf(" Count message: %d \n Size of mailbox: %d \n Max size of mailbox: %d \n", countMessage, sizeBox, maxSizeBox); printf(" A - add message \n R - read message \n I - integrity check \n D - delete message \n C - number of mailboxes \n E - exit. \n"); scanf_s("%c", &answer, 1); switch (answer) { case 'E': answer = 0; CloseHandle(hFile); break; case 'A': AddMessage(); break; case 'R': { int messageNumber; scanf_s("%d", &messageNumber, 1); ReadMessage(messageNumber); break; } case 'D': { int messageNumber; scanf_s("%d", &messageNumber, 1); if (messageNumber == 0) DeleteAll(); else DeleteMessage(messageNumber); break; } case 'I': { int chs = checksum(); int rchs=readChecksum(); rchs = readChecksum(); if (chs != rchs) { printf("The file is damaged \n"); } else { printf("The file is integral \n"); } } break; case 'C': { int i = numberOfMailBox(); printf("There are %d files\n", i); break; } } } return 0; }