1

我有 5MB 字节 [],我以 2k 的块写入磁盘。为了获得 2k (c_writeSizeInBytes) 的卡盘,我这样做:

int numberOfIterations = bytes.Length / c_writeSizeInBytes;
                    for (int i = 0; i < numberOfIterations; i++)
                    {
                        bool nearEnd = bytes.Length - i == c_writeSizeInBytes;
                        byte[] buffer = nearEnd ? bytes.Skip(i * c_writeSizeInBytes).ToArray() : bytes.Skip(i * c_writeSizeInBytes).Take(c_writeSizeInBytes).ToArray();
                        binaryWriter.Write(buffer, 0, c_writeSizeInBytes);

                    }

2MB 后 5MB 文件的性能非常慢。有什么办法可以优化吗?

谢谢

4

5 回答 5

12

您在这里使用Skip//是非常低效的TakeToArray如果您必须以块的形式写入,那么您应该将偏移量传递给Write,即

binaryWriter.Write(buffer, i * CHUNK_SIZE, CHUNK_SIZE);

(也许Math.Min在最后的块中使用一些来获取剩余的计数,以防它不是完整的块数)

但是,如果您已经拥有数据,则无需执行此操作byte[]- 只需调用Write.

binaryWriter.Write(buffer, 0, buffer.Length);

如果您正在编写整个文件(即此数据替换旧数据,如果有的话),那么只需使用File.WriteAllBytes.

于 2013-05-01T13:39:20.950 回答
3

啊,你那里有画家施莱米尔的情况。您的for循环涉及一次通过字节数组(通过.Skip())寻找一个元素,并且每次迭代都会在数组中走得更远,因此完成每次for循环迭代的时间越来越长,迭代次数越多你已经完成了。

既然你已经有了一个字节数组,为什么还需要一个缓冲区呢?您可以直接从现有数组写入二进制流:

int offset = 0, lastFullWriteIndex = bytes.Length - c_writeSizeInBytes;
while (offset < lastFullWriteIndex)
{
    binaryWriter.Write(bytes, offset, c_writeSizeInBytes);
    offset += c_writeSizeInBytes;
}
binaryWriter.Write(bytes, offset, bytes.Length - offset);

这不仅消除了连续遍历越来越多的数组的减慢效果,而且消除了将字节复制到缓冲区的额外工作。

于 2013-05-01T13:46:34.717 回答
3

我会这样写:

byte[] input;

using(var inStream = new MemoryStream(input))
using(var outStream = File.OpenWrite("c:\\file.dat"))
{
    inStream.CopyTo(outStream, 2048);
}
于 2013-05-01T13:39:44.343 回答
0

不知道你有什么样的约束迫使你只写 2k 块大小但是如果你一定要这样做,那么试试这个方法

  public void Write(Byte[] bytes,System.IO.Stream stream)
    {
        int chunkSize = 2 * 1024; //2k
        int offset = 0;
        do
        {
            var count = offset + chunkSize > bytes.Length ? bytes.Length - offset : chunkSize;
            stream.Write(bytes, offset, count);
            offset += count;

        } while (offset < bytes.Length);
    }
于 2013-05-01T13:47:34.407 回答
0

好的,如果您想自己动手(没有必要),这是一种方法。

const int BufferSize = 2000
for (int left = bytes.Length; left > 0; left -= BufferSize)
{
    if (left < BufferSize)
    {
        binaryWriter.Write(byte, bytes.length - left, left);
        break;
    }

    binaryWriter.Write(byte, bytes.length - left, BufferSize);
}
于 2013-05-01T13:56:35.797 回答