如何在C#中快速将双精度数组写入文件?

7

我想将类似以下内容写入文件:

FileStream output = new FileStream("test.bin", FileMode.Create, FileAccess.ReadWrite);
BinaryWriter binWtr = new BinaryWriter(output);
double [] a = new double [1000000];  //this array fill complete

for(int i = 0; i < 1000000; i++)
{
    binWtr.Write(a[i]);
}

不幸的是,这段代码的处理时间非常长!(在这个例子中大约需要10秒!)

文件格式是二进制的。

我该如何让它更快?

2个回答

12
你可以把双精度数组转换成字节数组,然后一次性写入字节以加快进程。这个答案展示了如何进行转换(下面的代码来自该答案): This answer
static byte[] GetBytes(double[] values) {
    var result = new byte[values.Length * sizeof(double)];
    Buffer.BlockCopy(values, 0, result, 0, result.Length);
    return result;
}

有了字节组的数组,你就可以调用接受字节数组参数的Write方法

var byteBuf = GetBytes(a);
binWtr.Write(byteBuf);

2
或者你可以选择“不安全”模式,这样就能节省一些宝贵的计算周期 :D - leppie
1
虽然从技术上讲这是正确的,但解释为什么它更快可能会很有用。因为如果操作者需要编写4GB字节,那么这种方法肯定行不通。 - Aron
@Mick 这正是我的观点。但更深层次的问题是为什么它起作用,以及为什么你需要进行分块处理....>_< 通常为什么应该对I/O操作进行分块处理。 - Aron
@Aron 哎呀,我在你的评论中漏掉了“if”。我已经删除了我的评论。 - Roman Starkov
@Mick 确实,更一般地说,一个应该利用性能数据来解决性能问题。但是,在更少数的情况下,在几乎所有语言和情况下,I / O会增加显着的延迟,因此操作数量应保持最少。另一方面,在内存中操纵大型数据集也是低效而昂贵的。在 .net 的情况下,还需要处理 LOH 和 GC。但是当处理这些问题时,对于所有开发人员都了解这些事实很有用。从问题中可以看出,OP确实知道这一点。 - Aron
显示剩余5条评论

1
你正在一个接一个地写入字节,当然会很慢。你可以将写入操作在内存中进行,并将数组一次性写入磁盘,像这样:
var arr = new double[1000000];
using(var strm = new MemoryStream())
using (var bw = new BinaryWriter(strm)) 
{ 
    foreach(var d in arr)
    {
        bw.Write(d);
    }
    bw.Flush();
    File.WriteAllBytes("myfile.bytes",strm.ToArray());
}

这个可能不再值得两个踩了,但是由于不必要地使用了额外的内存,这并不是加速这个特定任务的好方法,所以也没有赞... - Roman Starkov
@romkyns 嗯,如果不知道问题所在,加速某些东西的方法就不多。但通常情况下,当某些事情涉及磁盘访问且速度较慢时,最好的加速方法是一次性处理所有内容,而一次性处理所有内容的唯一方法是将其全部准备好以供处理,这意味着必须为此分配内存。大多数情况下,速度与内存之间存在权衡,无法同时获得两者。 - Ronan Thibaudau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接