28 import java.beans.ConstructorProperties; |
28 import java.beans.ConstructorProperties; |
29 import java.net.URI; |
29 import java.net.URI; |
30 import java.net.URL; |
30 import java.net.URL; |
31 import java.net.MalformedURLException; |
31 import java.net.MalformedURLException; |
32 import java.net.URISyntaxException; |
32 import java.net.URISyntaxException; |
33 import java.util.ArrayList; |
33 import java.util.*; |
34 import java.util.Map; |
34 import java.nio.file.*; |
35 import java.util.Hashtable; |
35 import java.nio.file.attribute.*; |
36 import java.util.Random; |
|
37 import java.security.AccessController; |
36 import java.security.AccessController; |
38 import java.security.AccessControlException; |
37 import java.security.PrivilegedAction; |
|
38 import java.security.SecureRandom; |
39 import sun.security.action.GetPropertyAction; |
39 import sun.security.action.GetPropertyAction; |
40 |
40 |
41 |
41 |
42 /** |
42 /** |
43 * An abstract representation of file and directory pathnames. |
43 * An abstract representation of file and directory pathnames. |
129 * |
129 * |
130 * <p> Instances of the <code>File</code> class are immutable; that is, once |
130 * <p> Instances of the <code>File</code> class are immutable; that is, once |
131 * created, the abstract pathname represented by a <code>File</code> object |
131 * created, the abstract pathname represented by a <code>File</code> object |
132 * will never change. |
132 * will never change. |
133 * |
133 * |
|
134 * <h4>Interoperability with {@code java.nio.file} package</h4> |
|
135 * |
|
136 * <p> The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a> |
|
137 * package defines interfaces and classes for the Java virtual machine to access |
|
138 * files, file attributes, and file systems. This API may be used to overcome |
|
139 * many of the limitations of the {@code java.io.File} class. |
|
140 * The {@link #toPath toPath} method may be used to obtain a {@link |
|
141 * Path} that uses the abstract path represented by a {@code File} object to |
|
142 * locate a file. The resulting {@code Path} provides more efficient and |
|
143 * extensive access to file attributes, additional file operations, and I/O |
|
144 * exceptions to help diagnose errors when an operation on a file fails. |
|
145 * |
134 * @author unascribed |
146 * @author unascribed |
135 * @since JDK1.0 |
147 * @since JDK1.0 |
136 */ |
148 */ |
137 |
149 |
138 public class File |
150 public class File |
661 * pathnames, however, this relationship typically does not hold when a |
675 * pathnames, however, this relationship typically does not hold when a |
662 * <tt>file:</tt> URI that is created in a virtual machine on one operating |
676 * <tt>file:</tt> URI that is created in a virtual machine on one operating |
663 * system is converted into an abstract pathname in a virtual machine on a |
677 * system is converted into an abstract pathname in a virtual machine on a |
664 * different operating system. |
678 * different operating system. |
665 * |
679 * |
|
680 * <p> Note that when this abstract pathname represents a UNC pathname then |
|
681 * all components of the UNC (including the server name component) are encoded |
|
682 * in the {@code URI} path. The authority component is undefined, meaning |
|
683 * that it is represented as {@code null}. The {@link Path} class defines the |
|
684 * {@link Path#toUri toUri} method to encode the server name in the authority |
|
685 * component of the resulting {@code URI}. The {@link #toPath toPath} method |
|
686 * may be used to obtain a {@code Path} representing this abstract pathname. |
|
687 * |
666 * @return An absolute, hierarchical URI with a scheme equal to |
688 * @return An absolute, hierarchical URI with a scheme equal to |
667 * <tt>"file"</tt>, a path representing this abstract pathname, |
689 * <tt>"file"</tt>, a path representing this abstract pathname, |
668 * and undefined authority, query, and fragment components |
690 * and undefined authority, query, and fragment components |
669 * @throws SecurityException If a required system property value cannot |
691 * @throws SecurityException If a required system property value cannot |
670 * be accessed. |
692 * be accessed. |
905 /** |
935 /** |
906 * Deletes the file or directory denoted by this abstract pathname. If |
936 * Deletes the file or directory denoted by this abstract pathname. If |
907 * this pathname denotes a directory, then the directory must be empty in |
937 * this pathname denotes a directory, then the directory must be empty in |
908 * order to be deleted. |
938 * order to be deleted. |
909 * |
939 * |
|
940 * <p> Note that the {@link Path} class defines the {@link Path#delete |
|
941 * delete} method to throw an {@link IOException} when a file cannot be |
|
942 * deleted. This is useful for error reporting and to diagnose why a file |
|
943 * cannot be deleted. The {@link #toPath toPath} method may be used to |
|
944 * obtain a {@code Path} representing this abstract pathname. |
|
945 * |
910 * @return <code>true</code> if and only if the file or directory is |
946 * @return <code>true</code> if and only if the file or directory is |
911 * successfully deleted; <code>false</code> otherwise |
947 * successfully deleted; <code>false</code> otherwise |
912 * |
948 * |
913 * @throws SecurityException |
949 * @throws SecurityException |
914 * If a security manager exists and its <code>{@link |
950 * If a security manager exists and its <code>{@link |
970 * complete path. |
1006 * complete path. |
971 * |
1007 * |
972 * <p> There is no guarantee that the name strings in the resulting array |
1008 * <p> There is no guarantee that the name strings in the resulting array |
973 * will appear in any specific order; they are not, in particular, |
1009 * will appear in any specific order; they are not, in particular, |
974 * guaranteed to appear in alphabetical order. |
1010 * guaranteed to appear in alphabetical order. |
|
1011 * |
|
1012 * <p> Note that the {@link Path} class defines the {@link |
|
1013 * Path#newDirectoryStream newDirectoryStream} method to open a directory |
|
1014 * and iterate over the names of the files in the directory. This may use |
|
1015 * less resources when working with very large directories. The {@link |
|
1016 * #toPath toPath} method may be used to obtain a {@code Path} representing |
|
1017 * this abstract pathname. |
975 * |
1018 * |
976 * @return An array of strings naming the files and directories in the |
1019 * @return An array of strings naming the files and directories in the |
977 * directory denoted by this abstract pathname. The array will be |
1020 * directory denoted by this abstract pathname. The array will be |
978 * empty if the directory is empty. Returns {@code null} if |
1021 * empty if the directory is empty. Returns {@code null} if |
979 * this abstract pathname does not denote a directory, or if an |
1022 * this abstract pathname does not denote a directory, or if an |
1022 public String[] list(FilenameFilter filter) { |
1065 public String[] list(FilenameFilter filter) { |
1023 String names[] = list(); |
1066 String names[] = list(); |
1024 if ((names == null) || (filter == null)) { |
1067 if ((names == null) || (filter == null)) { |
1025 return names; |
1068 return names; |
1026 } |
1069 } |
1027 ArrayList v = new ArrayList(); |
1070 List<String> v = new ArrayList<String>(); |
1028 for (int i = 0 ; i < names.length ; i++) { |
1071 for (int i = 0 ; i < names.length ; i++) { |
1029 if (filter.accept(this, names[i])) { |
1072 if (filter.accept(this, names[i])) { |
1030 v.add(names[i]); |
1073 v.add(names[i]); |
1031 } |
1074 } |
1032 } |
1075 } |
1033 return (String[])(v.toArray(new String[v.size()])); |
1076 return v.toArray(new String[v.size()]); |
1034 } |
1077 } |
1035 |
1078 |
1036 /** |
1079 /** |
1037 * Returns an array of abstract pathnames denoting the files in the |
1080 * Returns an array of abstract pathnames denoting the files in the |
1038 * directory denoted by this abstract pathname. |
1081 * directory denoted by this abstract pathname. |
1049 * the same directory. |
1092 * the same directory. |
1050 * |
1093 * |
1051 * <p> There is no guarantee that the name strings in the resulting array |
1094 * <p> There is no guarantee that the name strings in the resulting array |
1052 * will appear in any specific order; they are not, in particular, |
1095 * will appear in any specific order; they are not, in particular, |
1053 * guaranteed to appear in alphabetical order. |
1096 * guaranteed to appear in alphabetical order. |
|
1097 * |
|
1098 * <p> Note that the {@link Path} class defines the {@link |
|
1099 * Path#newDirectoryStream newDirectoryStream} method to open a directory |
|
1100 * and iterate over the names of the files in the directory. This may use |
|
1101 * less resources when working with very large directories. The {@link |
|
1102 * #toPath toPath} method may be used to obtain a {@code Path} representing |
|
1103 * this abstract pathname. |
1054 * |
1104 * |
1055 * @return An array of abstract pathnames denoting the files and |
1105 * @return An array of abstract pathnames denoting the files and |
1056 * directories in the directory denoted by this abstract pathname. |
1106 * directories in the directory denoted by this abstract pathname. |
1057 * The array will be empty if the directory is empty. Returns |
1107 * The array will be empty if the directory is empty. Returns |
1058 * {@code null} if this abstract pathname does not denote a |
1108 * {@code null} if this abstract pathname does not denote a |
1220 * file from one filesystem to another, it might not be atomic, and it |
1276 * file from one filesystem to another, it might not be atomic, and it |
1221 * might not succeed if a file with the destination abstract pathname |
1277 * might not succeed if a file with the destination abstract pathname |
1222 * already exists. The return value should always be checked to make sure |
1278 * already exists. The return value should always be checked to make sure |
1223 * that the rename operation was successful. |
1279 * that the rename operation was successful. |
1224 * |
1280 * |
|
1281 * <p> Note that the {@link Path} class defines the {@link Path#moveTo |
|
1282 * moveTo} method to move or rename a file in a platform independent manner. |
|
1283 * The {@link #toPath toPath} method may be used to obtain a {@code Path} |
|
1284 * representing this abstract pathname. |
|
1285 * |
1225 * @param dest The new abstract pathname for the named file |
1286 * @param dest The new abstract pathname for the named file |
1226 * |
1287 * |
1227 * @return <code>true</code> if and only if the renaming succeeded; |
1288 * @return <code>true</code> if and only if the renaming succeeded; |
1228 * <code>false</code> otherwise |
1289 * <code>false</code> otherwise |
1229 * |
1290 * |
1676 } |
1749 } |
1677 |
1750 |
1678 |
1751 |
1679 /* -- Temporary files -- */ |
1752 /* -- Temporary files -- */ |
1680 |
1753 |
1681 private static final Object tmpFileLock = new Object(); |
1754 private static class TemporaryDirectory { |
1682 |
1755 private TemporaryDirectory() { } |
1683 private static int counter = -1; /* Protected by tmpFileLock */ |
1756 |
1684 |
1757 static final String valueAsString = fs.normalize( |
1685 private static File generateFile(String prefix, String suffix, File dir) |
1758 AccessController.doPrivileged(new GetPropertyAction("java.io.tmpdir"))); |
1686 throws IOException |
1759 static final File valueAsFile = |
1687 { |
1760 new File(valueAsString, fs.prefixLength(valueAsString)); |
1688 if (counter == -1) { |
1761 |
1689 counter = new Random().nextInt() & 0xffff; |
1762 // file name generation |
1690 } |
1763 private static final SecureRandom random = new SecureRandom(); |
1691 counter++; |
1764 static File generateFile(String prefix, String suffix, File dir) { |
1692 return new File(dir, prefix + Integer.toString(counter) + suffix); |
1765 long n = random.nextLong(); |
1693 } |
1766 if (n == Long.MIN_VALUE) { |
1694 |
1767 n = 0; // corner case |
1695 private static String tmpdir; /* Protected by tmpFileLock */ |
1768 } else { |
1696 |
1769 n = Math.abs(n); |
1697 private static String getTempDir() { |
|
1698 if (tmpdir == null) |
|
1699 tmpdir = fs.normalize( |
|
1700 AccessController.doPrivileged( |
|
1701 new GetPropertyAction("java.io.tmpdir"))); |
|
1702 return tmpdir; |
|
1703 } |
|
1704 |
|
1705 private static boolean checkAndCreate(String filename, SecurityManager sm) |
|
1706 throws IOException |
|
1707 { |
|
1708 if (sm != null) { |
|
1709 try { |
|
1710 sm.checkWrite(filename); |
|
1711 } catch (AccessControlException x) { |
|
1712 /* Throwing the original AccessControlException could disclose |
|
1713 the location of the default temporary directory, so we |
|
1714 re-throw a more innocuous SecurityException */ |
|
1715 throw new SecurityException("Unable to create temporary file"); |
|
1716 } |
1770 } |
1717 } |
1771 return new File(dir, prefix + Long.toString(n) + suffix); |
1718 return fs.createFileExclusively(filename); |
1772 } |
|
1773 |
|
1774 // default file permissions |
|
1775 static final FileAttribute<Set<PosixFilePermission>> defaultPosixFilePermissions = |
|
1776 PosixFilePermissions.asFileAttribute(EnumSet |
|
1777 .of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)); |
|
1778 static final boolean isPosix = isPosix(); |
|
1779 static boolean isPosix() { |
|
1780 return AccessController.doPrivileged( |
|
1781 new PrivilegedAction<Boolean>() { |
|
1782 public Boolean run() { |
|
1783 try { |
|
1784 return FileSystems.getDefault().getPath(valueAsString) |
|
1785 .getFileStore().supportsFileAttributeView("posix"); |
|
1786 } catch (IOException e) { |
|
1787 throw new IOError(e); |
|
1788 } |
|
1789 } |
|
1790 }); |
|
1791 } |
1719 } |
1792 } |
1720 |
1793 |
1721 /** |
1794 /** |
1722 * <p> Creates a new empty file in the specified directory, using the |
1795 * <p> Creates a new empty file in the specified directory, using the |
1723 * given prefix and suffix strings to generate its name. If this method |
1796 * given prefix and suffix strings to generate its name. If this method |
1789 */ |
1862 */ |
1790 public static File createTempFile(String prefix, String suffix, |
1863 public static File createTempFile(String prefix, String suffix, |
1791 File directory) |
1864 File directory) |
1792 throws IOException |
1865 throws IOException |
1793 { |
1866 { |
1794 if (prefix == null) throw new NullPointerException(); |
|
1795 if (prefix.length() < 3) |
1867 if (prefix.length() < 3) |
1796 throw new IllegalArgumentException("Prefix string too short"); |
1868 throw new IllegalArgumentException("Prefix string too short"); |
1797 String s = (suffix == null) ? ".tmp" : suffix; |
1869 if (suffix == null) |
1798 synchronized (tmpFileLock) { |
1870 suffix = ".tmp"; |
1799 if (directory == null) { |
1871 |
1800 String tmpDir = getTempDir(); |
1872 File tmpdir = (directory != null) ? |
1801 directory = new File(tmpDir, fs.prefixLength(tmpDir)); |
1873 directory : TemporaryDirectory.valueAsFile; |
|
1874 SecurityManager sm = System.getSecurityManager(); |
|
1875 File f; |
|
1876 do { |
|
1877 f = TemporaryDirectory.generateFile(prefix, suffix, tmpdir); |
|
1878 if (sm != null) { |
|
1879 try { |
|
1880 sm.checkWrite(f.getPath()); |
|
1881 } catch (SecurityException se) { |
|
1882 // don't reveal temporary directory location |
|
1883 if (directory == null) |
|
1884 throw new SecurityException("Unable to create temporary file"); |
|
1885 throw se; |
|
1886 } |
1802 } |
1887 } |
1803 SecurityManager sm = System.getSecurityManager(); |
1888 } while (!fs.createFileExclusively(f.getPath())); |
1804 File f; |
1889 return f; |
1805 do { |
|
1806 f = generateFile(prefix, s, directory); |
|
1807 } while (!checkAndCreate(f.getPath(), sm)); |
|
1808 return f; |
|
1809 } |
|
1810 } |
1890 } |
1811 |
1891 |
1812 /** |
1892 /** |
1813 * Creates an empty file in the default temporary-file directory, using |
1893 * Creates an empty file in the default temporary-file directory, using |
1814 * the given prefix and suffix to generate its name. Invoking this method |
1894 * the given prefix and suffix to generate its name. Invoking this method |
1842 throws IOException |
1922 throws IOException |
1843 { |
1923 { |
1844 return createTempFile(prefix, suffix, null); |
1924 return createTempFile(prefix, suffix, null); |
1845 } |
1925 } |
1846 |
1926 |
|
1927 /** |
|
1928 * Creates an empty file in the default temporary-file directory, using |
|
1929 * the given prefix and suffix to generate its name. This method is |
|
1930 * equivalent to invoking the {@link #createTempFile(String,String) |
|
1931 * createTempFile(prefix, suffix)} method with the addition that the |
|
1932 * resulting pathname may be requested to be deleted when the Java virtual |
|
1933 * machine terminates, and the initial file attributes to set atomically |
|
1934 * when creating the file may be specified. |
|
1935 * |
|
1936 * <p> When the value of the {@code deleteOnExit} method is {@code true} |
|
1937 * then the resulting file is requested to be deleted when the Java virtual |
|
1938 * machine terminates as if by invoking the {@link #deleteOnExit deleteOnExit} |
|
1939 * method. |
|
1940 * |
|
1941 * <p> The {@code attrs} parameter is an optional array of {@link FileAttribute |
|
1942 * attributes} to set atomically when creating the file. Each attribute is |
|
1943 * identified by its {@link FileAttribute#name name}. If more than one attribute |
|
1944 * of the same name is included in the array then all but the last occurrence |
|
1945 * is ignored. |
|
1946 * |
|
1947 * @param prefix |
|
1948 * The prefix string to be used in generating the file's |
|
1949 * name; must be at least three characters long |
|
1950 * @param suffix |
|
1951 * The suffix string to be used in generating the file's |
|
1952 * name; may be {@code null}, in which case the suffix |
|
1953 * {@code ".tmp"} will be used |
|
1954 * @param deleteOnExit |
|
1955 * {@code true} if the file denoted by resulting pathname be |
|
1956 * deleted when the Java virtual machine terminates |
|
1957 * @param attrs |
|
1958 * An optional list of file attributes to set atomically when creating |
|
1959 * the file |
|
1960 * |
|
1961 * @return An abstract pathname denoting a newly-created empty file |
|
1962 * |
|
1963 * @throws IllegalArgumentException |
|
1964 * If the <code>prefix</code> argument contains fewer than three |
|
1965 * characters |
|
1966 * @throws UnsupportedOperationException |
|
1967 * If the array contains an attribute that cannot be set atomically |
|
1968 * when creating the file |
|
1969 * @throws IOException |
|
1970 * If a file could not be created |
|
1971 * @throws SecurityException |
|
1972 * If a security manager exists and its <code>{@link |
|
1973 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> |
|
1974 * method does not allow a file to be created. When the {@code |
|
1975 * deleteOnExit} parameter has the value {@code true} then the |
|
1976 * security manager's {@link |
|
1977 * java.lang.SecurityManager#checkDelete(java.lang.String)} is |
|
1978 * invoked to check delete access to the file. |
|
1979 * @since 1.7 |
|
1980 */ |
|
1981 public static File createTempFile(String prefix, |
|
1982 String suffix, |
|
1983 boolean deleteOnExit, |
|
1984 FileAttribute<?>... attrs) |
|
1985 throws IOException |
|
1986 { |
|
1987 if (prefix.length() < 3) |
|
1988 throw new IllegalArgumentException("Prefix string too short"); |
|
1989 suffix = (suffix == null) ? ".tmp" : suffix; |
|
1990 |
|
1991 // special case POSIX environments so that 0600 is used as the file mode |
|
1992 if (TemporaryDirectory.isPosix) { |
|
1993 if (attrs.length == 0) { |
|
1994 // no attributes so use default permissions |
|
1995 attrs = new FileAttribute<?>[1]; |
|
1996 attrs[0] = TemporaryDirectory.defaultPosixFilePermissions; |
|
1997 } else { |
|
1998 // check if posix permissions given; if not use default |
|
1999 boolean hasPermissions = false; |
|
2000 for (int i=0; i<attrs.length; i++) { |
|
2001 if (attrs[i].name().equals("posix:permissions")) { |
|
2002 hasPermissions = true; |
|
2003 break; |
|
2004 } |
|
2005 } |
|
2006 if (!hasPermissions) { |
|
2007 FileAttribute<?>[] copy = new FileAttribute<?>[attrs.length+1]; |
|
2008 System.arraycopy(attrs, 0, copy, 0, attrs.length); |
|
2009 attrs = copy; |
|
2010 attrs[attrs.length-1] = |
|
2011 TemporaryDirectory.defaultPosixFilePermissions; |
|
2012 } |
|
2013 } |
|
2014 } |
|
2015 |
|
2016 // use Path#createFile to create file |
|
2017 SecurityManager sm = System.getSecurityManager(); |
|
2018 for (;;) { |
|
2019 File f = TemporaryDirectory |
|
2020 .generateFile(prefix, suffix, TemporaryDirectory.valueAsFile); |
|
2021 if (sm != null && deleteOnExit) |
|
2022 sm.checkDelete(f.getPath()); |
|
2023 try { |
|
2024 f.toPath().createFile(attrs); |
|
2025 if (deleteOnExit) |
|
2026 DeleteOnExitHook.add(f.getPath()); |
|
2027 return f; |
|
2028 } catch (InvalidPathException e) { |
|
2029 // don't reveal temporary directory location |
|
2030 if (sm != null) |
|
2031 throw new IllegalArgumentException("Invalid prefix or suffix"); |
|
2032 throw e; |
|
2033 } catch (SecurityException e) { |
|
2034 // don't reveal temporary directory location |
|
2035 if (sm != null) |
|
2036 throw new SecurityException("Unable to create temporary file"); |
|
2037 throw e; |
|
2038 } catch (FileAlreadyExistsException e) { |
|
2039 // ignore |
|
2040 } |
|
2041 } |
|
2042 } |
1847 |
2043 |
1848 /* -- Basic infrastructure -- */ |
2044 /* -- Basic infrastructure -- */ |
1849 |
2045 |
1850 /** |
2046 /** |
1851 * Compares two abstract pathnames lexicographically. The ordering |
2047 * Compares two abstract pathnames lexicographically. The ordering |
1961 } |
2157 } |
1962 } |
2158 } |
1963 ); |
2159 ); |
1964 } |
2160 } |
1965 |
2161 |
1966 |
2162 // -- Integration with java.nio.file -- |
|
2163 |
|
2164 private volatile transient Path filePath; |
|
2165 |
|
2166 /** |
|
2167 * Returns a {@link Path java.nio.file.Path} object constructed from the |
|
2168 * this abstract path. The first invocation of this method works as if |
|
2169 * invoking it were equivalent to evaluating the expression: |
|
2170 * <blockquote><pre> |
|
2171 * {@link FileSystems#getDefault FileSystems.getDefault}().{@link FileSystem#getPath getPath}(this.{@link #getPath getPath}()); |
|
2172 * </pre></blockquote> |
|
2173 * Subsequent invocations of this method return the same {@code Path}. |
|
2174 * |
|
2175 * <p> If this abstract pathname is the empty abstract pathname then this |
|
2176 * method returns a {@code Path} that may be used to access to the current |
|
2177 * user directory. |
|
2178 * |
|
2179 * @return A {@code Path} constructed from this abstract path. The resulting |
|
2180 * {@code Path} is associated with the {@link FileSystems#getDefault |
|
2181 * default-filesystem}. |
|
2182 * |
|
2183 * @throws InvalidPathException |
|
2184 * If a {@code Path} object cannot be constructed from the abstract |
|
2185 * path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath}) |
|
2186 * |
|
2187 * @since 1.7 |
|
2188 */ |
|
2189 public Path toPath() { |
|
2190 if (filePath == null) { |
|
2191 synchronized (this) { |
|
2192 if (filePath == null) { |
|
2193 if (path.length() == 0) { |
|
2194 // assume default file system treats "." as current directory |
|
2195 filePath = Paths.get("."); |
|
2196 } else { |
|
2197 filePath = Paths.get(path); |
|
2198 } |
|
2199 } |
|
2200 } |
|
2201 } |
|
2202 return filePath; |
|
2203 } |
1967 } |
2204 } |