我正在为我的java程序编写一个记录器(采用csv格式)。 记录器工作正常,我有一个问题。
当我尝试写入文件并同时打开文件时,程序会崩溃,这听起来很合乎逻辑。 当我这样做时,我得到了一个例外:“进程无法访问该文件,因为它正被另一个进程使用”。
我的问题是,即使有人打开文件,是否还有继续写作?
感谢。
更新
我想我解决了这个问题。 每次写入文件后(使用bufferedWriter和FileWriter),我都会调用close()函数来关闭bufferedWriter和FileWriter。
我更改了close()函数: 1.添加了fileChannel和FileLock。 2. Igonore线bw.close();
可以不关闭bufferWriter(bw)?以后可以出现任何问题吗?
private void close() throws IOException {
RandomAccessFile rf;
rf = new RandomAccessFile(file, "rw");
fileChannel = rf.getChannel();
lock = fileChannel.lock();
try {
if (bw != null) {
// bw.close(); The line i ignored.
bw = null;
}
if (fw != null) {
fw.close();
fw = null;
}
} catch (IOException ex) {
ex.printStackTrace();
}
lock.release();
}
更新2: 现在我发现如果我将函数更改为(关闭更改为flush),它的工作:
private void close() {
try {
if (bw != null) {
bw.flush();
bw = null;
}
if (fw != null) {
fw.flush();
fw = null;
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
什么是最佳选择?
答案 0 :(得分:1)
即使有其他东西打开文件,是否还有继续写作?
不是Java。
要编写文件,必须先将其打开。如果你不能打开它,因为操作系统不会允许它...因为其他东西已经打开它......那么你就无法达到可以写它的程度。
在这种情况下,您应该考虑打开另一个日志文件。
请注意,这种情况发生在Windows中,因为Java遵循正常的Window实践并默认使用独占(强制)锁打开文件。没有更改Java ...以及打开这样的文件的每个其他Windows应用程序......你被困住了。
<强>更新强>
事实证明可能是的一种方式。
如上所述使用FileChannel.open
,但使用允许您在不禁止其他编写者的情况下编写的标记。例如
FileChannel.open(path, WRITE)
或
FileChannel.open(path, WRITE, APPEND)
诀窍在于您不需要任何NOSHARE_*
选项。
CAVEAT:我没试过。
答案 1 :(得分:1)
扭转问题:尝试在继续写作时打开:
如果你想要固定数据,你可以复制文件(通过shell),然后阅读它;
如果您想要未来的书面数据,则必须保持相同的输出:尝试将正常输出重定向到您可以存储和读取的内容。
也许存在一些图书馆。它看起来像发球和发球。
参见例如: Could I duplicate or intercept an output stream in Java?
How do I redirect log4j output to my HttpServletResponse output stream?
答案 2 :(得分:1)
正如@guillaume所说,你可以使用像log4j这样的库。
但是如果要在Java中实现解决方案,可以使用观察者模式并将日志写为异步。