На этом шаге мы приведем функцию, осуществляющую фрагментацию составных файлов.
Одна из проблем, связанных с составными файлами, заключается в том, что, как и все диски в целом, они подвержены фрагментации. Вероятность фрагментации возникает, когда субпамять или поток заново переписываются в новое место, а старое остается вакантным. Если составные файлы фрагментируются, их следует дефрагментировать так, как дефрагментируется диск.
Существуют процедуры, дефрагментирующие составные файлы
В листинге 1 представлена процедура в псевдокоде, которая дефрагментирует составной файл. Пожалуйста, не забудьте, что вы должны включить эту процедуру в ваш код, добавив обработку всех необходимых для вашего приложения ошибок.
Листинг 1. Процедура дефрагментации составных файлов
void CompressCompoundFile(char * szFile) { // Дано: szFile содержит имя файла, который необходимо дефрагментировать. // Объявление нескольких рабочих переменных. LPSTORAGE pINew; // Указатель на интерфейс IStorage. LPSTORAGE pIOld; // Указатель на интерфейс IStorage. LPMALLOC pIMalloc; // Указатель на интерфейс IMalloc. STATSTG StorageStatus; // Структура STATSTG. HRESULT hResult; // Дескриптор результата. char szError[129]; // Участок памяти для сообщений об ошибках. //Инициализация перед работой: hResult = CoGetMalloc(MEMCTX_TASK, &pIMalloc); if (FAILED(hResult)) {// Нельзя получить дескриптор функции выделения памяти: return; } // Сначала проверим, действительно ли это составной файл: if (FAILED(StgIsStorageFile(szFile))) {// Это не составной файл! wsprintf(szError, "File %s is not a compound file.", szFile); MessageBox(szError, "Compound file compressor", MB_OK); pIMalloc->Release(); return; } // Теперь мы знаем, что имеем дело с составным файлом. // Сначала откроем новый файл для записи: hResult = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &pINew); if (FAILED(hResult)) {// Нельзя открыть новый составной файл... wsprintf(szError, "Temporary file could not be opened."); MessageBox(szError, "Compound file compressor", MB_OK); pIMalloc->Release(); return; } // Затем откроем старый файл: hResult = StgOpenDocfile(szFile, STGMREAD | STGM_DIRECT | STGM_SHARE_EXCLUSIVE, NULL, 0, &pIOld); if (FAILED(hResult)) {// Нельзя открыть настоящий составной файл... wsprintf(szError, "Original file %s could not be opened, ", szFile); MessageBox(szError, "Compound file compressor", MB_OK); pINew->Release(); pIMalloc->Release(); return; } hResult = pIOld->CopyTo(NULL, NULL, NULL, pINew); pIOld->Release(): if (FAILED(hResult)) {// Нельзя скопировать файл... wsprintf(szError, "Original file %s could not be copied.", szFile); MessageBox(szError, "Compound file compressor", MB_OK); pINew->Release(); pIMalloc->Release(); return; } // Теперь pINew - дефрагментированная копия pIOld. // Далее, скопируем его назад в pIOld: hResult = StgCreateDocfile(szFile, STGM_CREATE | STGM_WRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE, NULL, 0, &pIOld); if (FAILED(hResult)) {// Нельзя открыть заново старый составной файл. pINew->Stat(&StorageStatus, 0); pINew->Release(); wsprintf(szError, "Cannot overwrite file %s, new copy is named named", szFile, st.pwcsName); MessageBox(szError, "Compound file compressor", MB_OK); pIMalloc->Free((LPVOID) st.pwcsName); pIMalloc->Release(); return; } // Все в порядке, новый составной файл скопирован поверх старого. // Удалим теперь временный файл... pINew->CopyTo(NULL, NULL, NULL, pIOld); pIOld->Release(); pINew->Stat(&StorageStatus, 0); pINew->Release(); OpenFile(StorageStatus.pwcsName, &OpenFileStruct, OF_DELETE); pIMalloc->Free((LPVOID) st.pwcsName); pIMalloc->Release(); return; }
Предыдущий код - в действительности нечто большее, чем простая дефрагментация составного файла: это также пример выполнения операций над составным файлом.
На следующем шаге мы рассмотрим интерфейсы памяти .