Пример использования функций для работы с разреженными потоками
static void ExampleSparse()
{
//Create new file. Delete the file before restart example!
FileStream FS = new FileStream(@"d:\file.fil", FileMode.CreateNew);
for (int i = 0; i < 1000; i++)
for (byte b = 0; b < 250; b++)
FS.WriteByte(b);
FS.Flush();
//Size of not compressed file
Console.WriteLine("File Size: {0}", FS.Length);
Console.WriteLine("Occupied: {0}", FS.GetLengthCompressed());
//Print first 16 bytes
Console.WriteLine();
PrintFirst16Bytes(FS);
//Zero first 8 bytes in not sparse file
FS.SetZeroData(new Range(0, 8));
PrintFirst16Bytes(FS);
//Make file sparse
FS.SetSparseAtribute(true);
//Zero first 0-64k and 128k-196k
FS.SetZeroData(new Range(0, 64 * 1024));
FS.SetZeroData(new Range(128 * 1024, 64 * 1024));
Console.WriteLine();
Console.WriteLine("Occupied after two 64k-blocks zeroed: {0}", FS.GetLengthCompressed());
PrintOccupiedRegions(FS);
//Write one byte in removed region
FS.Position = 1000;
FS.WriteByte(0);
FS.Flush();
Console.WriteLine();
Console.WriteLine("Occupied after 1 byte written (may be wrong): {0}", FS.GetLengthCompressed());
System.Threading.Thread.Sleep(1000);
Console.WriteLine("After pause: {0}", FS.GetLengthCompressed());
PrintOccupiedRegions(FS);
//Print occupied Regions
Console.WriteLine();
Console.WriteLine("Refill file");
FS.RefillZeroRegions();
PrintOccupiedRegions(FS);
FS.SetSparseAtribute(false);
FS.Close();
}
static void PrintFirst16Bytes(FileStream FS)
{
StringBuilder SB = new StringBuilder();
FS.Position = 0;
for (int i = 0; i < 16; i++)
SB.AppendFormat(" {0:x2}", FS.ReadByte());
Console.WriteLine("First 16 bytes: {0}", SB.ToString());
}
static void PrintOccupiedRegions(FileStream FS)
{
Console.WriteLine("Occupied regions:");
foreach (var R in FS.GetAllocatedRanges())
Console.WriteLine(" {0} , {1}", R.Start, R.Length);
}
Что происходит в данном примере:
- Сначала создается файл D:\file.fil размером в 250000 байт. Чтобы случайно не затереть нужный файл и не оставить атрибуты от старого файла, мы создаем принудительно новый файл. Перед каждым запуском примера Вы должны удалять созданный файл с диска.
- Затем выводится логическая длина потока и длина сжатого потока. Так как файл еще не сжат, вторая длина равна первой.
- Затем мы выводим первые 16 байт файла до и после обнуления первых восьми. Первые 8 байт стали равны 0, но размер файла не изменился.
- Затем у файла устанавливается атрибут разреженности и обнуляются два интервала по 64К: в самом начале файла и с позиции 128К. Физический размер файла при этом сократился.
- Затем мы записываем один байт в обнуленный интервал. Файловая система вынуждена опять выделить под него место и занимаемое место увеличивается на 64К. Если вызвать функцию GetLengthCompressed сразу после записи байта, она не всегда возвращает правильный размер. Это проблема WinAPI, а не данной библиотеки.
- И, наконец, мы заполняем пустые интервалы в файле и снимаем атрибут разреженности.
Значения физического размера могут зависеть от версии ОС и настроек файловой системы. На моей машине (Windows 8 64bit, с размером кластера 4К) вырезаются блоки только по 64К. Разумеется, выровнены они тоже по этой границе. При другой конфигурации значения могут быть другими, но размер блока и выравнивание не могут быть меньше размера кластера. При запуске под Windows XP этот пример завершится с ошибкой, т.к. некоторые функции появились лишь в более поздних версиях.
Общее описание работы с разреженными потоками см. в разделе Сжатые и разреженные потоки.