开发者

Using unsafe C# to take a pointer to a ushort array and write it to disk (create file)

开发者 https://www.devze.com 2022-12-17 11:51 出处:网络
I have a *ushort that points to an array of dimensions x * y of 16 bit values, I would like to be able to wr开发者_如何学Goite that to disk without copying to managed space, is that possible?Try this

I have a *ushort that points to an array of dimensions x * y of 16 bit values, I would like to be able to wr开发者_如何学Goite that to disk without copying to managed space, is that possible?


Try this - I've created an extension method on Stream that will write a pointer to shorts. It has the downside of allocating and copying the memory and the major added downside of huge chunks of unsafe code. It does, however, work as you would expect. I set up a managed array and then got a pointer to it to simulate getting an ushort * from unmanaged code.

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace UnsafeWriting
{
    class Program
    {
        static void Main(string[] args)
        {
            ushort[] someArray = new ushort[20];
            for (int i = 0; i < 20; i++) { someArray[i] = (ushort)i; }

            using (FileStream stm = new FileStream("output.bin", FileMode.Create))
            {
                unsafe
                {
                    fixed (ushort* dataPtr = &someArray[0])
                    {
                        stm.Write(dataPtr, someArray.Length);
                    }
                }
            }
        }
    }

    public static class Extensions
    {
        public static unsafe void Write(this Stream stm, ushort* data, int count)
        {
            count *= 2;
            byte[] arr = new byte[count];
            Marshal.Copy(new IntPtr(data), arr, 0, count);
            stm.Write(arr, 0, count);
        }
    }
}

If you don't like the allocate and copy, then you can do this instead:

public static unsafe void Write(this Stream stm, ushort* data, int count)
{
    count *= 2;
    byte* b = (byte*)data;
    for (int i = 0; i < count; i++)
    {
        stm.WriteByte(*b++);
    }
}

which also works as expected, except in this case you're adding the overhead of a method invocation for every byte. The underlying file system streams buffer, so it won't be too much overhead, but it's still there.

Don't ask me what would happen on a big endian processor (are there any that run .NET?) in either case.

EDIT - for grins I ran FileStream through Reflector to look at the underlying code and FileStream itself buffers both the Write() and WriteByte() calls, so I see no reason to use anything but the WriteByte version. The buffersize that is hard-coded into FileStream is 4K.


You could use WriteFile using P/Invoke, but why make the simple complicated?


A simple solution would be to copy the frames to managed memory using, for example, Marshal.Copy, and then write it to a file with a FileStream.

0

精彩评论

暂无评论...
验证码 换一张
取 消