2009-12-02 4 views
8

바이너리 플래그가 설정된 fstream을 사용하고 형식이 지정되지 않은 I/O 함수를 사용하여 읽고 쓰는 이진 파일을 조작하는 코드가 있습니다. 이것은 이전에 사용했던 모든 시스템에서 올바르게 작동하지만 (파일의 비트가 예상대로 정확하게 나타남) 기본적으로 모두 미국 영어입니다. 나는 다른 시스템에서 코덱으로 수정 될 가능성에 대해 궁금해했다.C++을 사용하여 이진 파일 작성 : 기본 로케일이 중요합니까?

표준 형식처럼 입/출력을 사용하면 sputc/sgetc를 사용하여 streambuf에 문자를 넣는 것과 동일하게 작동합니다. 이것들은 streambuf에서 오버플로 또는 언더 플로 기능으로 이어지며, 일부 코덱을 통과하는 것으로 보입니다 (예 : C++ 표준의 27.8.1.4.3 참조). basic_filebuf의 경우이 codecvt의 생성은 27.8.1.1.5에 명시되어있다. 결과는 basic_filebuf.getloc()이 반환하는 것에 따라 달라질 것입니다.

내 질문에, 한 시스템에서 ofstream.write를 사용하여 작성된 문자 배열은 다른 시스템에서 ifstream.read를 사용하여 그대로 사용할 수 있다고 가정 할 수 있습니다. 체계? 나는 다음과 같은 가정을 만들 것입니다 :이 프로그램은 (로케일 설정 자체 전혀 변화 즉, 프로그램이 아니다 ) 기본 로케일을 사용

  1. .
  2. 시스템은 모두 CHAR_BIT 8을 가지며 각 바이트 내에서 동일한 비트 순서를 가지며 파일을 옥텟 등으로 저장합니다.
  3. 스트림 객체에는 2 진 플래그 세트가 있습니다.
  4. 이 단계에서 endianess 차이점에 대해 걱정할 필요가 없습니다. 배열의 임의의 바이트를 멀티 바이트 값으로 해석해야하는 경우 엔디안 변환은 필요에 따라 나중에 처리됩니다. 기본 로케일은 일부 시스템 구성에 대한 수정되지 않은이 재료를 통과 보장되지 않으면

(나는, 아랍어 또는 뭔가를 알고하지 않습니다), 다음 C를 사용하여 바이너리 파일을 작성하는 가장 좋은 방법은 무엇입니까 + +?

+1

나는 당신이 당신의 가정에 동일한 바이트 순서를 추가해야한다고 생각한다. 아니면 내가 완전히 떨어져 있습니까? –

+0

@ TheScottMachine : Space_C0wb0y가 맞습니다. 가정에 동일한 바이트 순서를 추가하십시오. – Stan

+0

감사합니다. 명확한 추가 가정을 추가했습니다. – TheScottMachine

답변

0

Windows에서는 괜찮 았지만 다른 OS에서는 줄 끝 (안전과 마찬가지로)을 확인해야합니다. 기본 C/C++ 로켈은 이 아니고 시스템의 로켈에 따라 달라지는 인 "C"입니다.

이것은 보증하지 않습니다. 아시는 바와 같이 C/C++ 컴파일러와 그 대상 머신은 크게 다릅니다. 그래서 모든 가정을 지키면 문제가 생길 때까지 기다리고 있습니다. 당신이 초당 수백의 시간을 사용하려고 시도하지 않는 한, 로케일을 변경하기위한 무시할 수없는 오버 헤드가 있습니다.

+0

기본 로케일에 대한 정보는 내가 찾고있는 것입니다. 라인 엔딩은 이진 플래그가 스트림에 설정되어있는 한 중요하지 않아야한다고 생각합니다. – TheScottMachine

1

바이너리 플래그가 설정되어 있으면 작성한 모든 내용이 축 어적으로 파일에 기록됩니다. 전환이 없습니다. 바이트를 해석하는 방법은 당신 (그리고 아마도 로케일)에 달려 있습니다.

한 가지 더 : 다른 지역에서 파손 될 가능성이 있습니다. 예를 들어 데이터 원본에서 로캘에 따라 이진 데이터를 만든 경우 (이 데이터의 형식은 로캘에 따라 달라질 수 있습니다. 이는 나쁜 아이디어입니다). 다른 로케일을 사용하는 시스템에 데이터를로드 할 때 문제가 발생할 수 있습니다. 이것은 비록 설계 오류입니다.

형식/레이아웃이 동일한 표준 데이터 형식/구조를 사용하는 경우 모든 항목에서 만든 로캘에 관계없이 OK 여야합니다.

1

도움 주셔서 감사합니다. 코멘트에 맞지 않는 추가 정보를 게시하는 것이 도움이 될 것이라고 생각했습니다.

C++ 프로그램의 기본 로캘은 항상 "C"로캘 (http://www.cplusplus.com/reference/clibrary/clocale/setlocale/)입니다. 이것이 프로그램에서 사용되는 유일한 로케일 인 경우, 동작은 실행중인 시스템의 특정 로케일 구성에 의존하지 않는다는 것을 의미합니다. 또한 char에 대한 형식화되지 않은 I/O는 코드 변환을 수행하지 않는다는 것을 의미합니다 (wchar_t는 다른 이야기 일 수 있습니다). 이것은 (질문에서 가정 할 때) 읽기 및 쓰기가 바이너리 데이터를 수정하지 않고 복구 할 수 있어야한다는 것을 의미합니다.

(설명서 읽기부터) setlocale (LC_ALL, "")을 호출하여 응용 프로그램의 로캘을 전역 기본값으로 설정할 수 있습니다.이 경우 시스템 기본 로캘을 사용하는 스트림이 생성됩니다. 다시 "C"로케일로 설정하려면 setlocale (LC_ALL, "C")을 호출하면됩니다. 이는 향후에 생성되는 스트림이 사용하게 될 것을 의미합니다. stream.imbue (locale :: classic())를 호출하여 이미 생성 된 스트림에 대해 "C"로컬을 사용해야한다고 지정할 수도 있습니다.