원시 바이너리 구조를 D의 파일에 작성합니까?

Aug 19 2020

일부 .NET에서 정의 된 여러 이진 레코드가 포함 된 이진 파일을 만들려고합니다 struct. 그러나 나는 그것을하는 방법을 찾지 못하는 것 같습니다. 다른 예를 살펴보면 string문제없이 s 를 작성할 수 있었지만 struct. 에서 C와 같이 작성하고 fwrite(3)싶지만 D버전 2 에서는 작성하고 싶습니다 .

지금까지 시도한 내용은 다음과 같습니다.

  • 사용하는 stream.write(tr)- 사람이 읽을 수 / 디버그 표현을 쓴다
  • 사용 stream.rawWrite(tr)-이것은 내가 필요한 것처럼 들리지만 다음으로 컴파일하지 못했습니다.

오류 : std.stdio.File.rawWrite 템플릿은 인수 유형! () (TitleRecord)에서 함수를 추론 할 수 없습니다. 후보는 다음과 같습니다.

/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d(1132) : std.stdio.File.rawWrite (T) (T [] 버퍼에서)

  • rawWrite위와 같이 시도 하지만 데이터를 다양한 것으로 캐스팅하면 컴파일되지 않습니다.
  • 심지어 다시 얻으려고 노력 C으로 fwrite하지만, 파일 기술자 I의 필요성을 얻기 위해 깊은 충분히 얻을 수 없습니다.

문서 를 읽는 것은 그다지 도움이되지 않았습니다 (문자열 쓰기는 저에게도 효과가 있지만 작성하지는 않습니다 struct). 나는 그것을 할 수있는 간단한 방법이있을 것이라고 확신한다. 그러나 나는 그것을 찾을 수 없다 .... 다른 SO 질문 은 나를 돕지 않았다 . 나 D 1.0, 그것은 함께 달성되었을 수도 stream.writeExact(&tr, tr.sizeof)있지만 더 이상 선택 사항이 아닙니다.

import std.stdio;

struct TitleRecord {
        short id;
        char[49] text;
};

TitleRecord tr;

void main()
{
 auto stream = File("filename.dat","wb+");
 tr.id = 1234;
 tr.text = "hello world";
 writeln(tr);
 //stream.write(tr);
 //stream.rawWrite(tr);
 //stream.rawWrite(cast(ubyte[52]) tr);
 //stream.rawWrite(cast(ubyte[]) tr);
 //fwrite(&tr, 4, 1, stream);
}

답변

2 AdamD.Ruppe Aug 19 2020 at 21:40

이를 위해 그 오류는 구조체가 아닌 배열이 필요하다는 것을 의미합니다. 따라서이를 수행하는 한 가지 쉬운 방법은 포인터를 슬라이스하여 rawWrite에 제공하는 것입니다.

stream.rawWrite((&tr)[0 .. 1]);

(&tr)따라서 포인터로 구조체를 변환, 주소를 가져옵니다. 그런 다음 [0 .. 1]수단은 처음부터 하나의 요소 만 잡아서 조각을 얻습니다.

따라서 이제 T[]rawWrite가 하나의 요소를 포함하여 처리 할 수 ​​있습니다.

@safe주석 을 사용하는 경우 통과하지 못할 경우 표시해야합니다 @trusted. 또한 물론 stringC 경험에서 확실히 알고 있듯이 구조체 내부의 모든 참조 (포함 )는 데이터 대신 이진 포인터로 작성됩니다. 그러나 당신이 거기에서 보여준 경우 당신은 괜찮습니다.

편집 : BTW fwrite원하는 경우 C에서 동일한 코드를 복사 / 붙여 넣기하여 사용할 수도 있습니다 ( foo.sizeof대신 대신 sizeof foo). D File는 C를 둘러싼 작은 래퍼 FILE*이며 원래 FILE *을 다시 가져 와서 다른 함수로 전달할 수 있습니다.stream.getFP() http://dpldocs.info/experimental-docs/std.stdio.File.getFP.html )

1 LászlóSzerémi Aug 19 2020 at 23:55

rawWrite 배열이 필요하지만 많은 해결 방법이 있습니다.

하나는 단일 요소 배열을 만드는 것입니다.

file.rawWrite([myStruct]);

또 다른 하나는 구조체를 배열로 캐스팅하는 것입니다. 내 라이브러리 인 bitleveld에는 reinterpretAsArray. 이것은 또한 상기 구조체의 체크섬을 쉽게 생성 할 수 있도록합니다.

가끔이 방법을 사용하는 정렬에 문제가 발생 했으므로 조심하십시오. align구조체 의 속성을 변경하여 수정할 수 있습니다 .