[英]Read the newly appended file content to an InputStream in Java
我有一個編寫程序,可以以特定的速度將巨大的序列化Java對象(規模為1GB)寫入本地磁盤上的二進制文件中。 實際上,writer程序(用C語言實現)是一個網絡接收器,它從遠程服務器接收序列化對象的字節。 作者的實現是固定的。
現在, 我想實現一個Java閱讀程序 ,該程序讀取文件並將其反序列化為Java對象。 由於文件可能很大,因此減少反序列化對象的延遲是有益的。 特別是,我希望Java閱讀器一旦將對象的第一個字節寫入磁盤文件后就開始讀取/反序列化該對象,以便即使在將整個序列化對象寫入文件之前,閱讀器也可以開始對對象進行反序列化。 。 讀者可以提前知道文件的大小(在將第一個字節寫入文件之前)。
我認為我需要的是一個類似阻塞文件InputStream的東西,當它到達EndOfFile時將被阻塞,但是它沒有讀取預期的字節數(文件大小將是)。 因此,無論何時將新字節寫入文件,讀取器的InputStream都可以繼續讀取新內容。 但是,Java中的FileInputStream不支持此功能。
也許,我還需要一個文件監聽器來監視對文件所做的更改以實現此功能。
我想知道是否有任何現有的解決方案/庫/軟件包可以實現此功能。 該問題可能類似於監視日志文件中的某些問題。
字節流如下:FileInputStream-> SequenceInputStream-> BufferedInputStream-> JavaSerializer
您需要兩個線程:線程1從服務器下載並寫入文件,線程2則在文件可用時讀取文件。
兩個線程應共享一個RandomAccessFile,因此可以正確同步對OS文件的訪問。 您可以使用如下包裝器類:
public class ReadWriteFile {
ReadWriteFile(File f, long size) throws IOException {
_raf = new RandomAccessFile(f, "rw");
_size = size;
_writer = new OutputStream() {
@Override
public void write(int b) throws IOException {
write(new byte[] {
(byte)b
});
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (len < 0)
throw new IllegalArgumentException();
synchronized (_raf) {
_raf.seek(_nw);
_raf.write(b, off, len);
_nw += len;
_raf.notify();
}
}
};
}
void close() throws IOException {
_raf.close();
}
InputStream reader() {
return new InputStream() {
@Override
public int read() throws IOException {
if (_pos >= _size)
return -1;
byte[] b = new byte[1];
if (read(b, 0, 1) != 1)
throw new IOException();
return b[0] & 255;
}
@Override
public int read(byte[] buff, int off, int len) throws IOException {
synchronized (_raf) {
while (true) {
if (_pos >= _size)
return -1;
if (_pos >= _nw) {
try {
_raf.wait();
continue;
} catch (InterruptedException ex) {
throw new IOException(ex);
}
}
_raf.seek(_pos);
len = (int)Math.min(len, _nw - _pos);
int nr = _raf.read(buff, off, len);
_pos += Math.max(0, nr);
return nr;
}
}
}
private long _pos;
};
}
OutputStream writer() {
return _writer;
}
private final RandomAccessFile _raf;
private final long _size;
private final OutputStream _writer;
private long _nw;
}
以下代碼顯示了如何從兩個線程使用ReadWriteFile:
public static void main(String[] args) throws Exception {
File f = new File("test.bin");
final long size = 1024;
final ReadWriteFile rwf = new ReadWriteFile(f, size);
Thread t1 = new Thread("Writer") {
public void run() {
try {
OutputStream w = new BufferedOutputStream(rwf.writer(), 16);
for (int i = 0; i < size; i++) {
w.write(i);
sleep(1);
}
System.out.println("Write done");
w.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
Thread t2 = new Thread("Reader") {
public void run() {
try {
InputStream r = new BufferedInputStream(rwf.reader(), 13);
for (int i = 0; i < size; i++) {
int b = r.read();
assert (b == (i & 255));
}
int eof = r.read();
assert (eof == -1);
r.close();
System.out.println("Read done");
} catch (IOException ex) {
ex.printStackTrace();
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
rwf.close();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.