【发布时间】:2008-10-22 02:15:40
【问题描述】:
我有一组短裤 (short[]),我需要将其写入文件。最快的方法是什么?
【问题讨论】:
-
我刚刚意识到“短裤阵列”听起来很有趣。抱歉,这是一个真正的问题。
-
如果你提到你想要它们的格式会有所帮助。二进制,人类可读,逗号分隔,每行一个......
标签: c# .net filestream
我有一组短裤 (short[]),我需要将其写入文件。最快的方法是什么?
【问题讨论】:
标签: c# .net filestream
使用 BinaryWriter
static void WriteShorts(short[] values, string path)
{
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
foreach (short value in values)
{
bw.Write(value);
}
}
}
}
【讨论】:
按照 Jon B 的回答,如果您的文件包含任何其他数据,您可能需要在数据前面加上值的计数。
即:
static void WriteShorts(short[] values, string path)
{
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
// Write the number of items
bw.Write(values.Length);
foreach (short value in values)
{
bw.Write(value);
}
}
}
}
【讨论】:
BinaryFormatter 实际上在与原始类型数组 (obj.GetType().IsPrimitive) 一起使用时的读取和写入速度都快 10 倍,即不适用于Decimal 和 String(它们不是原始的),当然也不适用于任何其他结构或类,因为它非常慢。
[Test]
public void TestShortArray()
{
var n = 100000000;
var input = new short[n];
var r = new Random();
for (var i = 0; i < n; i++) input[i] = (short)r.Next();
var bf = new BinaryFormatter();
var sw = new Stopwatch();
using (var ms = new MemoryStream())
{
sw.Start();
bf.Serialize(ms, input);
sw.Stop();
Console.WriteLine("BinaryFormatter serialize: " +
sw.ElapsedMilliseconds + " ms, " + ms.ToArray().Length + " bytes");
sw.Reset();
ms.Seek(0, SeekOrigin.Begin);
sw.Start();
var output = (short[])bf.Deserialize(ms);
sw.Stop();
Console.WriteLine("BinaryFormatter deserialize: " +
sw.ElapsedMilliseconds + " ms, " + ms.ToArray().Length + " bytes");
Assert.AreEqual(input, output);
}
sw.Reset();
using (var ms = new MemoryStream())
{
var bw = new BinaryWriter(ms, Encoding.UTF8, true);
sw.Start();
bw.Write(input.Length);
for (var i = 0; i < input.Length; i++) bw.Write(input[i]);
sw.Stop();
Console.WriteLine("BinaryWriter serialize: " +
sw.ElapsedMilliseconds + " ms, " + ms.ToArray().Length + " bytes");
sw.Reset();
ms.Seek(0, SeekOrigin.Begin);
var br = new BinaryReader(ms, Encoding.UTF8, true);
sw.Start();
var length = br.ReadInt32();
var output = new short[length];
for (var i = 0; i < length; i++) output[i] = br.ReadInt16();
sw.Stop();
Console.WriteLine("BinaryReader deserialize: " +
sw.ElapsedMilliseconds + " ms, " + ms.ToArray().Length + " bytes");
Assert.AreEqual(input, output);
}
}
输出:
BinaryFormatter serialize: 175 ms, 200000028 bytes
BinaryFormatter deserialize: 79 ms, 200000028 bytes
BinaryWriter serialize: 1499 ms, 200000004 bytes
BinaryReader deserialize: 1599 ms, 200000004 bytes
因此,只要您有原始类型的数组或数组数组但没有多维数组 (!),请使用 BinaryFormatter。如果您的数据类型是例如 Point3(double) 您应该填写一个 double[] 并将其序列化。仅将 BinaryWriter 用于复杂/混合类型、字符串、小数和奇异值。
在处理 byte[] 时,BinaryFormatter 和 BinaryWriter 的性能相同(而且速度非常快)。如果您能以有效的方式将您的类型转换为字节数组,您可能会通过这种方式获得更快的性能。
【讨论】: