C#Stream写一个Uint数组

时间:2018-02-16 10:46:57

标签: c# type-conversion

我有一些数据包含锯齿状的uints数组 必须快速记录数据,因此我考虑使用stream.Write

using (var stream = File.Open(Folder + @"\"+Filename, FileMode.OpenOrCreate))
 {                 
   // uint[][] RawData = new Uint [9000][]
  foreach(uint[] LogRow in RawData)
   {
     stream.Write(LogRow, 0, 300); 
   }           
  }
}

但Stream.write只接受bytes []
可能只需获取LogRow的指针偏移量即可 然后因为a uint是32位,所以使用300 * 4的计数 并将uInt [] Logrow写为字节缓冲区?。

也许宽度不安全转换?

 int * ByteOffset = &LogRow;
//... ?? its a start 
// but it doesnt give the LogRow as Byte[] 
// not sure the best way to continou  
//

---更新说明---
此代码需要与视频数据缓冲区一起使用,因此它必须尽可能快,没有转换开销,或额外的线程,或安全检查,边界检查。在过去,人们过去常常考虑速度,因为我们的编码车间的糖果较少。今天的编码需求还有一些领域,速度仍然是“主要”的要求。这是一个问题。不要以为我通过改进我的代码的其他区域来获得更快的速度,因为你没有看到其余部分,也不是对这个主题的建设性讨论。

基本上我想要的是使用uint LogRow [],可以作为byte []而无需转换。把它想象成我不想改变的计算机内存,只需将uint []当作字节[],就可以计算偏移量和长度并将其分配给byte []数组。在c ++或汇编程序中很容易的东西,更难的是它的锯齿状的uint []数组。作为提醒,宽度VB的主要区别在于C#确实有不安全的选项,尽管使用它们是艺术。

我在下面写的一个内线是一个强制转换(C#编译器会对强制转换进行边界检查),但是我把它写下来只是表明我知道转换是什么,而且我不是在寻找转换答案,谁添加额外的说明。

byte[] objectCast = (byte[])(object)LogRow;

怎么做?

3 个答案:

答案 0 :(得分:1)

如果您想使用文件流,请尝试使用BinaryWriter,它会自动将每种类型写为字节。

答案 1 :(得分:0)

嗯,我相信这样做没有转换,它实际上使用一个结构通过字段偏移告诉编译器两个变量指向相同的偏移量,因此Ushort []成为标准的byte []变量。

虽然我认为这是解决方案,但我等待将其标记为答案,也许我将其发布在代码审核中。由于我对其他人的想法感到好奇,如果有更好的解决方案,我仍然耳目一新。 但由于我没有掉帧,所以我认为就是这样。

using System.Runtime.InteropServices   //must be on top of cs file

[StructLayout(LayoutKind.Explicit)]
 struct Converter
        {
            [FieldOffset(0)]
            public byte[] Bytes;     //warning bytes are 8 bit ! dont use
            [FieldOffset(0)]
            public ushort[] Ushorts;  //16bit
            [FieldOffset(0)]
            public char[] Chars;      //16bit
        }
 static byte[] ArrayUshort2Byte(ushort[] input)
        {

            Converter translate = new Converter();
            translate.Ushorts = input;
            return translate.Bytes;
        }

 static char[] ArrayUshort2Char(ushort[] input)
        {
            //without any buffer copying i convert types 
            //not even convert.ushort overhead no overhead here..

            Converter translate = new Converter();
            translate.Ushorts = input;
            return translate.Chars;
        }

小记, 在最初的问题中,我想从ushort到字节表示,我在'raw bytes'中考虑内存字节。然而,Ushort是2个字节而不是一个,处理宽度的streamwriter / streamreader,因此它更好地进行到char的转换(这也是像ushort一样的16bits)

它很有趣但是因为它很容易在ushort / short / char之间进行转换,只需将它们添加到结构宽度相同的偏移量即可。然后像我做宽度字节一样进行similair转换。

答案 2 :(得分:0)

我不确定这是不是你想要的。这将返回byte[]以与uint[]相同的方式对齐,但是您可以访问每个字节:

public unsafe static void Main()
{
    var data = new uint[1][];
    data[0] = new uint[100000];
    data[0][0] = 1;
    data[0][1] = 2;
    data[0][2] = 3;

    Stopwatch sw = new Stopwatch();
    sw.Start();

    foreach (uint[] LogRow in data)
    {
        fixed (uint* start = &LogRow[0])
        {
            var dataLength = LogRow.Length * sizeof(uint);
            byte[] result = new byte[dataLength];

            Marshal.Copy((IntPtr)start, result, 0, dataLength);
            // This will return 100020003000...00000......
            // Do something with result
        }
    }

    sw.Stop();

    Console.WriteLine(sw.ElapsedTicks);

    Console.ReadKey();
}

在我的机器上完成此操作需要大约700个刻度才能完成此操作。

更新

从C#7.2开始,您可以使用Span<T>来避免不安全的代码:

var jaggedData = new uint[1][];
jaggedData[0] = new uint[100000];
for (var index = 0; index < jaggedData[0].Length; index++)
{
    jaggedData[0][index] = (uint)index;
}

foreach (uint[] logRow in jaggedData)
{
    Span<byte> data = Span<uint>.DangerousCreate(logRow, ref logRow[0], logRow.Length).AsBytes();
    // Do stuff...
}

请注意,Span<T>已在堆栈上分配,因此,如果您有很多数据,那么您可能会获得StackOverflowException