Java应用程序如何在Windows上获得无损文件修改时间(NTFS)?

时间:2014-08-04 14:11:47

标签: java windows file filesystems ntfs

Java有方法lastModified来获取File修改时间(long值),这是自纪元以来的毫秒数(1970年1月1日格林威治标准时间00:00:00) )。

似乎NTFS的文件时间分辨率为100 ns,数据范围从1601年1月开始。因此没有从NTFS时间到long值的无损转换。

JNI可能是获取NTFS时间戳的解决方案,但是可以有更简单的解决方案吗?

我只需要NTFS上的64-bit FILETIME值。也许Java应用程序有一些简单的方法可以获得它?

2 个答案:

答案 0 :(得分:0)

如果您使用的是Java 7或更高版本,则应调查java.nio.file包。

特别是,java.nio.file.attribute.FileTime可以解决您的问题。

答案 1 :(得分:0)

<强> 1。使用Powershell

long fileTimeUtc = 0;

InputStream inpStrm = Runtime.getRuntime().exec(new String[] {
    "powershell", "[System.IO.File]::GetLastWriteTimeUtc('" + fullFilename.replace("'", "''") + "').ToFileTimeUtc();"
}).getInputStream();

for (;;) {
    int incomingByte = inpStrm.read();
    if (incomingByte < 48 || incomingByte > 57) break;
    fileTimeUtc = fileTimeUtc * 10 + incomingByte - 48;
}

此ps命令的输出结尾总是有换行符。因此只需要检查字节值以结束循环。在这种情况下,对于PowerShell,单引号(&#39;)应该比双引号(&#34;)更安全,更容易。

如果文件不存在,则输出为0.

.net的{p> DateTime结构也具有100纳秒的分辨率,因此对于大多数实际应用,转换ToFileTimeUtc()应该是无损的(在此代码中不处理负long值,可以添加逻辑,虽然负面结果应该是不常见的)。 (对于一些罕见的情况,可能会出现问题,因为DateTime的时间范围是0001-9999,而NTFS的时间范围是1601-60056。)

<强> 2。使用可执行文件

同样,您总是可以编写native code来获取上次写入时间的值,然后Java可以运行该可执行文件来获取其输出。

#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
    HANDLE hFile;
    if( argc != 2 )
    {
        printf("0");
        return 1;
    }
    hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        printf("0");
        return 1;
    }
    FILETIME ftCreate, ftAccess, ftWrite;
    if (GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)){
        printf("%lld\n",*(long long *)(&ftWrite));
        CloseHandle(hFile);
        return 0;
    } else {
        printf("0");
        CloseHandle(hFile);
        return 1;
    }
}

然后用这样的短路径名称调用它:

Runtime.getRuntime().exec(new String[]{
    "cmd",
    "/c @echo off & for %I in (\""+fullFilename+"\") do a.exe %~fsI"
})

这种方式与第一种方式没那么不同,但如果没有转换,它会更直接。