【问题标题】:What's the best way to write a short[] array to a file in C#?在 C# 中将 short[] 数组写入文件的最佳方法是什么?
【发布时间】:2008-10-22 02:15:40
【问题描述】:

我有一组短裤 (short[]),我需要将其写入文件。最快的方法是什么?

【问题讨论】:

  • 我刚刚意识到“短裤阵列”听起来很有趣。抱歉,这是一个真正的问题。
  • 如果你提到你想要它们的格式会有所帮助。二进制,人类可读,逗号分隔,每行一个......

标签: c# .net filestream


【解决方案1】:

使用 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);
                }
            }
        }
    }

【讨论】:

  • 这是一种更好的方法:使用 Buffer.BlockCopy 将短数组转换为字节数组,然后对其进行序列化。更快(包括转换部分)。或者直接使用 BinaryFormatter,这对于具有原始元素类型的数组来说非常快。
【解决方案2】:

按照 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);
            }
        }
    }
}

【讨论】:

    【解决方案3】:

    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 的性能相同(而且速度非常快)。如果您能以有效的方式将您的类型转换为字节数组,您可能会通过这种方式获得更快的性能。

    【讨论】:

      猜你喜欢
      • 2020-09-26
      • 2011-04-10
      • 2020-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2011-03-16
      • 1970-01-01
      相关资源
      最近更新 更多