Улучшить скорость разбиения файла
Я использую этот код для извлечения фрагмента из файла
// info is FileInfo object pointing to file
var percentSplit = info.Length * 50 / 100; // extract 50% of file
var bytes = new byte[percentSplit];
var fileStream = File.OpenRead(fileName);
fileStream.Read(bytes, 0, bytes.Length);
fileStream.Dispose();
File.WriteAllBytes(splitName, bytes);
Есть ли способ ускорить этот процесс?
В настоящее время для файла объемом 530 МБ требуется около 4 - 5 секунд. Может ли это время быть улучшено?
Ответы
Ответ 1
Есть несколько случаев, когда вы задаете вопрос, но ни один из них не является релевантным для языка.
Ниже следует что-то относиться к
- Что такое файловая система исходного/целевого файла?
- Вы хотите сохранить исходный исходный файл?
- Они лежат на одном диске?
В С# у вас почти нет метода, который может быть быстрее, чем File.Copy
, который внутренне вызывает CopyFile
of WINAPI
. Однако из-за того, что процент составляет пятьдесят, следующий код может быть не быстрее. Он копирует весь файл, а затем устанавливает длину целевого файла
var info=new FileInfo(fileName);
var percentSplit=info.Length*50/100; // extract 50% of file
File.Copy(info.FullName, splitName);
using(var outStream=File.OpenWrite(splitName))
outStream.SetLength(percentSplit);
Далее, если
- вы не сохраняете исходный источник после разбиения файла.
- целевой диск совпадает с исходным кодом
- вы не используете файловую систему crypto/compression enabled
тогда самое лучшее, что вы можете сделать, не копировать файлы вообще.
Например, если ваш исходный файл находится в файловой системе FAT
или FAT32
, то вы можете сделать это
- создать новую запись dir (записи) для недавно разделенных частей файла
- пусть точка (записи) записи (записей) в кластер целевой части (-ов)
- установить правильный размер файла для каждой записи
- проверьте наличие перекрестных ссылок и избегайте этого.
Если ваша файловая система была NTFS
, вам может потребоваться потратить много времени на изучение спецификации.
Удачи!
Ответ 2
var percentSplit = (int)(info.Length * 50 / 100); // extract 50% of file
var buffer = new byte[8192];
using (Stream input = File.OpenRead(info.FullName))
using (Stream output = File.OpenWrite(splitName))
{
int bytesRead = 1;
while (percentSplit > 0 && bytesRead > 0)
{
bytesRead = input.Read(buffer, 0, Math.Min(percentSplit, buffer.Length));
output.Write(buffer, 0, bytesRead);
percentSplit -= bytesRead;
}
output.Flush();
}
Флеш может не понадобиться, но это не повредит, это было довольно интересно, изменив цикл на пока-то, а не на время сильно поразив производительность. Я полагаю, что ИЛ не так быстро. Мой компьютер запускал исходный код через 4-6 секунд, вложенный код, казалось, работал примерно через 1 секунду.
Ответ 3
Я получаю лучшие результаты при чтении/записи кусками в несколько мегабайт. Производительность изменяется также в зависимости от размера куска.
FileInfo info = new FileInfo(@"C:\source.bin");
FileStream f = File.OpenRead(info.FullName);
BinaryReader br = new BinaryReader(f);
FileStream t = File.OpenWrite(@"C:\split.bin");
BinaryWriter bw = new BinaryWriter(t);
long count = 0;
long split = info.Length * 50 / 100;
long chunk = 8000000;
DateTime start = DateTime.Now;
while (count < split)
{
if (count + chunk > split)
{
chunk = split - count;
}
bw.Write(br.ReadBytes((int)chunk));
count += chunk;
}
Console.WriteLine(DateTime.Now - start);
Ответ 4
Я думаю, что самый быстрый способ обойти эту проблему - через двоичный буферный ввод файла.
Я не очень хорошо знаком с С#, но вы можете изучить некоторые методы буферизации для перехода к определенной части файла и делать буферизованный ввод из этой части.
Вы также можете прибегнуть к использованию С++ с Windows API для собственных методов буферизации или найти библиотеки, которые имеют быстрые методы буферизации.
Я не могу предложить много другого, надеюсь, это поможет.