2009-07-08 4 views
0

Java를 사용하는 형식을 합리적으로 잘 수행 한 dat 파일에 로그 (일종의)를 쓰는 프로그램에서 이진 파일을 읽으려고합니다. 나는 그래서 그것을로드 오전 :바이너리 파일에서 자바가 아닌 원시 코드를 읽으려고 시도합니다.

DataInputStream in = new DataInputStream(new FileInputStream("file.dat")); 

System.out.println("Bytes skipped: " + in.skipBytes(4)); 

System.out.println(in.readLong()); 

문제는 readLong()의 값입니다 것은 내가 기대하고 무엇을 다른 16 진수 워크샵에서 나는 육각 블록

BF02 0000 

및 보고서를 강조 그것은 그 유효한 서명 된 짧은/긴 숫자입니다 - 그러나 출력은 내가 기대하는 것과 매우 다릅니다. 자바 문서를 살펴보면, 64 비트 (8 바이트)로 분류되는 반면, 다른 소스는 부호있는 긴 정수가 32 비트 여야한다는 것을 보여줍니다.이 문제를 해결할 방법이 있습니까?

건배, 자바

답변

3

원시 타입은 다른 언어와 플랫폼에서 다른 것을 의미합니다. (예를 들어, 일부 플랫폼에서는 32 비트, 다른 플랫폼에서는 64 비트가 흔하지는 않습니다.

처음에는 .dat 파일의 형식과 바이트 순서 (빅/리틀 엔디안)를 알아야합니다. 그런 다음 개별 바이트를 적절한 Java 유형으로 어셈블하십시오. .dat 파일에 부호가있는 32 비트 정수가 지정되면 java의 int가 적합합니다 부호없는 32 비트 정수인 경우, 자바는 부호없는 형식을 가지고 있지 않기 때문에 자바 긴 모든 가능한 값을 캡처 다음과 같이

그것을 읽어 파일의 정수 리틀 엔디안 인 경우.

0 그것은 큰 엔디안 인 경우에 123,553,

가와,

int i = (in.readByte() << 24) | (in.readByte() << 16) | (in.readByte() << 8) | (in.readByte()) 

을 (내가 기압 기억하지 않습니다. 여기에 자바의 프로모션 규칙이 있다면 & 0xff와 비트 쉬프트 전에 int를 생성해야 할 수도 있습니다) 물론 바이트 배열을 읽고 in.readByte()를 개별적으로 호출하는 대신 해당 배열을 조작 할 수 있습니다 네가 원한다면.

+1

또는 정수입니다.reverseBytes(), Long.reverseBytes(). 적어도 그들은 형식을 정하는 사람들입니다. – akarnokd

2

긴은 항상 8 바이트 (64 비트)입니다. 다른 언어와 플랫폼은 다른 용어를 사용합니다. 4 바이트를 읽으려면 int를 읽습니다.

+3

big-endian int 인 경우 ... –

0

Preon을 사용하면 이동 및 마스킹을 모두 수행 할 필요가 없습니다. 인코딩 된 데이터 구조를 반영하는 클래스에서 일부 필드를 바운드 숫자 값으로 표시하기 만하면됩니다.

class EncodedDataStructure { 

    @BoundNumber 
    private long theLong; 

} 

는 그리고 당신은 단지 4 바이트를 읽고 싶어하지만, 여전히 원하는 경우 긴 수 :

@BoundNumber(size="32") // Size is number of bits 
private long theLong; 

Or if you want to force it to be big or little endian: 

@BoundNumber(size="32", byteOrder=Endian.Big) 
private long theLong; 

... 그리고 당신은 다음과 같이 읽어 :

Codec<EncodedDataStructure> codec = Codecs.create(EncodedDataStructure.class); 
EncodedDataStructure structure = Codecs.decode(codec, file); 
1

데이터를 읽을 때 ByteBuffer를 사용하고 order() 메소드를 사용하여 바이트 순서를 변경할 수 있습니다.

관련 문제