Android 是否有必要使用FileLock来避免读取和维护问题;写作或写作&;同时写作?

Android 是否有必要使用FileLock来避免读取和维护问题;写作或写作&;同时写作?,android,file,synchronization,locking,Android,File,Synchronization,Locking,我正在设计一个应用程序,其主线程通过读写与.txt文件交互 此应用程序还有一个后台IntentService,可以读取和写入此文件 我需要能够读入一个文件,并用新数据将其写回,同时确保在这两个步骤之间,另一个线程没有改变文件的数据 我认为文件锁是我想要的,但是当我开始读取文件时,我在锁定文件时遇到了问题,因为InputFileStream.getChannel().lock()给出了一个异常。(不可写通道异常) 我希望代码类似于: File theFile = new File(file.txt

我正在设计一个应用程序,其主线程通过读写与.txt文件交互

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

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

我认为文件锁是我想要的,但是当我开始读取文件时,我在锁定文件时遇到了问题,因为InputFileStream.getChannel().lock()给出了一个异常。(不可写通道异常)

我希望代码类似于:

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(),但我想在深入研究之前,我会询问社区。

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

根据此链接-

如果将文件内容写入设备,则速度将明显慢于其他方法

另外,就您的NonWritableChannelException而言,它的发生是因为您试图锁定inputstream。如果要锁定,需要打开文件进行写入


希望这能有所帮助。

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

除此之外,一般来说,您希望最小化磁盘I/O,因为这样做很慢

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

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


通过这种方式,您可以将磁盘读取量降低到所需的最小值,再加上同步磁盘I/O(
IntentService
仅使用一个线程,如果多个命令同时进入,则有一个工作队列),因此您不必担心应用程序的一部分会与应用程序的其余部分发生冲突

“我正在设计一个应用程序,其主线程通过读写与.txt文件交互。这个应用程序还有一个后台IntentService,可以读取和写入这个文件。”--为什么?为什么不让一个实体拥有一个工作队列,负责写入和读取或返回缓存数据?另外,我希望当你提到“主线程”时“执行读取并不意味着在主应用程序线程上执行磁盘I/O,因为这将导致jank。这些是小文件(几百个字符)。为什么后台线程访问这些文件?因为它是一款应用程序,可以使用AlarmManager在预定时间在手机的后台执行操作。它需要进行Internet下载,这不能在broadcast Receiver类中运行,因此broadcast Receiver类必须运行intentservice,其目的是在线检查文件。如果出现了某种情况,它需要写入用户界面读取的文件,以便向用户显示信息。这篇文章的名称不正确。更好的标题应该是:如何修改一个文件,同时确保没有其他线程可以修改它?“如果出现了某种情况,它需要写入用户界面读取的文件,以便将信息显示给用户”——这就是我建议可以重新设计的内容。特别是对于小文件,请使用由文件支持的内存缓存。您的服务更新该文件,并使用进程内事件总线让UI层知道(如果它当前存在)数据已更改。您需要读取文件的唯一时间是重新启动进程时,如果您在执行写入操作的同一
IntentService
中执行此操作,I/O将自动序列化。您说得对!好的,我有一个跟踪运行报警管理器的文件,这个文件还有线程写入的“更新”数据。创建新的AlarmManager时,UI必须更改此文件。相反,我将把这些不断变化的数据移动到一个单独的文件中,接口将只读取该文件,而不再需要写入该文件。我从未使用过缓存-我必须在原型工作后尝试使用它。当前,我的UI实例化了一个FileObserver,并向它传递一个在Looper.getMainLooper()上运行的处理程序。当文件发生更改时,file observer实例将消息传递给处理程序。当处理程序的handleMessage启动时,UI将更新。这项措施目前有效。谢谢我对你的答案有了新的发现。除了所有的东西都(某种程度上)存储在一个地方(硬盘)之外,我们还有不同文件的抽象。他们这样做是为了让我们可以在节目中分开“对话”。从两个不同的线程写入和读取同一个文件就像在别人说话时试图说话一样。只需通过不同的渠道说话!又名写入不同的文件,并从不同的文件读取。你从A读,然后给B写。他们从B读,然后给A写!最后用互斥体和SQLite解决了这个问题谢谢你的帮助!
"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.