2010-01-21 2 views
2

У меня есть * ushort, который указывает на массив размеров x * y из 16-битных значений, я хотел бы иметь возможность написать это на диск без копирования в управляемое пространство, возможно ли это?Использование небезопасного C#, чтобы взять указатель на массив ushort и записать его на диск (создать файл)

+0

Необходимо предоставить более подробную информацию. Как и почему у вас есть небезопасная структура данных. Если вы написали исходный код. Что вы уже пробовали и т. Д. –

+0

Это массив изображений беззнаковых 16-битных целых чисел. Он создается из dll C++, с которым я взаимодействую. Есть функция, которая вернет массив указателей на каждый кадр, мне нужно будет записать кадр в виде файла. Часто это происходит очень быстро, несколько раз в секунду, поэтому скорость важна. Это мой первый раз здесь, так что прощайте недостаток деталей, со временем я сойду с ума. – GMAN

+0

Вы уверены, что копирование из неуправляемой в управляемую память будет узким местом вашего приложения? Жесткие диски по-прежнему являются величинами медленнее, чем оперативная память, т. Е. Моя догадка заключается в том, что ваше приложение будет тратить больше времени на ожидание оборудования, чем на копирование некоторых байтов в памяти. – dtb

ответ

0

Вы можете использовать WriteFileusing P/Invoke, но зачем делать простые сложные?


Простое решение будет копировать кадры в управляемой памяти, используя, например, Marshal.Copy, а затем записать его в файл с FileStream.

+0

Сначала попробую простой метод. Вы случайно знаете какие-либо фрагменты кода, которые бы отображали основы? – GMAN

+0

Кажется, что Marshal.Copy не работает для Unsigned типов? Есть ли обходное решение для нас? – GMAN

+0

Вместо этого используйте 'short'. Биты одинаковы. – dtb

4

Попробуйте это - я создал метод расширения для Stream, который напишет указатель на шорты. Он имеет недостаток в распределении и копировании памяти, а основной недостаток - огромные куски небезопасного кода. Однако он работает так, как вы ожидали. Я создал управляемый массив, а затем получил указатель на него, чтобы имитировать получение ushort * из неуправляемого кода.

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

Если вы не любите выделять и копировать, то вы можете сделать это вместо:

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++); 
    } 
} 

, который также работает, как ожидалось, но в данном случае вы добавляете накладных расходов вызов метода для каждого байта. Базовый поток потоков файловой системы, поэтому он не будет слишком большим накладным, но он все еще существует.

Не спрашивайте меня, что произойдет на процессоре большого конца (есть ли какой-либо прогон .NET?) В любом случае.

EDIT - для усмешек Я запустил FileStream через Reflector, чтобы посмотреть базовый код, и сам FileStream буферизует вызовы Write() и WriteByte(), поэтому я не вижу причин использовать что-либо, кроме версии WriteByte. Буферизация, жестко закодированная в FileStream, составляет 4K.

+0

Я пробовал ваш код сэр. В первый раз я пробую что-нибудь с небезопасным. Ошибка, которую я получаю, с ключевым словом «небезопасно», говоря: «Нельзя использовать небезопасную конструкцию в безопасном контексте» Что мне делать? – radbyx

+3

О, я нашел решение. Я должен был проверить «Разрешить небезопасный код» в свойстве проекта – radbyx

+0

, это выглядит как лучшее решение, это могут быть очень большие массивы, 1024 x 1024 x ushort x 128 frames = слишком много для перераспределения, если это не нужно. Спасибо за отличное решение – GMAN

Смежные вопросы