C#의 BinaryWriter에서 작성한 데이터를 읽기 위해 C ++의 BinaryReader가 있습니까?
-
20-09-2019 - |
문제
나는 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를 만들 때 기본적으로 작성됩니다. char
UTF-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로 작성되었습니다
- 플로트는 더 복잡합니다 : 플로트 값을 가져 와서 해석하여 메모리 주소의 내용을 가져옵니다.