일부 처리 된 콘텐츠를 출력 스트림에 기록한 후 스트림의 시작 부분을 다시 방문하여 일부 콘텐츠 메타 데이터를 작성해야합니다. 필자가 쓰고있는 데이터는 4Gb만큼 큽니다. 다양한 환경 요인에 따라 직접 파일이나 메모리 버퍼에 쓸 수 있습니다.되감기 할 수있는 OutputStream을 어떻게 구현할 수 있습니까?
콘텐츠 쓰기를 완료 한 후 헤더를 쓸 수있는 OutputStream을 구현하려면 어떻게해야합니까?
일부 처리 된 콘텐츠를 출력 스트림에 기록한 후 스트림의 시작 부분을 다시 방문하여 일부 콘텐츠 메타 데이터를 작성해야합니다. 필자가 쓰고있는 데이터는 4Gb만큼 큽니다. 다양한 환경 요인에 따라 직접 파일이나 메모리 버퍼에 쓸 수 있습니다.되감기 할 수있는 OutputStream을 어떻게 구현할 수 있습니까?
콘텐츠 쓰기를 완료 한 후 헤더를 쓸 수있는 OutputStream을 구현하려면 어떻게해야합니까?
다음은 임의 액세스 파일 출력 스트림입니다.
많은 양의 스트리밍 된 출력에 사용하는 경우 BufferedOutputStream에 임시로 래핑하여 작은 쓰기가 많이 발생하지 않도록 할 수 있습니다 (래퍼를 삭제하거나 기본 스트림을 직접 사용하기 전에 반드시 플러시해야합니다).
import java.io.*;
/**
* A positionable file output stream.
* <p>
* Threading Design : [x] Single Threaded [ ] Threadsafe [ ] Immutable [ ] Isolated
*/
public class RandomFileOutputStream
extends OutputStream
{
// *****************************************************************************
// INSTANCE PROPERTIES
// *****************************************************************************
protected RandomAccessFile randomFile; // the random file to write to
protected boolean sync; // whether to synchronize every write
// *****************************************************************************
// INSTANCE CONSTRUCTION/INITIALIZATON/FINALIZATION, OPEN/CLOSE
// *****************************************************************************
public RandomFileOutputStream(String fnm) throws IOException {
this(fnm,false);
}
public RandomFileOutputStream(String fnm, boolean syn) throws IOException {
this(new File(fnm),syn);
}
public RandomFileOutputStream(File fil) throws IOException {
this(fil,false);
}
public RandomFileOutputStream(File fil, boolean syn) throws IOException {
super();
File par; // parent file
fil=fil.getAbsoluteFile();
if((par=fil.getParentFile())!=null) { IoUtil.createDir(par); }
randomFile=new RandomAccessFile(fil,"rw");
sync=syn;
}
// *****************************************************************************
// INSTANCE METHODS - OUTPUT STREAM IMPLEMENTATION
// *****************************************************************************
public void write(int val) throws IOException {
randomFile.write(val);
if(sync) { randomFile.getFD().sync(); }
}
public void write(byte[] val) throws IOException {
randomFile.write(val);
if(sync) { randomFile.getFD().sync(); }
}
public void write(byte[] val, int off, int len) throws IOException {
randomFile.write(val,off,len);
if(sync) { randomFile.getFD().sync(); }
}
public void flush() throws IOException {
if(sync) { randomFile.getFD().sync(); }
}
public void close() throws IOException {
randomFile.close();
}
// *****************************************************************************
// INSTANCE METHODS - RANDOM ACCESS EXTENSIONS
// *****************************************************************************
public long getFilePointer() throws IOException {
return randomFile.getFilePointer();
}
public void setFilePointer(long pos) throws IOException {
randomFile.seek(pos);
}
public long getFileSize() throws IOException {
return randomFile.length();
}
public void setFileSize(long len) throws IOException {
randomFile.setLength(len);
}
public FileDescriptor getFD() throws IOException {
return randomFile.getFD();
}
} // END PUBLIC CLASS
헤더의 크기를 알고있는 경우 처음에는 빈 헤더를 쓸 수 있습니다. 그런 다음 끝에 가서 RandomAccessFile
으로 수정하십시오. 헤더의 크기를 모른다면 파일 시스템은 일반적으로 데이터를 삽입 할 수 없다는 근본적인 문제가 있습니다. 따라서 임시 파일에 쓰고 실제 파일을 작성해야합니다.
헤더의 크기를 알 수 있지만 스트림의 임의의 지점에서 쓰기를 허용하는 일반 OuptutStream을 찾을 수있는 방법은 없습니다. –
당신은 그것을 밖으로 씁니다. 파일을 닫으십시오. RandomAccessFile을 엽니 다. 헤더를 작성하십시오. RandomAccessFile을 닫습니다. –
(동작 당 RandomAccessFile 성능이 좋지 않으므로 큰 블록 작업을 사용하십시오.) –
Lucene이 구현 된 것으로 보입니다. 그리고 api는 좋아 보인다.
getFilePointer()
void seek(long pos)
http://lucene.apache.org/java/1_4_3/api/org/apache/lucene/store/OutputStream.html
는 I은 우선 메모리 버퍼에 버퍼링 된 플러시 하였다 "진짜"출력 스트림으로 다음 헤더를 초기 내용을 작성하는 것 RandomAccessFile
편도 포장 추측 그 내용을 버퍼링되지 않은 스트림에 씁니다. 초기 세그먼트가 버퍼링을 합리적인 것으로 만들기 위해 그렇게 오래 걸리지는 않을 것 같습니다. 버퍼를 구현하는 데 ByteArrayOutputStream을 사용하고 OutputStream 클래스를 "실제"출력 스트림을 인수로 사용할 수 있습니다. 필요에 따라 둘 사이를 전환하면됩니다. 출력 할 API가 OutputStream API를 확장해야 쓰기가 가능한 메타 데이터를 정의 할 수 있습니다. 그러면 버퍼 모드에서 스위치가 트리거됩니다.
다른 답변에서 언급했듯이 RandomAccessFile 역시 OutputStream을 구현하지는 않지만 작동합니다.
"필자가 작성한 데이터는 4Gb만큼 큽니다." – DJClayworth
나는 유감스럽게도 그렇지 않았지만 그 이유는 다른 고려 사항 때문에 설계를 변경해야했기 때문입니다. 여전히 좋은 대답입니다. –