Cách đáng tin cậy để chuyển đổi tệp thành byte []


84

Tôi tìm thấy mã sau trên web:

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
}

Nó có đủ đáng tin cậy để sử dụng để chuyển đổi tệp thành byte [] trong c # không, hay có cách nào tốt hơn để thực hiện việc này?


3
Bạn nên đưa fs.Close()vào phần cuối cùng của câu lệnh try-final bao gồm phần còn lại của mã, để đảm bảo Closenó thực sự được gọi.
— Joren 30/09/09

Câu trả lời:


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

Điều đó sẽ làm các trick. ReadAllBytes mở tệp, đọc nội dung của nó vào một mảng byte mới, sau đó đóng nó. Đây là trang MSDN cho phương pháp đó.


Điều này có gây ra khóa tệp không?
— JL.

Ý tôi là - khi byte [] được điền, tệp sẽ không bị khóa?
— JL.

3
Không, nó sẽ không - tệp được đóng ngay sau khi mảng byte được điền.
— Erik Forbes

4
Chỉ có một vấn đề nhỏ với điều này là, nếu bạn có một tệp lớn (ví dụ 500MB hoặc 1GB, v.v.), nó sẽ phân bổ nhiều bộ nhớ đó cho mảng byte của bạn. Vì vậy, đôi khi nó trả tiền để lặp lại một .Read (..) và lấy nó ra từ từ. Tất nhiên, tất cả phụ thuộc vào kích thước tệp của bạn. :)
— Joshua

3
Điều này sẽ thất bại nếu tập tin được mở ra bởi quá trình khác, phương pháp OP sẽ làm việc với việc bổ sung FileShare.ReadWritesauFile.Read
— motes

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

hoặc là ...

var bytes = File.ReadAllBytes(filename) 

13
Nghiêm túc? 'var' là hoàn toàn chấp nhận được trong trường hợp này - các kiểu trả về được nêu rõ trong tên của phương pháp ...
— Erik Forbes

4
+1 cho việc sử dụng ban đầu var. Đó là ý kiến ​​cá nhân của tôi (và của nhiều người khác), rằng nó nên được sử dụng càng nhiều càng tốt. :) Trên thực tế, vấn đề đã được thảo luận nhiều lần trên trang web này.
— Noldorin 30/09/09

8
Cũng +1 để sử dụng var ... @silky, tôi đoán mọi người có thể tự do đưa ra ý kiến ​​về việc có nên sử dụng các tính năng ngôn ngữ mới khi chúng được giới thiệu hay không, nhưng từ chối câu trả lời vì nó không phù hợp với ý kiến ​​của bạn thì không những gì tôi nghĩ diễn đàn này là về. nó chắc chắn không liên quan đến câu hỏi JLs.
— Charles Bretana 30/09/09

6
Tôi nghĩ bạn nên cân nhắc nhiều hơn sở thích cá nhân khi từ chối. Đây là một câu trả lời hoàn toàn hợp lệ, có hoặc không var. Tôi có xu hướng nghĩ rằng bất kỳ lập trình viên nào cần đánh vần các kiểu theo cách thủ công và rõ ràng đều đang làm việc ở mức độ trừu tượng quá thấp. Không quan trọng loại chính xác của biến là gì, chỉ là biến đó dùng để làm gì . Nếu nó lưu trữ các byte từ tệp, thì đó mới là điều quan trọng. Không phải là Danh sách hay Mảng hoặc MyCustomContainer.
— jalf 30/09/09

8
Nếu nó varhoàn toàn phù hợp với câu trả lời thực tế, tranh luận về việc sử dụng nó sẽ có ý nghĩa. Nhưng ở đây, phần quan trọng của câu trả lời chỉ là File.ReadAllBytes(filename). Cách và nếu kết quả được lưu trữ trong một biến không liên quan như cách đặt tên của biến hoặc khoảng trắng sau =.
— jalf 30/09/09

12

Không lặp lại những gì mọi người đã nói nhưng hãy giữ lại bảng lừa đảo sau cho các thao tác trên File:

  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

Tất cả những câu trả lời với .ReadAllBytes(). Một câu hỏi khác, tương tự (tôi sẽ không nói là trùng lặp, vì họ đang cố gắng cấu trúc lại mã của họ) đã được hỏi trên SO tại đây: Cách tốt nhất để đọc một tệp lớn thành một mảng byte trong C #?

Một nhận xét đã được thực hiện trên một trong những bài đăng liên quan đến .ReadAllBytes():

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

Đối với tôi, một cách tiếp cận tốt hơn sẽ là như thế này, với 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;
}

Nhưng đó chỉ là tôi ...

Tất nhiên, tất cả điều này giả định rằng bạn có bộ nhớ để xử lý byte[]khi nó được đọc vào và tôi đã không File.Existskiểm tra để đảm bảo tệp ở đó trước khi tiếp tục, vì bạn sẽ làm điều đó trước khi gọi mã này.


1
Có một lỗi trong mã của bạn, bạn không cần phải mới trong sử dụng tuyên bố nó phải được sử dụng (FileStream fs = File.OpenRead (fileName)
— JoseR

Không có quá nhiều lỗi (tôi tin rằng mã vẫn sẽ được biên dịch) nhưng tôi đã loại bỏ nó như cũ. Nắm bắt tốt.
— vapcguy

3

trông đủ đẹp như một phiên bản chung. Bạn có thể sửa đổi nó để đáp ứng nhu cầu của mình, nếu chúng đủ cụ thể.

cũng kiểm tra các ngoại lệ và điều kiện lỗi, chẳng hạn như tệp không tồn tại hoặc không thể đọc được, v.v.

bạn cũng có thể làm như sau để tiết kiệm dung lượng:

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

2

Những người khác đã lưu ý rằng bạn có thể sử dụng cài sẵn File.ReadAllBytes. Phương pháp tích hợp sẵn là tốt, nhưng cần lưu ý rằng mã bạn đăng ở trên rất mỏng vì hai lý do:

  1. Streamlà IDisposable- bạn nên đặt phần FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read)khởi tạo trong mệnh đề using để đảm bảo tệp được đóng. Không làm được điều này có thể có nghĩa là luồng vẫn mở nếu xảy ra lỗi, điều này có nghĩa là tệp vẫn bị khóa - và điều đó có thể gây ra các sự cố khác sau này.
  2. fs.Readcó thể đọc ít byte hơn bạn yêu cầu. Nói chung, .Readphương thức của một Streamthể hiện sẽ đọc ít nhất một byte, nhưng không nhất thiết phải đọc tất cả các byte mà bạn yêu cầu. Bạn sẽ cần viết một vòng lặp để thử đọc lại cho đến khi tất cả các byte được đọc. Trang này giải thích điều này chi tiết hơn.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.