如何将一个Stream复制到具有最小C#代码的字节数组?

Jad*_*ias 9 .net c# stream

到现在为止,我正在计算12个LoC.你能把它缩小吗?

using (Stream fileStream = File.OpenRead(fileName))
{
    using (BinaryReader binaryReader = new BinaryReader(fileStream))
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            byte[] buffer = new byte[256];
            int count;
            int totalBytes = 0;
            while ((count = binaryReader.Read(buffer, 0, 256)) > 0)
            {
                memoryStream.Write(buffer, 0, count);
                totalBytes += count;
            }
            memoryStream.Position = 0;
            byte[] transparentPng = new byte[totalBytes];
            memoryStream.Read(transparentPng, 0, totalBytes);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Nol*_*rin 30

有一种静态方法可以在一次调用中为您完成此操作.

var data = File.ReadAllBytes(fileName);
Run Code Online (Sandbox Code Playgroud)

或者,适用于任何Stream(返回其长度)的方法将是:

byte[] data;
using (var br = new BinaryReader(stream))
    data = br.ReadBytes((int)stream.Length);
Run Code Online (Sandbox Code Playgroud)

对于没有明确定义长度的流(例如NetworkStream),从而在调用时引发异常stream.Length,这当然不起作用.Jon Skeet的答案中提出的稍微复杂的解决方案就是您可能想要的.


Joe*_*orn 27

怎么回事:

byte[] result = File.ReadAllBytes(fileName);
Run Code Online (Sandbox Code Playgroud)

  • 虽然它只适用于文件当然...它匹配原始问题中的代码,但不匹配问题的标题:) (2认同)

Jon*_*eet 16

减少代码行在这里非常简单(同时仍然使用任意流,而不仅仅是文件):

using (Stream fileStream = File.OpenRead(fileName))
using (MemoryStream memoryStream = new MemoryStream())
{
    int byteRead;
    while ((byteRead = fileStream.ReadByte()) != -1)
    {
        memoryStream.WriteByte(byteRead);
    }
    return memoryStream.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

显然,读入缓冲区比一次读取一个字节要高效得多,但这会减少语句的数量(因为你不需要声明缓冲区和变量来保存Stream的返回值) .调用MemoryStream.ToArray()比读入新构造的数组更简单.

使用缓冲区虽然更好.请注意,我们真的不需要BinaryReader:

using (Stream fileStream = File.OpenRead(fileName))
using (MemoryStream memoryStream = new MemoryStream())
{
    byte[] buffer = new byte[8192];
    int bytesRead;
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        memoryStream.Write(buffer, 0, bytesRead);
    }
    return memoryStream.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

如果你想要真正残酷,我们可以减少using语句的数量(使用任一解决方案):

using (Stream fileStream = File.OpenRead(fileName),
              memoryStream = new MemoryStream())
{
    byte[] buffer = new byte[8192];
    int bytesRead;
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        memoryStream.Write(buffer, 0, bytesRead);
    }
    return ((MemoryStream)memoryStream).ToArray();
}
Run Code Online (Sandbox Code Playgroud)

但那只是讨厌:)

另一种选择当然是使用像MiscUtil这样的库,它有一个从流中完全读取的方法:)实用程序方法可以这样简单:

public static byte[] ReadFully(this Stream stream)
{
    using (MemoryStream memoryStream = new MemoryStream())
    {
        byte[] buffer = new byte[8192];
        int bytesRead;
        while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
        {
            memoryStream.Write(buffer, 0, bytesRead);
        }
        return memoryStream.ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这永远不会关闭流 - 调用者应该这样做.


Gar*_*ler 8

虽然没有减少LOC(我从不使用它作为主要动机),你可以像这样折叠使用:

using (Stream fileStream = File.OpenRead(fileName))
using (BinaryReader binaryReader = new BinaryReader(fileStream))
using (MemoryStream memoryStream = new MemoryStream())
{
    byte[] buffer = new byte[256];
    int count;
    int totalBytes = 0;
    while ((count = binaryReader.Read(buffer, 0, 256)) > 0)
    {
        memoryStream.Write(buffer, 0, count);
        totalBytes += count;
    }
    memoryStream.Position = 0;
    byte[] transparentPng = new byte[totalBytes];
    memoryStream.Read(transparentPng, 0, totalBytes);    
}
Run Code Online (Sandbox Code Playgroud)

  • 我试图做的(严重的)是,目标不应该是减少LOC而是增加清晰度.我会在任何一天的4行无聊的疯狂中采取30行清晰的代码. (5认同)
  • "如果有效,为什么会这么重要?" 只要您不必维护代码就没关系;-) (3认同)