Java有方法lastModified
来获取File
修改时间(long
值),这是自纪元以来的毫秒数(1970年1月1日格林威治标准时间00:00:00) )。
似乎NTFS的文件时间分辨率为100 ns,数据范围从1601年1月开始。因此没有从NTFS时间到long
值的无损转换。
JNI可能是获取NTFS时间戳的解决方案,但是可以有更简单的解决方案吗?
我只需要NTFS上的64-bit FILETIME值。也许Java应用程序有一些简单的方法可以获得它?
答案 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"
})
这种方式与第一种方式没那么不同,但如果没有转换,它会更直接。