使用FileLock是为了避免阅读和阅读问题。写作或写作同时写作?

时间:2015-01-01 19:25:03

标签: android file synchronization locking

我正在设计一个应用程序,其主要线程通过读取和写入来与.txt文件进行交互。

此应用程序还具有后台IntentService,可以读取和写入此文件。

我需要能够读入一个文件,然后用新数据写回来,同时保证另一个线程在这两个步骤之间没有改变文件的数据。

我认为FileLock是我想要的,但是当我开始读取它时,我无法锁定文件,因为InputFileStream.getChannel()。lock()给出了异常。 (NonWritableChannelException)。

我希望代码类似于:

File theFile = new File(file.txt);
FileInputStream in = new FileInputStream(theFile);

//should block here if it can't immediately lock
FileLock fileLock = in.getChannel().lock(); 

String inString = "";

int content;
while((content = in.read()) != -1){
    inString += Character.toString(((char) content));
 }
in.close();

inString += "new data";

out = new FileOutputStream(file);

out.write(finalString.getBytes());

 out.flush();
 out.close();

//releases the lock
fileLock.release();

我意识到可能有用的一个场景是使用RandomAccessFile。因为从那些读取时,你可以声明它们是“rw”权限(读写),所以你可以使用.getChannel()。lock()但我想在讨论之前我会问社区。

2 个答案:

答案 0 :(得分:1)

使用随机访问文件可能会导致性能降低。

根据此链接 - http://docs.oracle.com/javase/6/docs/api/java/io/RandomAccessFile.html#RandomAccessFile%28java.io.File,%20java.lang.String%29

"rws"   Open for reading and writing, as with "rw", and also require that every update to the file's content or metadata be written synchronously to the underlying storage device.
"rwd"   Open for reading and writing, as with "rw", and also require that every update to the file's content be written synchronously to the underlying storage device. 

如果写入设备的文件内容将明显慢于其他方法。

此外,就您的NonWritableChannelException而言,它是因为您尝试锁定输入流而发生的。如果要锁定,则需要打开文件进行写入。

希望这有帮助。

答案 1 :(得分:1)

一般来说,对于单进程应用程序(大多数Android应用程序都是这样),线程同步是要走的路,比文件系统级锁定更多。

除此之外,通常,您希望最小化磁盘I / O,因为它很慢。

特别是对于小文件,请使用由文件支持的内存缓存。您的服务更新文件并使用进程内事件总线(LocalBroadcastManager,greenrobot的EventBus,Square的Otto)让UI层知道(如果当前存在)数据已更改。 UI层侧重于使用数据的内存缓存。

您需要读取文件的唯一时间是您的进程重新启动,如果您在执行写入的IntentService中执行此操作,则会自动序列化I / O.如果您的UI在启动时检测到进程内缓存为空,它只会发送命令以启动服务以读取该缓存。该服务再一次使用事件总线让UI层知道数据现在可以使用了。

这样,您可以将磁盘读数减少到所需的最小值,再加上同步磁盘I / O(IntentService只使用一个线程,并且如果多个命令大约在同一时间进入,则会有一个工作队列) ,所以你不必担心你的应用程序的一部分会破坏你的应用程序的其余部分。