Надежный способ конвертировать файл в байтовый []


85

Я нашел в сети следующий код:

private byte [] StreamFile(string filename)
{
   FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read);

   // Create a byte array of file stream length
   byte[] ImageData = new byte[fs.Length];

   //Read block of bytes from stream into the byte array
   fs.Read(ImageData,0,System.Convert.ToInt32(fs.Length));

   //Close the File Stream
   fs.Close();
   return ImageData; //return the byte data
}

Достаточно ли он надежен для преобразования файла в byte [] в C # или есть лучший способ сделать это?


3
Вы должны вставить fs.Close()finally-часть инструкции try-finally, которая включает в себя остальную часть кода, чтобы гарантировать, Closeчто действительно вызывается.
— Joren

Ответы:


221
byte[] bytes = System.IO.File.ReadAllBytes(filename);

Это должно делать свое дело. ReadAllBytes открывает файл, считывает его содержимое в новый массив байтов, а затем закрывает его. Вот страница MSDN для этого метода.


Это вызовет блокировку файла?
— JL.

Я имею в виду - после заполнения байта [] файл все равно не будет заблокирован?
— JL.

3
Нет, не будет - файл закрывается сразу после заполнения массива байтов.
— Эрик Форбс,

4
Единственная небольшая проблема с этим заключается в том, что если у вас большой файл (скажем, 500 МБ или 1 ГБ и т. Д.), Он выделит столько памяти для вашего байтового массива. Так что иногда стоит перебрать .Read (..) и вынуть его медленно. Конечно, все зависит от размера вашего файла. :)
— Джошуа

3
Это не удастся, если файл будет открыт другим процессом, метод OP будет работать с добавлением FileShare.ReadWriteafterFile.Read
— Motes

28
byte[] bytes = File.ReadAllBytes(filename) 

или же ...

var bytes = File.ReadAllBytes(filename) 

13
Шутки в сторону? 'var' в этом случае вполне приемлемо - тип возвращаемого значения четко указан в названии метода ...
— Эрик Форбс

4
+1 за первоначальное использование var. Мое личное мнение (и многих других), что его следует использовать как можно чаще. :) На самом деле этот вопрос уже несколько раз обсуждался на этом сайте.
— Нолдорин

8
Также +1 за использование var ... @silky, я думаю, каждый волен высказать свое мнение о том, использовать ли новые языковые функции, когда они будут представлены, но отрицать ответ, потому что он не соответствует вашему мнению, не о чем я думал этот форум. это определенно не имеет ничего общего с вопросом JL.
— Чарльз Бретана,

6
Я считаю, что при голосовании против вас следует учитывать не только личные предпочтения. Это совершенно верный ответ, с или без var. Я склонен думать, что любой программист, которому нужно вручную и явно описывать типы, работает на слишком низком уровне абстракции. Не имеет значения, какой именно тип переменной, важно только то, для чего она предназначена . Если он хранит байты из файла, то это должно быть важным. Не то, что это список, массив или MyCustomContainer.
— jalf

8
Если varбы он вообще имел отношение к фактическому ответу, споры по поводу его использования имели бы смысл. Но здесь важная часть ответа просто File.ReadAllBytes(filename). Как и если результат сохраняется в переменной, так же неважно, как ее название или пробел после =.
— jalf

12

Чтобы не повторять то, что все уже сказали, но держите под рукой следующую шпаргалку для работы с файлами:

  1. System.IO.File.ReadAllBytes(filename);
  2. File.Exists(filename)
  3. Path.Combine(folderName, resOfThePath);
  4. Path.GetFullPath(path); // converts a relative path to absolute one
  5. Path.GetExtension(path);

6

Все эти ответы с .ReadAllBytes(). Другой, похожий (я не скажу дублирующий, поскольку они пытались реорганизовать свой код) вопрос был задан здесь SO: Лучший способ прочитать большой файл в массив байтов на C #?

Был сделан комментарий к одному из постов относительно .ReadAllBytes():

File.ReadAllBytes throws OutOfMemoryException with big files (tested with 630 MB file 
and it failed) – juanjo.arana Mar 13 '13 at 1:31

Для меня лучший подход был бы примерно таким BinaryReader:

public static byte[] FileToByteArray(string fileName)
{
    byte[] fileData = null;

    using (FileStream fs = File.OpenRead(fileName)) 
    { 
        var binaryReader = new BinaryReader(fs); 
        fileData = binaryReader.ReadBytes((int)fs.Length); 
    }
    return fileData;
}

Но это только я ...

Конечно, все это предполагает, что у вас есть память для обработки, как byte[]только она будет прочитана, и я не File.Existsпроверял наличие файла перед продолжением, как вы сделали бы это перед вызовом этого кода.


1
В вашем коде есть ошибка, вам не нужно новое в выражении using, которое он должен использовать (FileStream fs = File.OpenRead (fileName)
— JoseR

Не то чтобы ошибка (я думаю, код все равно скомпилируется), но я все равно ее удалил. Хороший улов.
— vapcguy

3

выглядит достаточно хорошо как универсальная версия. Вы можете изменить его в соответствии со своими потребностями, если они достаточно конкретны.

также проверьте наличие исключений и ошибок, таких как файл не существует или не может быть прочитан и т. д.

вы также можете сделать следующее, чтобы сэкономить место:

 byte[] bytes = System.IO.File.ReadAllBytes(filename);

2

Другие отметили, что вы можете использовать встроенный File.ReadAllBytes. Встроенный метод хорош, но стоит отметить, что код, который вы публикуете выше, хрупок по двум причинам:

  1. Streamis IDisposable- вы должны поместить FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read)инициализацию в предложение using, чтобы файл был закрыт. Невыполнение этого может означать, что поток останется открытым в случае сбоя, что будет означать, что файл останется заблокированным - и это может вызвать другие проблемы позже.
  2. fs.Readможет прочитать меньше байтов, чем вы запрашиваете. В общем, .Readметод Streamэкземпляра будет читать по крайней мере один байт, но не обязательно все байты, которые вы запрашиваете. Вам нужно будет написать цикл, который повторяет попытку чтения, пока не будут прочитаны все байты. Эта страница объясняет это более подробно.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.