【问题标题】:Deny access to a file for all other processes?拒绝所有其他进程访问文件?
【发布时间】:2012-10-24 09:55:21
【问题描述】:

我正在编写一个应用程序(用于教育目的),它需要使用数据库管理系统(我自己编写了极其原始的 DBMS,它是任务的一部分)。而且我想确保在任何时候我的应用程序正在运行的所有表的内容都是正确的。为此,我编写了方法,它查看每个文件并进行必要的检查。问题是我只想在应用程序启动并拒绝访问文件时调用此方法一次,以确保在我的程序运行时没有人更改其内容。

我使用以下方法。应用程序启动时,我会初始化 InputStreamReaderOutputStreamWriter,存储它们并仅在应用程序终止时关闭它们。

部分初始化方法:

FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(file, true); 
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");

this.tables.get(table).put("fis", fis);
this.tables.get(table).put("fos", fos);
this.tables.get(table).put("isr", isr);
this.tables.get(table).put("osw", osw);

关闭方法:

try {
    for(Map<String, Object> table_map: tables.values()) {
        OutputStreamWriter osw = (OutputStreamWriter)table_map.get("osw"); 
        InputStreamReader isr = (InputStreamReader)table_map.get("isr"); 

        if (osw != null)
            osw.close();
        if (isr != null)
            isr.close();
    }
}
catch (IOException e) {
    throw new DBException("Closing error");
}

部分地,这种方法有效,因为当我尝试使用 MS 记事本修改这些文件中的任何一个时,我收到以下错误

"进程无法访问该文件,因为它正被 另一个进程”

这就是我想看到的。但是如果我使用 Notepad++,我可以在我的应用程序运行时进行任何修改,这不是我期望看到的。那么我该怎么做才能确保没有其他进程可以修改我的文件呢?

我尝试使用 FileLock,但如果我没记错的话,它只会拒绝我的进程访问。

对不起,我的英语不好,希望你能理解我的问题。

【问题讨论】:

  • 我不会使用地图,而是使用包含oswisr 的对象。我会缓冲它们以提高性能,并且我不会存储原始流,因为您不需要它们。我会使用合适的 IDE 来帮助您编写、运行和调试代码。
  • 拒绝访问文件的最简单方法是重命名文件。这样,除非您知道文件的名称,否则您将无法访问它,您可以更改其扩展名。
  • 是的,重命名文件通常是一种享受...只需确保将其重命名为“高度独特”的名称,例如 filename.UUID.ext。查看文档:docs.oracle.com/javase/6/docs/api/java/util/UUID.html
  • 对不起,我的英语很差 > 对于它的价值,你的问题读起来很好。可能比所谓的母语人士写的许多努力要好:-)
  • @PeterLawrey 可能需要非常小心地正确处理所有错误情况,以确保文件在程序退出时重命名为其原始名称。

标签: java file java-io


【解决方案1】:

我不确定这是一个值得解决的问题。无论您采取何种方法,具有正确权限的人都可能会撤消您的文件保护并进行更改。

最好专注于优雅地处理无效数据并信任文件中的内容。添加某种完整性检查(每行或表)将使某人更难意外或恶意更改您的数据,使其看起来“有效”。

【讨论】:

  • 好吧,首先我想回答你,这种完整性检查是相当耗费资源的。例如,我检查具有较高主键值的行是否排在具有较低主键值的行之后。要执行此检查,方法需要读取整个文件并解析每个字符串以获取主键值。但后来我想了想,决定这个检查是没有用的。如果用户试图故意破坏程序的正确工作,他们应该为意外结果做好准备。我只需要防止程序崩溃,所以,我想,主要方法(如插入)中的行检查就足够了。
  • 小评论 - 我并没有认为这种资源密集型检查根本没有用。它在应用程序启动时很有帮助,但每次我想选择、更新、插入或删除数据时都调用它是没有意义的。因此实际上不需要锁定文件。
【解决方案2】:

如果您阅读 java.nio.channels.FileLock 文档中的“平台依赖项”部分,您会看到:

  • FileLocks 不(仅)用于锁定在 one JVM 内部,而是用于计算机上的所有进程。
  • 文件锁(注意不同的拼写)很大程度上取决于平台和配置。

所以你基本上必须问自己:我真正需要什么保护?

如果您只想防止在同一数据上多次运行您的程序,您可以假设您的程序“表现良好”并且

  • 使用FileLocks
  • 使用标记锁定文件或
  • 在文件中使用“脏/锁定”标记

如果你想保护其他程序,那么你就迷失了,正如你在 Notepad++ 场景中看到的那样:考虑所有平台和所有可能的方法来规避锁和使用 Java——你没有机会.

【讨论】:

  • FileLocks 根本不是为了“锁定在一个 JVM 中”。它们只在进程之间工作。请参阅 Javadoc。
  • @EJP:我很困惑:JavaDoc 说:“单个 Java 虚拟机在特定文件上持有的锁不重叠。”这意味着你 可以在你的程序中使用FileLock。一个快速测试程序在 Linux 上验证了这一点。另一方面,同一个文档说:“文件锁代表整个 Java 虚拟机持有。它们不适合控制同一虚拟机内的多个线程对文件的访问。”所以你可以选择任何你想要的:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-23
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
相关资源
最近更新 更多