将文件转换为字节的可靠方法[]


84

我在网上找到了以下代码:

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
}

使用c#将文件转换为byte []是否足够可靠,或者有更好的方法吗?


3
您应该将fs.Close()try-finally语句的最后部分放入该代码的其余部分,以确保Close实际上已被调用。
Joren

Answers:


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

这应该够了吧。ReadAllBytes将打开文件,将其内容读取到新的字节数组中,然后关闭它。这是该方法的MSDN页面


这会导致文件锁定吗?
JL。

我的意思是-填充byte []后,文件仍不会被锁定吗?
JL。

3
不,不会-填充字节数组后立即关闭文件。
Erik Forbes

4
仅有的一个问题是,如果您有一个大文件(例如500MB或1GB等),它将为字节数组分配那么多的内存。因此,有时需要在.Read(..)周围循环并慢慢将其取出。当然,这取决于您的文件大小。:)
约书亚记

3
如果文件是由另一个进程打开的,则此操作将失败,OP方法将与FileShare.ReadWriteafter一起添加File.Read
Motes

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

要么 ...

var bytes = File.ReadAllBytes(filename) 

13
认真吗 在这种情况下,'var'是完全可以接受的-在方法的名称中明确说明了返回类型...
Erik Forbes,2009年

4
+1(最初使用)var。我个人(以及许多其他人)的个人意见是,应尽可能多地使用它。:)实际上,此问题已在此站点上讨论过多次。
Noldorin

8
也为使用var +1。我以为这个论坛是关于什么的。这当然与JL的问题无关。
查尔斯·布雷塔纳

6
我认为在投票时,您不应该考虑个人喜好。不论是否带有,这都是一个非常有效的答案var。我倾向于认为,任何需要手动和显式拼出类型的程序员都只能在太低的抽象水平上工作。它不应该不管什么确切类型的变量是,变量只什么是对。如果它存储文件中的字节,那应该很重要。并非是List还是Array或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. StreamIDisposable-您应该将FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read)初始化放在using子句中,以确保关闭文件。未能执行此操作可能意味着如果发生故障,流将保持打开状态,这将意味着文件保持锁定状态-以后可能会导致其他问题。
  2. fs.Read读取的字节可能少于您的请求。通常,实例的.Read方法Stream将读取至少一个字节,但不一定读取您要求的所有字节。您需要编写一个循环,重试读取,直到读取完所有字节。 此页面对此进行了更详细的说明。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.