2012-06-26 4 views
3

공간 데이터를 테이블에서 파일로 쓰려고합니다. 하지만 디스크에 기록하기 전에 디스크의 정확한 데이터 크기를 알아야합니다.ObjectOutputStream을 사용할 때 디스크의 파일 크기를 추정합니다.

size= 4B {for gid, int} + fullname.getBytes.length() {string} + 4B {d.shape.length, int} + d.shape.length 

하지만 사실, 이것은 매우입니다 : 예를 들어, 이제 나는 다음과 같은 코드를 사용하여 디스크에 쓰고 있다고 가정 해 봅시다 :에

FileOutputStream fos = new FileOutputStream("t.tmp",false); 
    ObjectOutputStream oos = new ObjectOutputStream(fos); 
    oos.writeInt(gid); 
    oos.writeUTF(fullname); 
    oos.writeInt(d.shape.length); 
    oos.write(d.shape); 

    oos.close(); 
    fos.close(); 

내가 디스크에 해당 파일의 크기를 생각은 같다 디스크의 실제 파일 크기와 다릅니다.

ObjectOutputstream을 사용하여 빈 파일을 생성하더라도 디스크에 4B 공간이 생깁니다.

디스크의 파일 크기를 계산하는 방법에 대한 도움이 필요하십니까?

(I 디스크에 데이터를 기록하고 실제 크기를 읽을 수 없습니다.이 성능을 낮출 것이다. 대신, 메모리에 저장된 데이터 값을 기준으로 디스크에있는 데이터의 크기를 계산해야합니다.)

+0

* Object * OutputStream이 실제로 필요합니까? 'writeObject()'를 사용합니까? 또는 예제 코드가 세련된 것입니까? [DataOutputStream] (http://docs.oracle.com/javase/6/docs/api/java/io/DataOutputStream.html)을 사용하는 것이 더 나을 것 같습니다. ObjectOutputStream는 스트림 헤더 정보를 기록하고 이미 작성된 객체에 대한 참조를 추적하므로 참조를 작성하기 만하면되므로 크기를 사전 계산하는 데 방해가 될 수 있습니다.) –

+0

또한 - 바이트를 쓴 후에 파일 시스템을 사용하여 인식하는 성능 문제를 확장 할 수 있습니까? 성능 문제와 관련하여 –

+0

입니다. 나는 내 테이블에 40GB의 데이터를 가지고 있으며 그 중 대다수는 공간 데이터입니다. 나는 각 파일에 저장된 데이터의 전체 크기가 특정 값 (max_file_size)보다 작도록 테이블을 분할하고있다. 첫 번째 라운드에서는 테이블의 각 행에 대한 디스크의 크기를 계산하고 다음 라운드에서는 총 파일 크기가 max_file_size보다 작은 파일 내에 들어갈 수있는 많은 파일을 합계합니다. 따라서 모든 파일을 쓰고 디스크의 실제 파일 크기를 측정하는 것은 옵션이 아닙니다. – reza

답변

1

일부 메모리를 낭비하지 않으려면 먼저 ByteArrayOutputStream에 모두 기입 한 다음 크기를 확인하십시오.

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(boas); 
oos.writeInt(gid); 
oos.writeUTF(fullname); 
oos.writeInt(d.shape.length); 
oos.write(d.shape); 

oos.close(); 
boas.close(); 
int size = boas.size(); 
+0

위대한. 한 행의 데이터 크기를 계산하려면이 작동합니다. 모든 데이터 행에 대해이를 계산하고 block_size 열 아래에 내 테이블에 저장합니다. 그런 다음 누적 된 block_size가 특정 값보다 작은 행을 너무 많이 선택합니다. 문제는 두 행의 block_size 값의 합이 디스크에 기록 된 두 행의 파일 크기보다 큰 것입니다. 이 부분을 해결하는 방법에 대한 아이디어가 있습니까? – reza

+0

@reza 정확해야 할 필요가있는 경우 메모리의 전체 데이터 구조를 먼저 (또는 임시 파일로) 직렬화해야합니다. Java 직렬화는 중복 객체와 문자열을 어느 정도 제거하여 데이터가 두 배가된다고 가정 할 수 없습니다 두 배의 공간. –

+0

감사합니다. DataOutputStream을 사용하여 종료되었습니다. 이렇게하면 계산 된 크기가 디스크의 파일 크기와 정확하게 일치합니다. 제안에 감사드립니다. – reza

2

나는 파일에 테이블에서 내 공간 데이터를 쓰기 위해 노력하고 있어요. 하지만 디스크에 기록하기 전에 디스크의 정확한 데이터 크기를 알아야합니다.

ObjectOutputStream을 사용하지 마십시오. ObjectOutputStream은 자동으로 객체의 복잡한 그래프를 직렬화 할 수 있지만 사용자 요구 사항 중 하나는 아닙니다. 이 직렬화의 일부로 ObjectOutputStream은 일부 스트림 헤더 정보 (처음에 발견 한 4 바이트)를 기록하고 이전에 작성된 객체를 추적하므로 전체 객체를 다시 쓰지 않고 특별한 마커 값을 쓸 수 있습니다 .

대신 DataOutputStream을 사용하십시오.

데이터 출력 스트림을 사용하면 응용 프로그램에서 기본 Java 데이터 유형을 출력 스트림에 이식 방식으로 쓸 수 있습니다. 응용 프로그램은 다음 다시 데이터를 읽을 수있는 데이터 입력 스트림을 사용할 수 있습니다.

FileOutputStream fos = new FileOutputStream("t.tmp",false); 
DataOutputStream dos = new DataOutputStream(fos); 
dos.writeInt(gid);     // write 4 bytes 
dos.writeUTF(fullname);   // write 2 bytes of length, then variable length string (UTF encoded) 
dos.writeInt(d.shape.length);  // write 4 bytes 
dos.write(d.shape);    // write a variable length byte array 

dos.close(); 
fos.close(); 

여기에 어떤 놀라움을가되지 않습니다 (당신이 당신의 UTF 인코딩 된 문자열이 끝날 바이트 얼마나 많은 알고 제공), 및 산술 연산을 통해 정확한 파일 크기를 계산할 수 있습니다.

(한 문자 -1 바이트와 같지 않은 문자열을 처리하는 경우 먼저 charset 인코더를 사용하여 문자열을 바이트 배열로 렌더링 할 수 있습니다.

+0

고마워. 이것은 문제를 해결했습니다. Java 스트림에서 내 기억을 새로 고침해야한다고 생각합니다. Java 스트림에 대한 자습서를 권합니까? – reza

+0

@reza : 아니요, 죄송합니다. –

관련 문제