我正在创建一个程序,需要从仍在编写的文件中读取。
主要问题是:如果使用在单独的线程上运行的InputStream
和OutputStream
类来执行读写操作,那么我将需要哪些捕获和边缘情况要注意以防止数据损坏?
如果有人想知道我是否考虑过其他非基于InputStream
的方法,答案是肯定的,但我很遗憾,因为该程序仅使用库,所以在此项目中不可能适用于InputStream
和OutputStream
。
此外,一些读者已经问过为什么这种并发症是必要的。完全写完文件后为什么不执行读取?
原因是效率。该计划将执行以下
如果我们要等待整个文件被转移,那么它将会对应该是一个实时系统造成很大的延迟。
答案 0 :(得分:2)
使用 RandomAccessFile 。通过 getChannel 或者这样的人可以使用 ByteBuffer 。
您将无法“插入”或“删除”文件的中间部分。出于这样的目的,你的原始方法会很好,但是使用两个文件。
对于并发:要保持同步,您可以维护文件的单个对象模型,在那里进行更改。只有待处理的更改需要保留在内存中,其他分层数据可以根据需要重新读取和重新分析。
答案 1 :(得分:0)
你应该使用PipedInputStream和PipedOutputStream:
static Thread newCopyThread(InputStream is, OutputStream os) {
Thread t = new Thread() {
@Override
public void run() {
byte[] buffer = new byte[2048];
try {
while (true) {
int size = is.read(buffer);
if (size < 0) break;
os.write(buffer, 0, size);
}
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
};
return t;
}
public void main(String[] args) throws IOException, InterruptedException {
ByteArrayInputStream bi = new ByteArrayInputStream("abcdefg".getBytes());
PipedInputStream is = new PipedInputStream();
PipedOutputStream os = new PipedOutputStream(is);
Thread p = newCopyThread(bi, os);
Thread c = newCopyThread(is, System.out);
p.start();
c.start();
p.join();
c.join();
}
答案 2 :(得分:0)
所以你的问题(正如你现在已经清除它)是你无法开始处理直到#1块到达,你需要缓冲每个块#N(N> 1)直到你可以处理它们。
我会将每个块写入自己的文件并创建一个自定义InputStream
,它将按顺序读取每个块。下载chunk文件时会命名为chunk.1.downloading
,当整个块加载时,它将被重命名为chunk.1
。
自定义InputStream
将检查文件chunk.N
是否存在(其中N = 1 ... X)。如果没有,它将阻止。每次完全下载一个块时,都会通知InputStream
,它将检查下载的块是否是下一个要处理的块。如果是,请按正常方式读取,否则再次阻止。