如何使用Java查找文件的创建时间?

24

有没有一种简单的方法用Java发现文件的创建时间?File类只提供了一个获取“最后修改”时间的方法。根据我在Google上找到的一些资源,File类没有提供getCreationTime()方法是因为并非所有文件系统都支持创建时间的概念。

我找到的唯一可行的解决方案是通过调用命令行并执行“dir”命令来查找文件的创建时间。我想这种方法可以工作,因为我只需要支持Windows,但它似乎很容易出错。

有没有第三方库提供我需要的信息呢?

更新:最终,我不认为值得购买第三方库,但它们的API似乎非常好,所以对于其他遇到这个问题的人来说可能是一个不错的选择。


我检查了Apache Commons VFS,其中虚拟文件系统可以导出一组丰富的功能。但不幸的是,没有定义CREATION_TIME能力。 - Lenik
据我所知,NIO-2可以解决这个问题,但尚未发布(应该在第7个版本中)。例如,请参见http://java.sun.com/developer/technicalArticles/javase/nio/和http://today.java.net/article/2009/10/14/sweeping-file-system-nio-2。 - Petr Gladkikh
7个回答

21

随着Java 7的发布,现在有一种内置的方法可以实现这一点:

Path path = Paths.get("path/to/file");
BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
FileTime creationTime = attributes.creationTime();

需要注意的是,并非所有操作系统都提供此信息。在这种情况下,我相信该返回修改时间(mtime),也就是最后修改的时间。

Windows 提供创建时间。


8

我几天前写了一个小测试类,希望它能对你有所帮助:

// Get/Set windows file CreationTime/LastWriteTime/LastAccessTime
// Test with jna-3.2.7
// [http://maclife.net/wiki/index.php?title=Java_get_and_set_windows_system_file_creation_time_via_JNA_(Java_Native_Access)][1]

import java.io.*;
import java.nio.*;
import java.util.Date;

// Java Native Access library: jna.dev.java.net
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.*;
import com.sun.jna.platform.win32.*;

public class WindowsFileTime
{
    public static final int GENERIC_READ = 0x80000000;
    //public static final int GENERIC_WRITE = 0x40000000;   // defined in com.sun.jna.platform.win32.WinNT
    public static final int GENERIC_EXECUTE = 0x20000000;
    public static final int GENERIC_ALL = 0x10000000;

    // defined in com.sun.jna.platform.win32.WinNT
    //public static final int CREATE_NEW = 1;
    //public static final int CREATE_ALWAYS = 2;
    //public static final int OPEN_EXISTING = 3;
    //public static final int OPEN_ALWAYS = 4;
    //public static final int TRUNCATE_EXISTING = 5;

    public interface MoreKernel32 extends Kernel32
    {
        static final MoreKernel32 instance = (MoreKernel32)Native.loadLibrary ("kernel32", MoreKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
        boolean GetFileTime (WinNT.HANDLE hFile, WinBase.FILETIME lpCreationTime, WinBase.FILETIME lpLastAccessTime, WinBase.FILETIME lpLastWriteTime);
        boolean SetFileTime (WinNT.HANDLE hFile, final WinBase.FILETIME lpCreationTime, final WinBase.FILETIME lpLastAccessTime, final WinBase.FILETIME lpLastWriteTime);
    }

    static MoreKernel32 win32 = MoreKernel32.instance;
    //static Kernel32 _win32 = (Kernel32)win32;

    static WinBase.FILETIME _creationTime = new WinBase.FILETIME ();
    static WinBase.FILETIME _lastWriteTime = new WinBase.FILETIME ();
    static WinBase.FILETIME _lastAccessTime = new WinBase.FILETIME ();

    static boolean GetFileTime (String sFileName, Date creationTime, Date lastWriteTime, Date lastAccessTime)
    {
        WinNT.HANDLE hFile = OpenFile (sFileName, GENERIC_READ);    // may be WinNT.GENERIC_READ in future jna version.
        if (hFile == WinBase.INVALID_HANDLE_VALUE) return false;

        boolean rc = win32.GetFileTime (hFile, _creationTime, _lastAccessTime, _lastWriteTime);
        if (rc)
        {
            if (creationTime != null) creationTime.setTime (_creationTime.toLong());
            if (lastAccessTime != null) lastAccessTime.setTime (_lastAccessTime.toLong());
            if (lastWriteTime != null) lastWriteTime.setTime (_lastWriteTime.toLong());
        }
        else
        {
            int iLastError = win32.GetLastError();
            System.out.print ("获取文件时间失败,错误码:" + iLastError + " " + GetWindowsSystemErrorMessage (iLastError));
        }
        win32.CloseHandle (hFile);
        return rc;
    }
    static boolean SetFileTime (String sFileName, final Date creationTime, final Date lastWriteTime, final Date lastAccessTime)
    {
        WinNT.HANDLE hFile = OpenFile (sFileName, WinNT.GENERIC_WRITE);
        if (hFile == WinBase.INVALID_HANDLE_VALUE) return false;

        ConvertDateToFILETIME (creationTime, _creationTime);
        ConvertDateToFILETIME (lastWriteTime, _lastWriteTime);
        ConvertDateToFILETIME (lastAccessTime, _lastAccessTime);

        //System.out.println ("creationTime: " + creationTime);
        //System.out.println ("lastWriteTime: " + lastWriteTime);
        //System.out.println ("lastAccessTime: " + lastAccessTime);

        //System.out.println ("_creationTime: " + _creationTime);
        //System.out.println ("_lastWriteTime: " + _lastWriteTime);
        //System.out.println ("_lastAccessTime: " + _lastAccessTime);

        boolean rc = win32.SetFileTime (hFile, creationTime==null?null:_creationTime, lastAccessTime==null?null:_lastAccessTime, lastWriteTime==null?null:_lastWriteTime);
        if (! rc)
        {
            int iLastError = win32.GetLastError();
            System.out.print ("设置文件时间失败,错误码:" + iLastError + " " + GetWindowsSystemErrorMessage (iLastError));
        }
        win32.CloseHandle (hFile);
        return rc;
    }
    static void ConvertDateToFILETIME (Date date, WinBase.FILETIME ft)
    {
        if (ft != null)
        {
            long iFileTime = 0;
            if (date != null)
            {
                iFileTime = WinBase.FILETIME.dateToFileTime (date);
                ft.dwHighDateTime = (int)((iFileTime >> 32) & 0xFFFFFFFFL);
                ft.dwLowDateTime = (int)(iFileTime & 0xFFFFFFFFL);
            }
            else
            {
                ft.dwHighDateTime = 0;
                ft.dwLowDateTime = 0;
            }
        }
    }

    static WinNT.HANDLE OpenFile (String sFileName, int dwDesiredAccess)
    {
        WinNT.HANDLE hFile = win32.CreateFile (
            sFileName,
            dwDesiredAccess,
            0,
            null,
            WinNT.OPEN_EXISTING,
            0,
            null
            );
        if (hFile == WinBase.INVALID_HANDLE_VALUE)
        {
            int iLastError = win32.GetLastError();
            System.out.print (" 打开文件失败,错误码:" + iLastError + " " + GetWindowsSystemErrorMessage (iLastError));
        }
        return hFile;
    }
    static String GetWindowsSystemErrorMessage (int iError)
    {
        char[] buf = new char[255];
        CharBuffer bb = CharBuffer.wrap (buf);
        //bb.clear ();
        //PointerByReference pMsgBuf = new PointerByReference ();
        int iChar = win32.FormatMessage (
                WinBase.FORMAT_MESSAGE_FROM_SYSTEM
                    //| WinBase.FORMAT_MESSAGE_IGNORE_INSERTS
                    //|WinBase.FORMAT_MESSAGE_ALLOCATE_BUFFER
                    ,
                null,
                iError,
                0x0804,
                bb, buf.length,
                //pMsgBuf, 0,
                null
            );
        //for (int i=0; i<iChar; i++)
        //{
        //  System.out.print (" ");
        //  System.out.print (String.format("%02X", buf[i]&0xFFFF));
        //}
        bb.limit (iChar);
        //System.out.print (bb);
        //System.out.print (pMsgBuf.getValue().getString(0));
        //win32.LocalFree (pMsgBuf.getValue());
        return bb.toString ();
    }

    public static void main (String[] args) throws Exception
    {
        if (args.length == 0)
        {
            System.out.println ("获取 Windows 的文件时间(创建时间、最后修改时间、最后访问时间)");
            System.out.println ("用法:");
            System.out.println ("   java -cp .;..;jna.jar;platform.jar WindowsFileTime [文件名1] [文件名2]...");
            return;
        }

        boolean rc;
        java.sql.Timestamp ct = new java.sql.Timestamp(0);
        java.sql.Timestamp wt = new java.sql.Timestamp(0);
        java.sql.Timestamp at = new java.sql.Timestamp(0);

        for (String sFileName : args)
        {
            System.out.println ("文件 " + sFileName);

            rc = GetFileTime (sFileName, ct, wt, at);
            if (rc)
            {
                System.out.println ("   创建时间:" + ct);
                System.out.println ("   修改时间:" + wt);
                System.out.println ("   访问时间:" + at);
            }
            else
            {
                //System.out.println ("GetFileTime 失败");
            }


            //wt.setTime (System.currentTimeMillis());
            wt = java.sql.Timestamp.valueOf("2010-07-23 00:00:00");
            rc = SetFileTime (sFileName, null, wt, null);
            if (rc)
            {
                System.out.println ("SetFileTime (最后修改时间) 成功");
            }
            else
            {
                //System.out.println ("SetFileTime 失败");
            }
        }
    }
}

2
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class CreateDateInJava {
    public static void main(String args[]) {
        try {

            // get runtime environment and execute child process
            Runtime systemShell = Runtime.getRuntime();
            BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("Enter filename: ");
            String fname = (String) br1.readLine();
            Process output = systemShell.exec("cmd /c dir \"" + fname + "\" /tc");

            System.out.println(output);
            // open reader to get output from process
            BufferedReader br = new BufferedReader(new InputStreamReader(output.getInputStream()));

            String out = "";
            String line = null;

            int step = 1;
            while ((line = br.readLine()) != null) {
                if (step == 6) {
                    out = line;
                }
                step++;
            }

            // display process output
            try {
                out = out.replaceAll(" ", "");
                System.out.println("CreationDate: " + out.substring(0, 10));
                System.out.println("CreationTime: " + out.substring(10, 16) + "m");
            } catch (StringIndexOutOfBoundsException se) {
                System.out.println("File not found");
            }
        } catch (IOException ioe) {
            System.err.println(ioe);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

/**
D:\Foldername\Filename.Extension

Ex:
Enter Filename :
D:\Kamal\Test.txt
CreationDate: 02/14/2011
CreationTime: 12:59Pm

*/

2

javaxt-core库包含一个File类,可用于检索文件属性,包括创建时间。例如:

javaxt.io.File file = new javaxt.io.File("/temp/file.txt");
System.out.println("Created: " + file.getCreationTime());
System.out.println("Accessed: " + file.getLastAccessTime());
System.out.println("Modified: " + file.getLastModifiedTime());

可与Java 1.5及以上版本兼容。


2
我一直在自己进行调查,但我需要一个可以在Windows/*nix平台上工作的东西。
一个SO帖子包括一些指向Posix JNI实现的链接。 特别是,JNA-POSIX实现了获取文件统计信息的方法,并提供了Windows, BSD, Solaris, Linux和OSX的实现。
总的来说,看起来非常有前途,所以我很快就会在自己的项目中尝试它。

1

我喜欢jGuru上列出使用JNI获取答案的选项的回答。这可能比外壳更快,而且您可能会遇到其他需要专门为Windows实现的情况。

此外,如果您需要将其移植到不同的平台,则也可以将库移植并仅使其返回-1作为*ix上此问题的答案。


0

这是一个基本的Java示例,使用BasicFileAttributes类:

   Path path = Paths.get("C:\\Users\\jorgesys\\workspaceJava\\myfile.txt");
    BasicFileAttributes attr;
    try {
      attr = Files.readAttributes(path, BasicFileAttributes.class);
      System.out.println("File creation time: " + attr.creationTime());
    } catch (IOException e) {
      System.out.println("oops un error! " + e.getMessage());
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接