【问题标题】:File last access time and last modified time in java?java中的文件最后访问时间和最后修改时间?
【发布时间】:2016-09-06 10:44:06
【问题描述】:

在我的应用程序中,我使用以下方法读取文件,

public void readFIleData(String path) {
    BufferedReader br = null;
    try {
        String sCurrentLine;
        br = new BufferedReader(new FileReader(path));
        while ((sCurrentLine = br.readLine()) != null) {
            System.out.println("Data : "+sCurrentLine);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (br != null)br.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

我还使用以下方法获取文件的最后访问时间和最后修改时间,

public void getFIleInfo(String path) {
    Path file = Paths.get(path);
    try {
        BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class);
        FileTime accessTime = attrs.lastAccessTime();
        System.out.println("accessTime : "+accessTime.toMillis());
        FileTime modifiedTime = attrs.lastModifiedTime();
        System.out.println("modifiedTime : "+modifiedTime.toMillis());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我按以下顺序运行上述方法,

1-> getFIleInfo()
2-> readFIleData()
3-> getFIleInfo()

我得到以下输出,

accessTime : 1462943491685
modifiedTime : 1462943925846
Data : erteuyuittdgfdfghjkhw5643rtrr66664fdghf
accessTime : 1462943491685
modifiedTime : 1462943925846

这里是字符串格式的输出时间,

accessTime : 2016-05-11T05:11:31.685881Z
modifiedTime : 2016-05-11T07:39:28.237884Z
Data : erteuyuittdgfdfghjkhw5643rtrr66LE229F1HBQ664fdghf
accessTime : 2016-05-11T05:11:31.685881Z
modifiedTime : 2016-05-11T07:39:28.237884Z

我对此输出有疑问,因为访问时间与读取文件数据之前保持相同。有人可以向我解释一下java中的最后访问时间和最后修改时间的实际含义吗?

【问题讨论】:

  • This might be the reason。另一方面,您正在运行什么操作系统?这可能不是 Java 的错,而是操作系统没有正确更新它
  • Win8.1 64bit here,我可以复制相同的。很有趣。
  • Java 自己什么都不做:它只是向底层文件系统询问值。可以肯定的是,只需创建一个文本文件,使用操作系统或文件系统工具查看访问时间(类 Unix 上的ls -atime,或 Windows 上的资源管理器),等待一两分钟,显示文件并再次查看访问时间。如果没有任何变化,则底层文件系统是有罪的。
  • 另一种可能性是内存缓存。许多操作系统现在使用高速缓存存储经常访问的文件。如果你重新读取一个已经缓存的文件,就没有文件系统级别的访问,访问时间也没有理由改变。但这绝对不是Java问题。
  • 很可能,因为 Window 10 是基于 NTFS 的,所以试试看changing the reg value in the article 是否能解决您的问题。但是,请注意,由于它是性能调整,因此已更改,因此将其关闭(设置为 0)可能会对性能产生影响

标签: java nio java-io


【解决方案1】:

首先,让我们关注一下这些东西的含义。

访问 - 上次读取文件的时间,即上次访问文件数据的时间。

修改 - 上次修改文件的时间(内容已被修改),即上次修改文件数据的时间。

Change - 上次更改文件元数据的时间(例如权限),即上次更改文件状态的时间。

编辑。 访问时间IS正在改变。 我建议你使用Thread.sleep(100) 之类的,然后看看这个问题是否仍然存在。 如果是这样,那么罪魁祸首就是您正在运行的操作系统,因为 Java 只是从文件系统中读取。 @Serge Ballesta 的 cmets 应该了解 Windows NTFS 有一个选项,即出于性能原因,可以禁用对文件属性所做的每个更改都写入硬盘驱动器。实际上还有更多。

来自 [docs],

NTFS 将文件的最后访问时间的更新延迟到最后一次访问后一小时。 NTFS 还允许禁用上次访问时间更新。默认情况下,不会在 NTFS 卷上更新上次访问时间。

以下是在 mac os x 上运行脚本的一些数据。

calling getFileInfo() at: 11.4.2016 3:13:08:738
    accessTime : 11.4.2016 3:12:53:0
    modifiedTime : 29.10.2015 1:49:14:0
--------------------
sleeping for 100ms
--------------------
calling readFIleData() at: 11.4.2016 3:13:08:873
--------------------
sleeping for 100ms
--------------------
re-calling getFileInfo() at: 11.4.2016 3:13:08:977
    accessTime : 11.4.2016 3:13:08:0 <---- READING FILE CHANGES ACCESS TIME
    modifiedTime : 29.10.2015 1:49:14:0
--------------------
sleeping for 100ms
--------------------
re-calling getFileInfo() at: 11.4.2016 3:13:09:81
    accessTime : 11.4.2016 3:13:08:0 <---- READING FILE ATTRIBUTES DOES NOT CHANGE ACCESS TIME
    modifiedTime : 29.10.2015 1:49:14:0 


为了提高清晰度,您可以将您拥有的毫秒转换为更具可读性的内容。以下代码 sn -p 将对此进行详细说明。
long accessTimeSinceEpoch = Files.readAttributes(file, BasicFileAttributes.class).lastAccessTime().toMillis();

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(accessTimeSinceEpoch);

int mYear = calendar.get(Calendar.YEAR);
int mMonth = calendar.get(Calendar.MONTH);
int mDay = calendar.get(Calendar.DAY_OF_MONTH);

int mHour = calendar.get(Calendar.HOUR);
int mMin = calendar.get(Calendar.MINUTE);
int mSec = calendar.get(Calendar.SECOND);
int mMilisec = calendar.get(Calendar.MILLISECOND);
String st = mDay + "." + mMonth + "." + mYear + " " + mHour + ":" + mMin + ":" + mSec + ":" + mMilisec;

【讨论】:

  • 这根本不能回答问题。它不要求转换毫。它是在询问为什么调用 read 不会影响上次访问时间。
  • @RichardEriksson 对于缺乏明确性,我深表歉意。我期待答案的第一部分已经回答了问题的那一部分。
【解决方案2】:

如果你查看 api 你有这个。

如果文件系统实现不支持时间戳 指示上次访问的时间,然后此方法返回 特定于实现的默认值,通常是 last-modified-timeFileTime 代表时代(1970-01-01T00:00:00Z)。

看起来“问题”与您的文件系统和操作系统有关。我认为您的代码没有任何问题。

例如,对于windows operating systemNtfsDisableLastAccessUpdate 选项在 Vista 和 Windows 7 中默认启用,但您可以使用以下命令行禁用它:

fsutil behavior set disablelastaccess 0

正如我在对您的问题的评论中所说,我能够在 Windows 中的真机中解决此问题,但不能在虚拟机中解决。如果您仍在为这个问题苦苦挣扎,请在执行任何操作之前发出此命令以查看注册表发生了什么:

fsutil behavior query disablelastaccess 

最后一点,我不必重新启动 Windows 或 Intellij(我运行测试的地方)。结果是立竿见影的,我可以看到,对于值 1,最后一次访问的时间戳不会改变,而对于值 0,它会改变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-07
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2012-05-13
    相关资源
    最近更新 更多