2014-12-28 11 views
0

Java에서 Memory Mapped 파일로 작업하고 있습니다. 특정 매핑 된 파일 내에서 Avro 이진 인코딩 형식으로 저장된 특정 사용자 ID 데이터가 있습니다.특정 형식의 메모리 매핑 된 파일을 읽는 방법?

메모리 매핑 된 파일은 두 개의 주요 부분으로 구성됩니다. - 전체 파일 내용에 대한 색인으로 사용되는 헤더로, 특히 파일에 대한 질문에 대답하고 각 사용자의 데이터에 대한 오프셋을 파일에 제공합니다. - 본문 다음에 지정된 오프셋의 파일에있는 각 사용자의 데이터가옵니다.

헤더

version      4 bytes 
last_modified_date   8 bytes 
users      4 bytes 
shards      4 bytes 
the shards     N * 4 bytes 
num_hash_index    4 bytes 
num_chain_slots    4 bytes 
user offset/size index  num_hash_index * num_chain_slots * (8 bytes + 8 bytes + 4 bytes) 

이제 헤더는 다음과 같이 설명한다 본체 따른다.

바디

number of records     2 bytes   how many records does this user have? 
a repeated sequence of records  variable size as described below 

모든 기록은이 규격을 따르

attribute key      X bytes  a string of the users key. 
key delimiter      1 bytes  '\0' 
client id       2 bytes  some client id 
last modified time (in ms)   8 bytes  This is the last modified time for this attribute in ms. 
length of the avro binary data  2 bytes  actual length of avro binary data 
the binary avro data or text  Y bytes  Length given by the previous field. 

가 지금은 이미 위의 형식으로 생성 된 파일을 많이 가지고있다. Java 프로그램에서이 파일을 읽어야합니다. Java에서이 작업을 수행하는 가장 좋은 방법은 무엇입니까? 이것은 내가 메모리 맵핑 된 파일로 작업 할 때 처음이므로 어떻게 진행해야하는지 이해하려고 노력하고 있습니까?

FileChannel fc = new RandomAccessFile(new File("c:/tmp/file.txt"), "rw").getChannel(); 

이제 어떻게해야할지 잘 모르겠습니까? 모든 예를 통해 더 잘 이해할 수 있습니다.

답변

1

이렇게해야합니다. 열쇠는 DataInputStream의 바이트를 읽고 변환하는 메소드입니다. 나는 엔디안이 적당하다고 생각합니다.

ByteBuffer buf = ByteBuffer.allocate(9999); // capacity 
int nRead = fc.read(buf); 
InputStream is = new ByteArrayInputStream(buf.array()); 
DataInputStream dis = new DataInputStream(is); 
int version = dis.readInt(); //     4 bytes 
long timestamp = dis.readLong(); //     8 bytes 
int numUsers = dis.readInt(); //     4 bytes 

등등. 키 구분자 ('\ 0')와 바이트 배열의 길이로 표시되는 브로 데이터의 길이를 저장하는 필요가 없기 몸

추가 사항. 내가 파편해야 내가 읽고 생각, 또한

public class UserAttribute { 
    private final String attributeKey; 
    private final int schemaId;    // unsigned short 
    private final long lastModifiedDate; 
    private final byte[] avroBinaryData;  // preceded by length: unsigned short 
    // constructor and getters here 

} 

int numberOfAttributes = dis.readShort(); 
List<UserAttribute> ual = new ArrayList<>(numberOfAttributes); 
for(int iAttr = 0; iAttr < numberOfAttributes; ++iAttr){ 
    // read values for one attribute, create UserAttribute object 
    UserAttribute ua = new UserAttribute(); 
    StringBuilder sb = new StringBuilder(); 
    for(;;){ 
     int ub = dis.readUnsignedByte(); // can this be in ISO-8859-1 > 0x80? 
     if(ub == 0) break; 
     sb.append((char)ub); 
    } 
    ua.setAttributeKey(sb.toString()); 
    ua.setSchemaId(dis.readUnsignedShort()); 
    ua.setLastModifiedDate(dis.readLong()); 
    int loabd = dis.readUnsignedShort(); 
    byte[] abd = new byte[loabd]; 
    for(int ib = 0; ib < loabd; ++ib){ 
     abd[ib] = dis.readByte(); 
    } 
    ua.setAvroBinaryData(); 
    ual.add(ua); 
} 

, 단지 안전을 (자바에서 어떤 부호 없음 short)에있을, 짧은 정수를 저장하는 int를 사용하고

int numShards = dis.readInt(); // 4 bytes 1..101 
int[] shards = new int[numShards]; 
for(il = 0; il < numShards; ++il){ 
    shards[il] = dis.readInt(); // N * 4 bytes  Where N is the number of shards 
} 

int read = ...; 
FileChannel fc = new RandomAccessFile(file, "rw").getChannel(); 
ByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, read); 
buffer.order(ByteOrder.BIG_ENDIAN); 

이 파일 데이터를 포함하는 지정된 길이의 ByteBuffer를 초래하더라도 나중에 메모리 매핑. 파일이 0x7fffffff보다 큰 경우 청크로 매핑해야합니다. 동일한 FileChannel 메소드 (즉, map)를 사용하여 가능합니다.

+0

도움 주셔서 감사합니다. 나는 지금 내가해야 할 일을 이해하지만 신체 부분에서해야 할 일을 혼란스럽게합니까? '반복되는 속성의 순서 '는 단지 하나가 아니기 때문에, 반복적으로 얼마나 오랫동안 반복 할 것인가는 여러개가 될 것입니다. 일반적으로 특정 사용자 ID에 대한 데이터가있는 한 계속 반복해야합니다. – john

+0

"속성 수"를 읽고 다시 입력 할 수 있습니다. 0으로 구분 된 문자열의 경우 바이트 단위로 가져와야합니다. 아마도 readUnsignedByte()를 사용하고 문자열로 변환해야하지만 해당 문자열의 인코딩을주의해야합니다. "avro 데이터 또는 텍스트"에 관해서는 그것이 무엇인지를 알아야합니다. 그렇지 않으면 단지 "바이트"입니다. – laune

+0

avro 인코딩의 경우, 디코딩 방법을 알고 있으므로 쉽게 디코딩 할 수 있습니다. 'readUnsignedByte' 또는 모든 UserAttribute 필드 만 읽을 수있게 하시겠습니까? – john