簡體   English   中英

將新添加的文件內容讀取到Java中的InputStream

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM