Qual é a melhor maneira de escrever uma curta [] matriz para um arquivo em C #?
-
03-07-2019 - |
Pergunta
Eu tenho uma matriz de shorts (short []) que eu preciso para escrever para um arquivo. Qual é a maneira mais rápida de fazer isso?
Solução
Use o 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);
}
}
}
}
Outras dicas
Na sequência da resposta do Jon B, se o arquivo contém quaisquer outros dados, você pode querer prefixar os dados com a contagem de valores.
ou seja:.
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 é na verdade sobre 10 vezes mais rápido tanto para leituras e gravações quando usado com matrizes de tipos primitivos (obj.GetType (). IsPrimitive), ou seja, não para decimal e string (que não são primitivos) e certamente não para qualquer outra estrutura ou classe onde em vez disso é terrivelmente lento.
[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);
}
}
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
Portanto, use BinaryFormatter sempre que você tem um conjunto de um tipo primitivo, ou matriz de matrizes, mas matrizes não multi-dim (!). Se o seu tipo de dados é, por exemplo Point3 (duplo), você deve preencher um double [] e serialize que em vez. Só use BinaryWriter para tipos complexos / mistas, cordas, decimais e valores singulares.
Ao lidar com byte [], em seguida, BinaryFormatter e BinaryWriter é igualmente alto desempenho (e muito rápido). Se você pode converter o seu tipo de byte-array de uma forma eficaz, você pode obter ainda mais rápido desempenho desta forma.