У меня есть веб-сервер, который будет читать большие двоичные файлы (несколько мегабайт) в байтовые массивы. Сервер может считывать несколько файлов одновременно (разные запросы страниц), поэтому я ищу наиболее оптимизированный способ сделать это без чрезмерной нагрузки на процессор. Код ниже достаточно хорош?
public byte[] FileToByteArray(string fileName)
{
byte[] buff = null;
FileStream fs = new FileStream(fileName,
FileMode.Open,
FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = new FileInfo(fileName).Length;
buff = br.ReadBytes((int) numBytes);
return buff;
}
c#
.net
bytearray
binary-data
Tony_Henrich
источник
источник
byte[] buff = File.ReadAllBytes(fileName)
.Ответы:
Просто замените все это:
Однако, если вас беспокоит потребление памяти, вам не следует читать весь файл в память сразу. Вы должны сделать это кусками.
источник
Я могу утверждать, что ответ здесь, как правило , «не». Если вам абсолютно не нужны все данные одновременно, рассмотрите возможность использования
Stream
API на основе (или некоторого варианта читателя / итератора). Это особенно важно, когда у вас есть несколько параллельных операций (как предполагает вопрос), чтобы минимизировать нагрузку на систему и максимизировать пропускную способность.Например, если вы передаете данные абоненту:
источник
byte[]
, я советую избегать использования потоков или чего-либо еще и просто использовать предоставляемый системой API.File.ReadAllBytes
.Я думаю, что это:
источник
Ваш код может быть учтен к этому (вместо File.ReadAllBytes):
Обратите внимание на Integer.MaxValue - ограничение размера файла, размещаемое методом Read. Другими словами, вы можете прочитать только блок размером 2 ГБ.
Также обратите внимание, что последний аргумент для FileStream - это размер буфера.
Я также предложил бы прочитать о FileStream и BufferedStream .
Как всегда, простой пример программы для профиля, который является самым быстрым, будет наиболее полезным.
Также ваше основное оборудование будет иметь большое влияние на производительность. Используете ли вы серверные жесткие диски с большими кэшами и карту RAID с встроенной кэш-памятью? Или вы используете стандартный диск, подключенный к порту IDE?
источник
var binaryReader = new BinaryReader(fs); fileData = binaryReader.ReadBytes((int)fs.Length);
в этомusing
заявлении. Но это по сути похоже на то, что сделал OP, просто я вырезал строку кода, приведяfs.Length
к немуint
вместо того, чтобы получитьlong
значениеFileInfo
длины и преобразовать его.В зависимости от частоты операций, размера файлов и количества просматриваемых файлов существуют и другие проблемы с производительностью, которые необходимо учитывать. Следует помнить одну вещь: каждый из ваших байтовых массивов будет освобожден во власти сборщика мусора. Если вы не кешируете какие-либо из этих данных, вы можете создать много мусора и потерять большую часть своей производительности % Time в GC, Если чанки больше 85 КБ, вы будете выделять кучу больших объектов (LOH), для освобождения которой потребуется коллекция всех поколений (это очень дорого, и на сервере остановит все выполнение во время работы). ). Кроме того, если у вас есть куча объектов в LOH, вы можете получить фрагментацию LOH (LOH никогда не уплотняется), что приводит к низкой производительности и исключениям нехватки памяти. Вы можете перезапустить процесс, как только достигнете определенной точки, но я не знаю, является ли это лучшей практикой.
Суть в том, что вы должны учитывать полный жизненный цикл своего приложения, прежде чем просто просто считать все байты в памяти самым быстрым способом, или же вы можете обменять краткосрочную производительность на общую производительность.
источник
garbage collector
,chunks
, производительность, счетчики событий , ...Я бы сказал, что
BinaryReader
все в порядке, но можно реорганизовать это вместо всех этих строк кода для получения длины буфера:Должно быть лучше, чем использовать
.ReadAllBytes()
, так как в комментариях к верхнему ответу я увидел,.ReadAllBytes()
что у одного из комментаторов были проблемы с файлами> 600 МБ, так какBinaryReader
он предназначен для такого рода вещей. Кроме того , поместив его вusing
заявлении обеспечиваетFileStream
иBinaryReader
замкнуты и утилизированы.источник
new
не было необходимости. Удалены.В случае, когда «большой файл» подразумевается за пределами 4 ГБ, тогда применима следующая моя логика написанного кода. Ключевой вопрос, на который следует обратить внимание, - это тип данных LONG, используемый с методом SEEK. Поскольку LONG способен указывать за пределы 2 ^ 32 границ данных. В этом примере код обрабатывает сначала обработку большого файла кусками по 1 ГБ, после обработки больших целых кусков по 1 ГБ обрабатываются оставшиеся (<1 ГБ) байты. Я использую этот код для расчета CRC файлов, размер которых превышает 4 ГБ. (используя https://crc32c.machinezoo.com/ для вычисления crc32c в этом примере)
источник
Используйте класс BufferedStream в C # для повышения производительности. Буфер - это блок байтов в памяти, используемый для кэширования данных, что уменьшает количество обращений к операционной системе. Буферы улучшают производительность чтения и записи.
Ниже приведен пример кода и дополнительные пояснения: http://msdn.microsoft.com/en-us/library/system.io.bufferedstream.aspx
источник
BufferedStream
когда вы читаете все это сразу?использовать этот:
источник
Обзор: если ваше изображение добавлено в качестве встроенного ресурса action =, используйте GetExecutingAssembly для извлечения ресурса jpg в поток, а затем считайте двоичные данные в потоке в байтовый массив.
источник
Я бы порекомендовал попробовать
Response.TransferFile()
метод тогдаResponse.Flush()
иResponse.End()
для обслуживания ваших больших файлов.источник
Если вы имеете дело с файлами размером более 2 ГБ, вы обнаружите, что вышеуказанные методы не работают.
Гораздо проще просто передать поток в MD5 и позволить ему разбить ваш файл на части:
источник