File last access time and last modified time in java?
Asked Answered
C

2

6

In my application I read file using following method,

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();
        }
    }
}

Also I get last access time and last modified time of the file using following method,

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();
    }
}

I ran above methods in following order,

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

I got following as output,

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

Here is output times in string format,

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

I have a doubt about this output because access time remains the same as before reading the data of the file. Can somebody please explain to me what is actually mean by last access time and last modified time in java?

Cyperaceous answered 11/5, 2016 at 7:22 Comment(14)
This might be the reason. On another note, what OS are you running on? It might not be Javas fault, but instead the OS not updating it correctlyJeconiah
Win8.1 64bit here and i can replicate the same. Interesting.Gouache
Java does nothing by itself: it just asks values to the underlying file system. Just to be sure, just create a text file, look with the os or file system tools at the access time (ls -atime on Unix-like, or explorer on Windows), wait one or two minutes, display the file and once again look at the access time. If nothing has changed, the underlying file system is guilty.Polk
Another possibility would be memory cache. Many OS now use cache memory for frequently accessed files. If you re-read a file that has been cached, there is no file system level access and the access time has no reason to change. But it is definitely not a Java problem.Polk
@Draken, I did this on Windows 10. Is that can be reason for this behavior?Cyperaceous
@SergeBallesta, according to your test when I view the properties of the file access time has changed.Cyperaceous
It could very well be, since Window 10 is NTFS based, have a go and see if changing the reg value in the article fixes your issue. However, be warned as it was changed since it's a performance tweak, so having it turned off (Set to 0) could have performance effectsJeconiah
Which file system are you using?Derm
@Draken, in redhat linux this is working as expected.Cyperaceous
@RichardEriksson yes, and probably because you have the NtfsDisableLastAccessUpdate option enabled.Derm
@Cyperaceous if you didn't disable the NtfsDisableLastAccessUpdate property then that explains already what's going on.Derm
Can confirm that switching runtime environment to Arch Linux, the issue is gone. There is a risk of portability issues in this, obviously. But Java is not to blame for it as we can see.Gouache
@RichardEriksson Seems like GetFileTime function docs might have an potential answer as to why this is happening. I have added that in the answer belowJinn
@Cyperaceous I tried to reproduce this problem today with a windows virtual machine. Unfortunatelly, with my virtual machine I ran into your problem exactly and in spite of disabling the NtfsDisableLastAccessUpdate registry, I could not get the file access to work. I do have windows at home and gave it a try. That way it works, so if you issue the command I posted as an answer to your question you will see that the last access timestamp changes when this registry is set to 0 and will not change if it is set to 1 as it is by default.Derm
B
0

If you look into the api you have this.

If the file system implementation does not support a time stamp to indicate the time of last access then this method returns an implementation specific default value, typically the last-modified-time or a FileTime representing the epoch (1970-01-01T00:00:00Z).

It looks pretty much like the "problem" is related to your file system and your operating system. I don't think your code has anything wrong in it.

For example, for a windows operating system, the NtfsDisableLastAccessUpdate option was enabled by default in Vista and Windows 7, but you can disable it by using the following command line:

fsutil behavior set disablelastaccess 0

As I said in the comment to your question I was able to solve this problem in Windows in a real machine, but not in a virtual one. If you are still struggling with this issue then issue this command prior to anything to see whats going on with the registry:

fsutil behavior query disablelastaccess 

On a last note, I did not had to restart windows or Intellij (where I ran my tests). The results were immediate and I could see that for value 1 the timestamp for the last access does not change and for value 0 it does.

Bitartrate answered 11/5, 2016 at 9:43 Comment(0)
J
2

First, let's focus on what these things mean.

Access - the last time the file was read, i.e., the last time the file data was accessed.

Modify - the last time the file was modified (content has been modified), i.e., time when file data last modified.

Change - the last time meta data of the file was changed (e.g. permissions), i.e., time when file status was last changed.

Edit. The access time IS changing. I suggest you use Thread.sleep(100) or something and then see if this problem persists. If it does, the culprit would have to the be the OS you are running since Java simply reads from the filesystem. @Serge Ballesta's comments should give an understanding about the Windows NTFS having an option to disable writing every change made to the file attributes back to the hard drive for performance reasons. There is actually more to this.

From [docs],

NTFS delays updates to the last access time for a file by up to one hour after the last access. NTFS also permits last access time updates to be disabled. Last access time is not updated on NTFS volumes by default.

Following is some data from running the script on 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 


To enhance clarity, you can convert the milliseconds you have, to something more readable. The following code snippet will elaborate on that.
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;
Jinn answered 11/5, 2016 at 7:44 Comment(2)
This does not answer the question at all. It is not asking for conversion of millis. It is asking why the call to read does not affect last accesstime.Gouache
@RichardEriksson I apologize for the lack of clarity. I was expecting the first part of the answer to have answered that part of the question.Jinn
B
0

If you look into the api you have this.

If the file system implementation does not support a time stamp to indicate the time of last access then this method returns an implementation specific default value, typically the last-modified-time or a FileTime representing the epoch (1970-01-01T00:00:00Z).

It looks pretty much like the "problem" is related to your file system and your operating system. I don't think your code has anything wrong in it.

For example, for a windows operating system, the NtfsDisableLastAccessUpdate option was enabled by default in Vista and Windows 7, but you can disable it by using the following command line:

fsutil behavior set disablelastaccess 0

As I said in the comment to your question I was able to solve this problem in Windows in a real machine, but not in a virtual one. If you are still struggling with this issue then issue this command prior to anything to see whats going on with the registry:

fsutil behavior query disablelastaccess 

On a last note, I did not had to restart windows or Intellij (where I ran my tests). The results were immediate and I could see that for value 1 the timestamp for the last access does not change and for value 0 it does.

Bitartrate answered 11/5, 2016 at 9:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.