2010-05-26 5 views
5

C#을 사용하여 FORTRAN을 사용하여 만든 압축 된 바이너리 파일을 읽어야합니다. 이 파일은 (이하 "포맷되지 않은 순차 파일"섹션에서 페이지 아래로 절반 방법에 대해) 여기에 설명 된대로 "포맷되지 않은 연속"형식으로 저장됩니다구조체의 내용을 이진 파일로 구문 분석

http://www.tacc.utexas.edu/services/userguides/intel8/fc/f_ug1/pggfmsp.htm

당신은 URL에서 볼 수 있듯이, 파일은 130 바이트 이하의 "덩어리"로 구성되며 각 덩어리를 감싸는 2 길이 바이트 (FORTRAN 컴파일러에 의해 삽입 됨)를 포함합니다.

그래서 컴파일러가 삽입 한 형식에서 실제 파일 페이로드를 구문 분석하는 효율적인 방법을 찾아야합니다.

파일에서 실제 페이로드를 추출한 후에 다양한 데이터 유형으로 파싱해야합니다. 그것은 다음 운동이 될 것입니다.

내 첫 번째 생각은 File.ReadAllBytes을 사용하여 전체 파일을 바이트 배열로 스터핑하는 것입니다. 그런 다음 형식을 건너 뛰고 실제 데이터를 두 번째 바이트 배열로 전송하여 바이트를 반복합니다.

결국 두 번째 바이트 배열에는 실제 파일 내용에서 모든 형식 지정을 뺀 값이 있어야합니다. 그런 다음 필요한 형식을 얻으려면 다시 돌아가야합니다.

저는 C#을 처음 접했을 때이 점에 대해 더 잘 받아 들일 수있는 방법이있을 것이라고 생각했습니다.

또한, 그것은 도움이 경우, 이러한 파일 (30메가바이트 말), 가장하지만 ...이 기록에 의해 기록처럼 파일을 읽을 수있는

답변

1

한 가지 방법 훨씬 작은 것 상당히 큰 수 (예를 들어, 읽기 length 바이트 다음에 데이터 청크, 바이트 배열 인 레코드 목록 작성). 그런 다음 레코드 모음이 추가 구문 분석 루틴으로 전달됩니다.

그러나 4.0 이상인 경우 파일 매핑에 new class이 있는데 이는 더 효율적이지만 ReadAllBytes과 유사하게 작동합니다.

ReadAllBytes 또는 MemoryMappedFile을 사용하는 경우 모든 레코드 길이를 먼저 구문 분석하여 큰 이진 파일에 메모리 "인덱스"를 만드는 것이 좋습니다. 이는 특정 레코드 만 필요할 경우 특히 유용합니다.

+0

감사합니다. 귀하의 의견을 바탕으로, 나는 바이트 배열에 내 파일을로드하고 두 번째 깨끗한 바이트 배열 (길이 마커가없는)을 생성하는 몇 가지 코드를 작성했습니다.나는 지금 그것을 BitConverter를 사용하여 다양한 스칼라 값으로 파싱하려고 시도하고 있는데, 변환 할 때 배열에 자체 포인터를 유지해야하기 때문에 약간 추한 것처럼 보인다. 바이트 배열을 계속한다고 가정하면 거기에서 다양한 스칼라를 가져 오는 더 좋은 방법이 있을까요? 아, 4.0을 사용하지 않습니다 ... –

+0

바이트 배열을'MemoryStream'으로 랩핑하고'BinaryReader'를 사용할 수 있습니다. 'BinaryReader'는 자신의 위치를 ​​기억하므로 필요하지 않습니다. –

0

바이트를 반복하는 대신 System.IO.BinaryReader을 살펴보십시오. 파일을 FileStream으로 열고 BinaryReader에 랩핑하면 스트림 포인터가 blob 로의 오프셋을 추적하는 기본 유형을 직접 읽을 수 있습니다. 엔디안과 사용자 정의 유형을 직접 고려해야 할 수도 있습니다. 어쩌면 개별 바이트를 읽는 방법 위에 BinaryReader에 대한 확장 메소드를 직접 구축해야 할 수도 있습니다.

바이트 배열의 데이터가 필요한 경우 MemoryStream에 배열을 래핑하는 경우에도 BinaryReader을 계속 사용할 수 있습니다.

파일이 크면 나는 File.ReadAllBytes을 알 수 있습니다. FileStream은 버퍼링해야하며, 메모리 매핑 된 파일 사용에 대한 Stephen의 제안은 특히 포맷팅을 위해 두 번째 패스를 만들어야 할 경우 더욱 정교한 (더 효율적일 수 있습니다) 대안처럼 들립니다.

+0

감사합니다. 내가 이것을 BinaryReader와 직접적으로 처리 할 때 보게되는 문제는 데이터가 길이 마커로 오염되었다는 것입니다 (원래 게시물의 URL에 요약되어 있음). 따라서 길이 마커가 스트림 포인터를 따라 이동하므로 기본 요소를 간단히 읽을 수 없습니다. 그 때문에 길이 마커의 데이터를 먼저 스크럽하고 두 번째 단계에서 처리하는 것이 더 깨끗해 보입니다. 그러나, 그것은 전체 것을 메모리에 먼저 저주하는 것을 의미합니다. 길이 표시를 없애고 BinaryReader를 한 번에 사용할 수있는 쉬운 방법이 있습니까? –

+0

아, 알겠습니다. 자 이제 BitConverter를 사용하지 않고 코드없는 데이터를 생성하는 코드를 만들었으므로 배열 포인터 문제를 처리하는 각 배열에서 MemoryStream을 생성 할 수 있습니다 (MemoryStream에는 자체 배열을 배치하는 대신 기존 배열을 래핑하는 생성자가 있음) . 그런 다음 BinaryReader에서 MemoryStream을 래핑하십시오. – shambulator

+0

아, 지금은 유망 해 보인다. (BinaryReader에 래핑 된 MemoryStream). 내가 뭘 잘할 수 있는지 보자. 고맙습니다. –