C#의 BinaryWriter에서 작성한 데이터를 읽기 위해 C ++의 BinaryReader가 있습니까?

StackOverflow https://stackoverflow.com/questions/1525580

문제

나는 C#의 BinaryWriter와 함께 데이터 파일에 여러 ints, char [] s 등을 작성했습니다. BinaryReader를 사용하여 파일을 다시 읽으면 파일의 모든 부분을 완벽하게 재현 할 수 있습니다.

그러나 C ++로 다시 읽으려고하면 몇 가지 무서운 결과가 나옵니다. FSTREAM을 사용하여 데이터를 읽으려고 시도했으며 데이터가 올바르게 읽지 않았습니다. C ++에서 나는 fstream을 ios::in|ios::binary|ios::ate 그리고 내 위치를 타겟팅하기 위해 Seekg를 사용했습니다. 그런 다음 정수 "16"으로 쓰여진 다음 4 바이트를 읽습니다 (그리고 C#에 올바르게 읽습니다). 이것은 C ++에서 1244780으로 읽습니다 (메모리 주소가 아님). 왜 이렇게 될까요? C ++의 이진 리더와 동등한 것이 있습니까? 나는 MSDN에 언급 된 것을 보았지만 그것은 시각적 인 C ++이며 Intellisense는 C ++처럼 보이지 않습니다.

파일 작성에 대한 코드 (C#) :

    public static void OpenFile(string filename)
    {
        fs = new FileStream(filename, FileMode.Create);
        w = new BinaryWriter(fs);

    }

    public static void WriteHeader()
    {
        w.Write('A');
        w.Write('B');
    }

    public static byte[] RawSerialize(object structure)
    {
        Int32 size = Marshal.SizeOf(structure);
        IntPtr buffer = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(structure, buffer, true);
        byte[] data = new byte[size];
        Marshal.Copy(buffer, data, 0, size);
        Marshal.FreeHGlobal(buffer);
        return data;
    }

    public static void WriteToFile(Structures.SomeData data)
    {
        byte[] buffer = Serializer.RawSerialize(data);
        w.Write(buffer);
    }

데이터 파일을 어떻게 보여줄 수 있는지 잘 모르겠습니다.

데이터를 읽는 예 (C#)의 예 :

        BinaryReader reader = new BinaryReader(new FileStream("C://chris.dat", FileMode.Open));
        char[] a = new char[2];
        a = reader.ReadChars(2);
        Int32 numberoffiles;
        numberoffiles = reader.ReadInt32();
        Console.Write("Reading: ");
        Console.WriteLine(a);
        Console.Write("NumberOfFiles: ");
        Console.WriteLine(numberoffiles);

이것은 C ++에서 수행하고 싶습니다. 초기 시도 (첫 번째 정수에서 실패) :

 fstream fin("C://datafile.dat", ios::in|ios::binary|ios::ate);
 char *memblock = 0;
 int size;
 size = 0;
 if (fin.is_open())
 {
  size = static_cast<int>(fin.tellg());
  memblock = new char[static_cast<int>(size+1)];
  memset(memblock, 0, static_cast<int>(size + 1));

  fin.seekg(0, ios::beg);
  fin.read(memblock, size);
  fin.close();
  if(!strncmp("AB", memblock, 2)){ 
   printf("test. This works."); 
  }
  fin.seekg(2); //read the stream starting from after the second byte.
  int i;
  fin >> i;

편집 : "Seekg"에 어떤 위치를 사용하든 정확히 동일한 값을받는 것 같습니다.

도움이 되었습니까?

해결책

당신은 숯이 8 개가 아닌 C#에서 16 비트라는 것을 알고 있습니다. C#의 숯은 원시 데이터 대신 유니 코드 텍스트를 처리하도록 설계 되었기 때문입니다. 따라서 BinaryWriter를 사용하여 숯을 쓰면 원시 바이트가 아닌 유니 코드가 작성됩니다.

이로 인해 정수의 오프셋을 잘못 계산하게 만들 수 있습니다. HEX 편집기의 파일을 살펴 보는 것이 좋습니다. 파일과 코드를 게시 할 수없는 경우 여기에 코드를 작성할 수 없습니다.

edit1
C ++ 코드와 관련하여 >> 연산자를 사용하여 이진 스트림에서 읽지 마십시오. 읽으려는 int의 주소와 함께 Read ()를 사용하십시오.

int i;
fin.read((char*)&i, sizeof(int));

edit2
닫힌 스트림에서 읽는 것도 정의되지 않은 동작을 초래할 것입니다. fin.close ()를 호출 할 수없는 다음 여전히 읽을 수있을 것으로 기대합니다.

다른 팁

이것은 문제와 관련이 있거나 관련이 없지만 ...

BinaryWriter를 만들 때 기본적으로 작성됩니다. charUTF-8에서 s. 이것은 그들 중 일부가 하나의 바이트보다 길어서 당신의 추구를 버릴 수 있음을 의미합니다.

2 인용 생성자를 사용하여 인코딩을 지정하여이를 피할 수 있습니다. 인스턴스 System.Text.ASCIIEncoding 기본적으로 C/C ++를 사용하는 것과 동일합니다.

C ++ 스 니펫에는 많은 문제가 있습니다. 이진 판독 값을 형식 읽기와 혼합해서는 안됩니다.

  // The file is closed after this line. It is WRONG to read from a closed file.
  fin.close();

  if(!strncmp("AB", memblock, 2)){ 
   printf("test. This works."); 
  }

  fin.seekg(2); // You are moving the "get pointer" of a closed file
  int i;

  // Even if the file is opened, you should not mix formatted reading
  // with binary reading. ">>" is just an operator for reading formatted data.
  // In other words, it is for reading "text" and converting it to a 
  // variable of a specific data type.
  fin >> i;

도움이되면 Binarywriter가 데이터를 작성하는 방법을 살펴 보았습니다. 여기.

오랜 시간이 지났지 만 인용하고 정확하기를 바랍니다.

  • int16은 2 바이트로 작성되고 패딩됩니다.
  • INT32는 Little Endian과 Zero Padded로 작성되었습니다
  • 플로트는 더 복잡합니다 : 플로트 값을 가져 와서 해석하여 메모리 주소의 내용을 가져옵니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top