关于Windows:如何使用Java发现文件的创建时间?

关于Windows:如何使用Java发现文件的创建时间?

How to discover a File's creation time with Java?

是否有一种简便的方法来使用Java发现文件的创建时间? File类仅具有一种获取"上次修改"时间的方法。根据我在Google上发现的一些资源,File类不提供getCreationTime()方法,因为并非所有文件系统都支持创建时间的想法。

我发现唯一可行的解??决方案是卷入命令行并执行" dir"命令,该命令看起来像输出文件的创建时间。我想这可行,我只需要支持Windows,但是我似乎很容易出错。

是否有任何第三方图书馆提供我所需的信息?

更新:最后,我认为购买第三方库对我来说不值得,但是它们的API看起来确实不错,因此对于任何有此问题的人来说,它都是一个不错的选择。


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

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

请注意,并非所有操作系统都提供此信息。我相信在这些情况下,这会返回mtime,这是最后修改的时间。

Windows确实提供了创建时间。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// 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 ????–?????—?é—′????????o?—?é—′?€???€???????"1??é—′???????è??é—???é—′??");
            System.out.println ("
?"¨?3????");
            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 ("   ?????o?—?é—′???" + ct);
                System.out.println ("   ????"1??é—′???" + 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 (?????????"1?—?é—′) ??????");
            }
            else
            {
                //System.out.println ("SetFileTime ?¤±è′¥");
            }
        }
    }
}


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

1
2
3
4
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及更高版本。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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

*/

我一直在自己进行调查,但是我需要一些可以在Windows / * nix平台上运行的工具。

一篇SO帖子中包含指向Posix JNI实现的一些链接。

  • JNA-POSIX
  • 适用于Java的POSIX

尤其是,JNA-POSIX通过Windows,BSD,Solaris,Linux和OSX的实现来实现获取文件统计信息的方法。

总的来说,它看起来非常有前途,所以我将很快在自己的项目中进行尝试。


我喜欢jGuru上的答案,其中列出了使用JNI获得答案的选项。这可能比脱壳要快,而且您可能会遇到其他情况,例如需要专门针对Windows实施的情况。

此外,如果您需要移植到其他平台,那么也可以移植您的库,并在* ix上让它返回-1,以回答该问题。


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

1
2
3
4
5
6
7
8
   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());
    }


推荐阅读