2010-01-21 3 views
2

16 비트 값의 x * y 차원 배열을 가리키는 * ushort가 있습니다. 관리 공간에 복사하지 않고 디스크에 기록 할 수 있습니까?안전하지 않은 C#을 사용하여 ushort 배열에 대한 포인터를 가져 와서 디스크에 쓰기 (파일 만들기)

+0

자세한 내용을 입력해야합니다. 어떻게/왜 당신은 안전하지 않은 데이터 구조를 가지고 있습니다. 원래 코드를 작성한 경우 –

+0

이것은 부호없는 16 비트 int의 이미지 배열입니다. 그것은 내가 interoping하는 C + +의 DLL에서 만들어집니다. 각 프레임에 대한 포인터 배열을 반환하는 함수가 있습니다. 프레임으로 파일을 쓸 수 있어야합니다. 종종 이것은 매우 빠르게 일어나야하는데, 몇 초에 한 번 속도가 중요합니다. 이것은 처음으로 여기에서 세부 사항의 부족을 용서하고, 나는 시간이 지나면 더 좋아질 것입니다. – GMAN

+0

관리되지 않는 메모리에서 관리되는 메모리로 복사하는 것이 응용 프로그램의 병목 현상입니까? 하드 디스크 드라이브는 여전히 RAM보다 크기가 느립니다. 즉, 응용 프로그램이 메모리에서 일부 바이트를 복사하는 것보다 하드웨어를 기다리는 데 더 많은 시간을 소비 할 것으로 추측됩니다. – dtb

답변

0

WriteFileusing P/Invoke을 사용할 수 있지만, 왜 단순하게 만드나요?


간단한 해결책은 예 Marshal.Copy 대한 사용 관리 프레임 메모리에 복사 한 다음 FileStream으로 파일에 기록 될 것이다.

+0

먼저 간단한 방법을 시도해 보겠습니다. 기본을 보여줄 코드 스 니펫에 대해 알고 있습니까? – GMAN

+0

Marshal.Copy가 서명되지 않은 유형에서는 작동하지 않는 것 같습니다. Ushorts에 대한 해결 방법이 있습니까? – 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 - 미소 짓기 Reflector를 통해 Reflector를 통해 기본 코드를 살펴본 결과 FileStream 자체가 Write() 및 WriteByte() 호출을 모두 버퍼링하므로 WriteByte 버전 외에는 아무 것도 사용하지 않아도됩니다. FileStream에 하드 코딩 된 버퍼 크기는 4K입니다.

+0

나는 귀하의 코드를 시험해 보았습니다. 처음에는 안전하지 않은 것을 시도합니다. 내가 얻는 오류는 안전하지 않은 구문을 안전한 상황에서 사용할 수 없다는 '안전하지 않은'키워드입니다. 어떻게해야합니까? – radbyx

+3

오 솔루션을 찾았습니다. 나는 프로젝트의 속성에서 "안전하지 않은 코드 허용"을 확인해야했다. – radbyx

+0

가장 좋은 해결책 인 것처럼 보이지만, 1024 x 1024 x ushort x 128 프레임 = 매우 큰 배열 일 수있다. 필요하지 않다면 너무 많이 할당한다. 우수한 솔루션에 감사드립니다. – GMAN

관련 문제