我有一个可能更大的int
数组,正在使用BinaryWriter
写入文件。当然,我可以使用默认方法。
using (BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
{
writer.Write(myIntArray.Length);
foreach (int value in myIntArray)
writer.Write(value);
}
但这似乎效率很低。我很确定int
数组将数据连续存储在内存中。是否没有办法像使用byte
数组那样直接将内存直接写入文件?也许是一种将int
数组强制转换(而不是复制)到byte
数组的方法吗?
答案 0 :(得分:2)
我认为对上述每种方法进行基准测试是很有趣的,@ Jonathan-Wood(TestCopyStream)的原始方法,@ Mike-Zboray(TestCopySpan)的Span建议以及@ oleg-bondarenko的Buffer BlockCopy( TestCopySpanByteCopy)[是的,很难命名]。
我正在生成大小为N的随机数的整数数组,每次运行都具有相同的集合。
结果如下:
| Method | N | Mean | Error | StdDev | Median | Ratio | RatioSD | Rank | Gen 0 | Gen 1 | Gen 2 | Allocated |
|--------------------- |------ |---------:|----------:|----------:|---------:|------:|--------:|-----:|--------:|------:|------:|----------:|
| TestCopySpan | 1000 | 1.372 ms | 0.0382 ms | 0.1109 ms | 1.348 ms | 1.00 | 0.11 | 1 | - | - | - | 4984 B |
| TestCopyStream | 1000 | 1.377 ms | 0.0324 ms | 0.0935 ms | 1.364 ms | 1.00 | 0.00 | 1 | - | - | - | 4984 B |
| TestCopySpanByteCopy | 1000 | 2.215 ms | 0.0700 ms | 0.2008 ms | 2.111 ms | 1.62 | 0.19 | 2 | 3.9063 | - | - | 13424 B |
| | | | | | | | | | | | | |
| TestCopySpan | 10000 | 1.617 ms | 0.1167 ms | 0.3155 ms | 1.547 ms | 0.80 | 0.19 | 1 | - | - | - | 864 B |
| TestCopyStream | 10000 | 2.032 ms | 0.0776 ms | 0.2251 ms | 1.967 ms | 1.00 | 0.00 | 2 | - | - | - | 4984 B |
| TestCopySpanByteCopy | 10000 | 2.433 ms | 0.0703 ms | 0.2040 ms | 2.430 ms | 1.21 | 0.18 | 3 | 11.7188 | - | - | 45304 B |
答案 1 :(得分:1)
.NET Core中没有通过MemoryMarshal.Cast和Span<T>
复制的任何内容,都支持最有效的格式。这将直接重新解释内存,但是在跨平台上可能是不可移植的,因此应谨慎使用:
int[] values = { 1, 2, 3 };
using (var writer = new BinaryWriter(File.Open(path, FileMode.Create)))
{
Span<byte> bytes = MemoryMarshal.Cast<int, byte>(values.AsSpan());
writer.Write(bytes);
}
此API从MemoryExtensions.NonPortableCast
移出时的一些相关讨论
但是我会说您的原始文件实际上会相当高效,因为BinaryWriter和FileStream都有自己的内部缓冲区,在编写此类int时会使用它们。
答案 2 :(得分:0)
我不确定,但是您可以尝试myIntArray.SelectMany(BitConverter.GetBytes).ToArray()
(执行时间4700毫秒)
还有其他方法
var binFormatter = new BinaryFormatter();
var mStream = new MemoryStream();
binFormatter.Serialize(mStream, myIntArray);
mStream.ToArray();
(执行时间2700ms)
这是我发现并通过观察者探查器检查过的最快方法:执行时间1500毫秒(无3d参与者组件),其他方式约为1700毫秒(MemoryMarshal),“对于每个”方法-2700毫秒
int maxValue = Int32.MaxValue / 50;
int[] myIntArray = Enumerable.Range(0, maxValue).ToArray();
var path = "e:\\temp\\1.test";
using (BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
{
int intLength = myIntArray.Length;
writer.Write(intLength);
byte[] bytes = new byte[intLength * sizeof(int)];
Buffer.BlockCopy(myIntArray, 0, bytes, 0, sizeof(byte));
writer.Write(bytes);
}