Path: blob/master/src/java.base/share/classes/java/io/File.java
41152 views
/*1* Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.io;2627import java.net.URI;28import java.net.URL;29import java.net.MalformedURLException;30import java.net.URISyntaxException;31import java.nio.file.FileStore;32import java.nio.file.FileSystems;33import java.nio.file.Path;34import java.security.SecureRandom;35import java.util.ArrayList;36import java.util.List;37import sun.security.action.GetPropertyAction;3839/**40* An abstract representation of file and directory pathnames.41*42* <p> User interfaces and operating systems use system-dependent <em>pathname43* strings</em> to name files and directories. This class presents an44* abstract, system-independent view of hierarchical pathnames. An45* <em>abstract pathname</em> has two components:46*47* <ol>48* <li> An optional system-dependent <em>prefix</em> string,49* such as a disk-drive specifier, {@code "/"} for the UNIX root50* directory, or {@code "\\\\"} for a Microsoft Windows UNC pathname, and51* <li> A sequence of zero or more string <em>names</em>.52* </ol>53*54* The first name in an abstract pathname may be a directory name or, in the55* case of Microsoft Windows UNC pathnames, a hostname. Each subsequent name56* in an abstract pathname denotes a directory; the last name may denote57* either a directory or a file. The <em>empty</em> abstract pathname has no58* prefix and an empty name sequence.59*60* <p> The conversion of a pathname string to or from an abstract pathname is61* inherently system-dependent. When an abstract pathname is converted into a62* pathname string, each name is separated from the next by a single copy of63* the default <em>separator character</em>. The default name-separator64* character is defined by the system property {@code file.separator}, and65* is made available in the public static fields {@link66* #separator} and {@link #separatorChar} of this class.67* When a pathname string is converted into an abstract pathname, the names68* within it may be separated by the default name-separator character or by any69* other name-separator character that is supported by the underlying system.70*71* <p> A pathname, whether abstract or in string form, may be either72* <em>absolute</em> or <em>relative</em>. An absolute pathname is complete in73* that no other information is required in order to locate the file that it74* denotes. A relative pathname, in contrast, must be interpreted in terms of75* information taken from some other pathname. By default the classes in the76* {@code java.io} package always resolve relative pathnames against the77* current user directory. This directory is named by the system property78* {@code user.dir}, and is typically the directory in which the Java79* virtual machine was invoked.80*81* <p> The <em>parent</em> of an abstract pathname may be obtained by invoking82* the {@link #getParent} method of this class and consists of the pathname's83* prefix and each name in the pathname's name sequence except for the last.84* Each directory's absolute pathname is an ancestor of any {@code File}85* object with an absolute abstract pathname which begins with the directory's86* absolute pathname. For example, the directory denoted by the abstract87* pathname {@code "/usr"} is an ancestor of the directory denoted by the88* pathname {@code "/usr/local/bin"}.89*90* <p> The prefix concept is used to handle root directories on UNIX platforms,91* and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,92* as follows:93*94* <ul>95*96* <li> For UNIX platforms, the prefix of an absolute pathname is always97* {@code "/"}. Relative pathnames have no prefix. The abstract pathname98* denoting the root directory has the prefix {@code "/"} and an empty99* name sequence.100*101* <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive102* specifier consists of the drive letter followed by {@code ":"} and103* possibly followed by {@code "\\"} if the pathname is absolute. The104* prefix of a UNC pathname is {@code "\\\\"}; the hostname and the share105* name are the first two names in the name sequence. A relative pathname that106* does not specify a drive has no prefix.107*108* </ul>109*110* <p> Instances of this class may or may not denote an actual file-system111* object such as a file or a directory. If it does denote such an object112* then that object resides in a <i>partition</i>. A partition is an113* operating system-specific portion of storage for a file system. A single114* storage device (e.g. a physical disk-drive, flash memory, CD-ROM) may115* contain multiple partitions. The object, if any, will reside on the116* partition <a id="partName">named</a> by some ancestor of the absolute117* form of this pathname.118*119* <p> A file system may implement restrictions to certain operations on the120* actual file-system object, such as reading, writing, and executing. These121* restrictions are collectively known as <i>access permissions</i>. The file122* system may have multiple sets of access permissions on a single object.123* For example, one set may apply to the object's <i>owner</i>, and another124* may apply to all other users. The access permissions on an object may125* cause some methods in this class to fail.126*127* <p> Instances of the {@code File} class are immutable; that is, once128* created, the abstract pathname represented by a {@code File} object129* will never change.130*131* <h2>Interoperability with {@code java.nio.file} package</h2>132*133* <p> The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a>134* package defines interfaces and classes for the Java virtual machine to access135* files, file attributes, and file systems. This API may be used to overcome136* many of the limitations of the {@code java.io.File} class.137* The {@link #toPath toPath} method may be used to obtain a {@link138* Path} that uses the abstract path represented by a {@code File} object to139* locate a file. The resulting {@code Path} may be used with the {@link140* java.nio.file.Files} class to provide more efficient and extensive access to141* additional file operations, file attributes, and I/O exceptions to help142* diagnose errors when an operation on a file fails.143*144* @since 1.0145*/146147public class File148implements Serializable, Comparable<File>149{150151/**152* The FileSystem object representing the platform's local file system.153*/154private static final FileSystem fs = DefaultFileSystem.getFileSystem();155156/**157* This abstract pathname's normalized pathname string. A normalized158* pathname string uses the default name-separator character and does not159* contain any duplicate or redundant separators.160*161* @serial162*/163private final String path;164165/**166* Enum type that indicates the status of a file path.167*/168private static enum PathStatus { INVALID, CHECKED };169170/**171* The flag indicating whether the file path is invalid.172*/173private transient PathStatus status = null;174175/**176* Check if the file has an invalid path. Currently, the inspection of177* a file path is very limited, and it only covers Nul character check.178* Returning true means the path is definitely invalid/garbage. But179* returning false does not guarantee that the path is valid.180*181* @return true if the file path is invalid.182*/183final boolean isInvalid() {184PathStatus s = status;185if (s == null) {186s = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED187: PathStatus.INVALID;188status = s;189}190return s == PathStatus.INVALID;191}192193/**194* The length of this abstract pathname's prefix, or zero if it has no195* prefix.196*/197private final transient int prefixLength;198199/**200* Returns the length of this abstract pathname's prefix.201* For use by FileSystem classes.202*/203int getPrefixLength() {204return prefixLength;205}206207/**208* The system-dependent default name-separator character. This field is209* initialized to contain the first character of the value of the system210* property {@code file.separator}. On UNIX systems the value of this211* field is {@code '/'}; on Microsoft Windows systems it is {@code '\\'}.212*213* @see java.lang.System#getProperty(java.lang.String)214*/215public static final char separatorChar = fs.getSeparator();216217/**218* The system-dependent default name-separator character, represented as a219* string for convenience. This string contains a single character, namely220* {@link #separatorChar}.221*/222public static final String separator = "" + separatorChar;223224/**225* The system-dependent path-separator character. This field is226* initialized to contain the first character of the value of the system227* property {@code path.separator}. This character is used to228* separate filenames in a sequence of files given as a <em>path list</em>.229* On UNIX systems, this character is {@code ':'}; on Microsoft Windows systems it230* is {@code ';'}.231*232* @see java.lang.System#getProperty(java.lang.String)233*/234public static final char pathSeparatorChar = fs.getPathSeparator();235236/**237* The system-dependent path-separator character, represented as a string238* for convenience. This string contains a single character, namely239* {@link #pathSeparatorChar}.240*/241public static final String pathSeparator = "" + pathSeparatorChar;242243244/* -- Constructors -- */245246/**247* Internal constructor for already-normalized pathname strings.248*/249private File(String pathname, int prefixLength) {250this.path = pathname;251this.prefixLength = prefixLength;252}253254/**255* Internal constructor for already-normalized pathname strings.256* The parameter order is used to disambiguate this method from the257* public(File, String) constructor.258*/259private File(String child, File parent) {260assert parent.path != null;261assert (!parent.path.isEmpty());262this.path = fs.resolve(parent.path, child);263this.prefixLength = parent.prefixLength;264}265266/**267* Creates a new {@code File} instance by converting the given268* pathname string into an abstract pathname. If the given string is269* the empty string, then the result is the empty abstract pathname.270*271* @param pathname A pathname string272* @throws NullPointerException273* If the {@code pathname} argument is {@code null}274*/275public File(String pathname) {276if (pathname == null) {277throw new NullPointerException();278}279this.path = fs.normalize(pathname);280this.prefixLength = fs.prefixLength(this.path);281}282283/* Note: The two-argument File constructors do not interpret an empty284parent abstract pathname as the current user directory. An empty parent285instead causes the child to be resolved against the system-dependent286directory defined by the FileSystem.getDefaultParent method. On Unix287this default is "/", while on Microsoft Windows it is "\\". This is required for288compatibility with the original behavior of this class. */289290/**291* Creates a new {@code File} instance from a parent pathname string292* and a child pathname string.293*294* <p> If {@code parent} is {@code null} then the new295* {@code File} instance is created as if by invoking the296* single-argument {@code File} constructor on the given297* {@code child} pathname string.298*299* <p> Otherwise the {@code parent} pathname string is taken to denote300* a directory, and the {@code child} pathname string is taken to301* denote either a directory or a file. If the {@code child} pathname302* string is absolute then it is converted into a relative pathname in a303* system-dependent way. If {@code parent} is the empty string then304* the new {@code File} instance is created by converting305* {@code child} into an abstract pathname and resolving the result306* against a system-dependent default directory. Otherwise each pathname307* string is converted into an abstract pathname and the child abstract308* pathname is resolved against the parent.309*310* @param parent The parent pathname string311* @param child The child pathname string312* @throws NullPointerException313* If {@code child} is {@code null}314*/315public File(String parent, String child) {316if (child == null) {317throw new NullPointerException();318}319if (parent != null) {320if (parent.isEmpty()) {321this.path = fs.resolve(fs.getDefaultParent(),322fs.normalize(child));323} else {324this.path = fs.resolve(fs.normalize(parent),325fs.normalize(child));326}327} else {328this.path = fs.normalize(child);329}330this.prefixLength = fs.prefixLength(this.path);331}332333/**334* Creates a new {@code File} instance from a parent abstract335* pathname and a child pathname string.336*337* <p> If {@code parent} is {@code null} then the new338* {@code File} instance is created as if by invoking the339* single-argument {@code File} constructor on the given340* {@code child} pathname string.341*342* <p> Otherwise the {@code parent} abstract pathname is taken to343* denote a directory, and the {@code child} pathname string is taken344* to denote either a directory or a file. If the {@code child}345* pathname string is absolute then it is converted into a relative346* pathname in a system-dependent way. If {@code parent} is the empty347* abstract pathname then the new {@code File} instance is created by348* converting {@code child} into an abstract pathname and resolving349* the result against a system-dependent default directory. Otherwise each350* pathname string is converted into an abstract pathname and the child351* abstract pathname is resolved against the parent.352*353* @param parent The parent abstract pathname354* @param child The child pathname string355* @throws NullPointerException356* If {@code child} is {@code null}357*/358public File(File parent, String child) {359if (child == null) {360throw new NullPointerException();361}362if (parent != null) {363if (parent.path.isEmpty()) {364this.path = fs.resolve(fs.getDefaultParent(),365fs.normalize(child));366} else {367this.path = fs.resolve(parent.path,368fs.normalize(child));369}370} else {371this.path = fs.normalize(child);372}373this.prefixLength = fs.prefixLength(this.path);374}375376/**377* Creates a new {@code File} instance by converting the given378* {@code file:} URI into an abstract pathname.379*380* <p> The exact form of a {@code file:} URI is system-dependent, hence381* the transformation performed by this constructor is also382* system-dependent.383*384* <p> For a given abstract pathname <i>f</i> it is guaranteed that385*386* <blockquote><code>387* new File(</code><i> f</i><code>.{@link #toURI()388* toURI}()).equals(</code><i> f</i><code>.{@link #getAbsoluteFile() getAbsoluteFile}())389* </code></blockquote>390*391* so long as the original abstract pathname, the URI, and the new abstract392* pathname are all created in (possibly different invocations of) the same393* Java virtual machine. This relationship typically does not hold,394* however, when a {@code file:} URI that is created in a virtual machine395* on one operating system is converted into an abstract pathname in a396* virtual machine on a different operating system.397*398* @param uri399* An absolute, hierarchical URI with a scheme equal to400* {@code "file"}, a non-empty path component, and undefined401* authority, query, and fragment components402*403* @throws NullPointerException404* If {@code uri} is {@code null}405*406* @throws IllegalArgumentException407* If the preconditions on the parameter do not hold408*409* @see #toURI()410* @see java.net.URI411* @since 1.4412*/413public File(URI uri) {414415// Check our many preconditions416if (!uri.isAbsolute())417throw new IllegalArgumentException("URI is not absolute");418if (uri.isOpaque())419throw new IllegalArgumentException("URI is not hierarchical");420String scheme = uri.getScheme();421if ((scheme == null) || !scheme.equalsIgnoreCase("file"))422throw new IllegalArgumentException("URI scheme is not \"file\"");423if (uri.getRawAuthority() != null)424throw new IllegalArgumentException("URI has an authority component");425if (uri.getRawFragment() != null)426throw new IllegalArgumentException("URI has a fragment component");427if (uri.getRawQuery() != null)428throw new IllegalArgumentException("URI has a query component");429String p = uri.getPath();430if (p.isEmpty())431throw new IllegalArgumentException("URI path component is empty");432433// Okay, now initialize434p = fs.fromURIPath(p);435if (File.separatorChar != '/')436p = p.replace('/', File.separatorChar);437this.path = fs.normalize(p);438this.prefixLength = fs.prefixLength(this.path);439}440441442/* -- Path-component accessors -- */443444/**445* Returns the name of the file or directory denoted by this abstract446* pathname. This is just the last name in the pathname's name447* sequence. If the pathname's name sequence is empty, then the empty448* string is returned.449*450* @return The name of the file or directory denoted by this abstract451* pathname, or the empty string if this pathname's name sequence452* is empty453*/454public String getName() {455int index = path.lastIndexOf(separatorChar);456if (index < prefixLength) return path.substring(prefixLength);457return path.substring(index + 1);458}459460/**461* Returns the pathname string of this abstract pathname's parent, or462* {@code null} if this pathname does not name a parent directory.463*464* <p> The <em>parent</em> of an abstract pathname consists of the465* pathname's prefix, if any, and each name in the pathname's name466* sequence except for the last. If the name sequence is empty then467* the pathname does not name a parent directory.468*469* @return The pathname string of the parent directory named by this470* abstract pathname, or {@code null} if this pathname471* does not name a parent472*/473public String getParent() {474int index = path.lastIndexOf(separatorChar);475if (index < prefixLength) {476if ((prefixLength > 0) && (path.length() > prefixLength))477return path.substring(0, prefixLength);478return null;479}480return path.substring(0, index);481}482483/**484* Returns the abstract pathname of this abstract pathname's parent,485* or {@code null} if this pathname does not name a parent486* directory.487*488* <p> The <em>parent</em> of an abstract pathname consists of the489* pathname's prefix, if any, and each name in the pathname's name490* sequence except for the last. If the name sequence is empty then491* the pathname does not name a parent directory.492*493* @return The abstract pathname of the parent directory named by this494* abstract pathname, or {@code null} if this pathname495* does not name a parent496*497* @since 1.2498*/499public File getParentFile() {500String p = this.getParent();501if (p == null) return null;502if (getClass() != File.class) {503p = fs.normalize(p);504}505return new File(p, this.prefixLength);506}507508/**509* Converts this abstract pathname into a pathname string. The resulting510* string uses the {@link #separator default name-separator character} to511* separate the names in the name sequence.512*513* @return The string form of this abstract pathname514*/515public String getPath() {516return path;517}518519520/* -- Path operations -- */521522/**523* Tests whether this abstract pathname is absolute. The definition of524* absolute pathname is system dependent. On UNIX systems, a pathname is525* absolute if its prefix is {@code "/"}. On Microsoft Windows systems, a526* pathname is absolute if its prefix is a drive specifier followed by527* {@code "\\"}, or if its prefix is {@code "\\\\"}.528*529* @return {@code true} if this abstract pathname is absolute,530* {@code false} otherwise531*/532public boolean isAbsolute() {533return fs.isAbsolute(this);534}535536/**537* Returns the absolute pathname string of this abstract pathname.538*539* <p> If this abstract pathname is already absolute, then the pathname540* string is simply returned as if by the {@link #getPath}541* method. If this abstract pathname is the empty abstract pathname then542* the pathname string of the current user directory, which is named by the543* system property {@code user.dir}, is returned. Otherwise this544* pathname is resolved in a system-dependent way. On UNIX systems, a545* relative pathname is made absolute by resolving it against the current546* user directory. On Microsoft Windows systems, a relative pathname is made absolute547* by resolving it against the current directory of the drive named by the548* pathname, if any; if not, it is resolved against the current user549* directory.550*551* @return The absolute pathname string denoting the same file or552* directory as this abstract pathname553*554* @throws SecurityException555* If a required system property value cannot be accessed.556*557* @see java.io.File#isAbsolute()558*/559public String getAbsolutePath() {560return fs.resolve(this);561}562563/**564* Returns the absolute form of this abstract pathname. Equivalent to565* <code>new File(this.{@link #getAbsolutePath})</code>.566*567* @return The absolute abstract pathname denoting the same file or568* directory as this abstract pathname569*570* @throws SecurityException571* If a required system property value cannot be accessed.572*573* @since 1.2574*/575public File getAbsoluteFile() {576String absPath = getAbsolutePath();577if (getClass() != File.class) {578absPath = fs.normalize(absPath);579}580return new File(absPath, fs.prefixLength(absPath));581}582583/**584* Returns the canonical pathname string of this abstract pathname.585*586* <p> A canonical pathname is both absolute and unique. The precise587* definition of canonical form is system-dependent. This method first588* converts this pathname to absolute form if necessary, as if by invoking the589* {@link #getAbsolutePath} method, and then maps it to its unique form in a590* system-dependent way. This typically involves removing redundant names591* such as {@code "."} and {@code ".."} from the pathname, resolving592* symbolic links (on UNIX platforms), and converting drive letters to a593* standard case (on Microsoft Windows platforms).594*595* <p> Every pathname that denotes an existing file or directory has a596* unique canonical form. Every pathname that denotes a nonexistent file597* or directory also has a unique canonical form. The canonical form of598* the pathname of a nonexistent file or directory may be different from599* the canonical form of the same pathname after the file or directory is600* created. Similarly, the canonical form of the pathname of an existing601* file or directory may be different from the canonical form of the same602* pathname after the file or directory is deleted.603*604* @return The canonical pathname string denoting the same file or605* directory as this abstract pathname606*607* @throws IOException608* If an I/O error occurs, which is possible because the609* construction of the canonical pathname may require610* filesystem queries611*612* @throws SecurityException613* If a required system property value cannot be accessed, or614* if a security manager exists and its {@link615* java.lang.SecurityManager#checkRead} method denies616* read access to the file617*618* @since 1.1619* @see Path#toRealPath620*/621public String getCanonicalPath() throws IOException {622if (isInvalid()) {623throw new IOException("Invalid file path");624}625return fs.canonicalize(fs.resolve(this));626}627628/**629* Returns the canonical form of this abstract pathname. Equivalent to630* <code>new File(this.{@link #getCanonicalPath})</code>.631*632* @return The canonical pathname string denoting the same file or633* directory as this abstract pathname634*635* @throws IOException636* If an I/O error occurs, which is possible because the637* construction of the canonical pathname may require638* filesystem queries639*640* @throws SecurityException641* If a required system property value cannot be accessed, or642* if a security manager exists and its {@link643* java.lang.SecurityManager#checkRead} method denies644* read access to the file645*646* @since 1.2647* @see Path#toRealPath648*/649public File getCanonicalFile() throws IOException {650String canonPath = getCanonicalPath();651if (getClass() != File.class) {652canonPath = fs.normalize(canonPath);653}654return new File(canonPath, fs.prefixLength(canonPath));655}656657private static String slashify(String path, boolean isDirectory) {658String p = path;659if (File.separatorChar != '/')660p = p.replace(File.separatorChar, '/');661if (!p.startsWith("/"))662p = "/" + p;663if (!p.endsWith("/") && isDirectory)664p = p + "/";665return p;666}667668/**669* Converts this abstract pathname into a {@code file:} URL. The670* exact form of the URL is system-dependent. If it can be determined that671* the file denoted by this abstract pathname is a directory, then the672* resulting URL will end with a slash.673*674* @return A URL object representing the equivalent file URL675*676* @throws MalformedURLException677* If the path cannot be parsed as a URL678*679* @see #toURI()680* @see java.net.URI681* @see java.net.URI#toURL()682* @see java.net.URL683* @since 1.2684*685* @deprecated This method does not automatically escape characters that686* are illegal in URLs. It is recommended that new code convert an687* abstract pathname into a URL by first converting it into a URI, via the688* {@link #toURI() toURI} method, and then converting the URI into a URL689* via the {@link java.net.URI#toURL() URI.toURL} method.690*/691@Deprecated692public URL toURL() throws MalformedURLException {693if (isInvalid()) {694throw new MalformedURLException("Invalid file path");695}696return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));697}698699/**700* Constructs a {@code file:} URI that represents this abstract pathname.701*702* <p> The exact form of the URI is system-dependent. If it can be703* determined that the file denoted by this abstract pathname is a704* directory, then the resulting URI will end with a slash.705*706* <p> For a given abstract pathname <i>f</i>, it is guaranteed that707*708* <blockquote><code>709* new {@link #File(java.net.URI) File}(</code><i> f</i><code>.toURI()).equals(710* </code><i> f</i><code>.{@link #getAbsoluteFile() getAbsoluteFile}())711* </code></blockquote>712*713* so long as the original abstract pathname, the URI, and the new abstract714* pathname are all created in (possibly different invocations of) the same715* Java virtual machine. Due to the system-dependent nature of abstract716* pathnames, however, this relationship typically does not hold when a717* {@code file:} URI that is created in a virtual machine on one operating718* system is converted into an abstract pathname in a virtual machine on a719* different operating system.720*721* <p> Note that when this abstract pathname represents a UNC pathname then722* all components of the UNC (including the server name component) are encoded723* in the {@code URI} path. The authority component is undefined, meaning724* that it is represented as {@code null}. The {@link Path} class defines the725* {@link Path#toUri toUri} method to encode the server name in the authority726* component of the resulting {@code URI}. The {@link #toPath toPath} method727* may be used to obtain a {@code Path} representing this abstract pathname.728*729* @return An absolute, hierarchical URI with a scheme equal to730* {@code "file"}, a path representing this abstract pathname,731* and undefined authority, query, and fragment components732* @throws SecurityException If a required system property value cannot733* be accessed.734*735* @see #File(java.net.URI)736* @see java.net.URI737* @see java.net.URI#toURL()738* @since 1.4739*/740public URI toURI() {741try {742File f = getAbsoluteFile();743String sp = slashify(f.getPath(), f.isDirectory());744if (sp.startsWith("//"))745sp = "//" + sp;746return new URI("file", null, sp, null);747} catch (URISyntaxException x) {748throw new Error(x); // Can't happen749}750}751752753/* -- Attribute accessors -- */754755/**756* Tests whether the application can read the file denoted by this757* abstract pathname. On some platforms it may be possible to start the758* Java virtual machine with special privileges that allow it to read759* files that are marked as unreadable. Consequently this method may return760* {@code true} even though the file does not have read permissions.761*762* @return {@code true} if and only if the file specified by this763* abstract pathname exists <em>and</em> can be read by the764* application; {@code false} otherwise765*766* @throws SecurityException767* If a security manager exists and its {@link768* java.lang.SecurityManager#checkRead(java.lang.String)}769* method denies read access to the file770*/771public boolean canRead() {772@SuppressWarnings("removal")773SecurityManager security = System.getSecurityManager();774if (security != null) {775security.checkRead(path);776}777if (isInvalid()) {778return false;779}780return fs.checkAccess(this, FileSystem.ACCESS_READ);781}782783/**784* Tests whether the application can modify the file denoted by this785* abstract pathname. On some platforms it may be possible to start the786* Java virtual machine with special privileges that allow it to modify787* files that are marked read-only. Consequently this method may return788* {@code true} even though the file is marked read-only.789*790* @return {@code true} if and only if the file system actually791* contains a file denoted by this abstract pathname <em>and</em>792* the application is allowed to write to the file;793* {@code false} otherwise.794*795* @throws SecurityException796* If a security manager exists and its {@link797* java.lang.SecurityManager#checkWrite(java.lang.String)}798* method denies write access to the file799*/800public boolean canWrite() {801@SuppressWarnings("removal")802SecurityManager security = System.getSecurityManager();803if (security != null) {804security.checkWrite(path);805}806if (isInvalid()) {807return false;808}809return fs.checkAccess(this, FileSystem.ACCESS_WRITE);810}811812/**813* Tests whether the file or directory denoted by this abstract pathname814* exists.815*816* @return {@code true} if and only if the file or directory denoted817* by this abstract pathname exists; {@code false} otherwise818*819* @throws SecurityException820* If a security manager exists and its {@link821* java.lang.SecurityManager#checkRead(java.lang.String)}822* method denies read access to the file or directory823*/824public boolean exists() {825@SuppressWarnings("removal")826SecurityManager security = System.getSecurityManager();827if (security != null) {828security.checkRead(path);829}830if (isInvalid()) {831return false;832}833return fs.hasBooleanAttributes(this, FileSystem.BA_EXISTS);834}835836/**837* Tests whether the file denoted by this abstract pathname is a838* directory.839*840* <p> Where it is required to distinguish an I/O exception from the case841* that the file is not a directory, or where several attributes of the842* same file are required at the same time, then the {@link843* java.nio.file.Files#readAttributes(Path,Class,LinkOption[])844* Files.readAttributes} method may be used.845*846* @return {@code true} if and only if the file denoted by this847* abstract pathname exists <em>and</em> is a directory;848* {@code false} otherwise849*850* @throws SecurityException851* If a security manager exists and its {@link852* java.lang.SecurityManager#checkRead(java.lang.String)}853* method denies read access to the file854*/855public boolean isDirectory() {856@SuppressWarnings("removal")857SecurityManager security = System.getSecurityManager();858if (security != null) {859security.checkRead(path);860}861if (isInvalid()) {862return false;863}864return fs.hasBooleanAttributes(this, FileSystem.BA_DIRECTORY);865}866867/**868* Tests whether the file denoted by this abstract pathname is a normal869* file. A file is <em>normal</em> if it is not a directory and, in870* addition, satisfies other system-dependent criteria. Any non-directory871* file created by a Java application is guaranteed to be a normal file.872*873* <p> Where it is required to distinguish an I/O exception from the case874* that the file is not a normal file, or where several attributes of the875* same file are required at the same time, then the {@link876* java.nio.file.Files#readAttributes(Path,Class,LinkOption[])877* Files.readAttributes} method may be used.878*879* @return {@code true} if and only if the file denoted by this880* abstract pathname exists <em>and</em> is a normal file;881* {@code false} otherwise882*883* @throws SecurityException884* If a security manager exists and its {@link885* java.lang.SecurityManager#checkRead(java.lang.String)}886* method denies read access to the file887*/888public boolean isFile() {889@SuppressWarnings("removal")890SecurityManager security = System.getSecurityManager();891if (security != null) {892security.checkRead(path);893}894if (isInvalid()) {895return false;896}897return fs.hasBooleanAttributes(this, FileSystem.BA_REGULAR);898}899900/**901* Tests whether the file named by this abstract pathname is a hidden902* file. The exact definition of <em>hidden</em> is system-dependent. On903* UNIX systems, a file is considered to be hidden if its name begins with904* a period character ({@code '.'}). On Microsoft Windows systems, a file is905* considered to be hidden if it has been marked as such in the filesystem.906*907* @return {@code true} if and only if the file denoted by this908* abstract pathname is hidden according to the conventions of the909* underlying platform910*911* @throws SecurityException912* If a security manager exists and its {@link913* java.lang.SecurityManager#checkRead(java.lang.String)}914* method denies read access to the file915*916* @since 1.2917*/918public boolean isHidden() {919@SuppressWarnings("removal")920SecurityManager security = System.getSecurityManager();921if (security != null) {922security.checkRead(path);923}924if (isInvalid()) {925return false;926}927return fs.hasBooleanAttributes(this, FileSystem.BA_HIDDEN);928}929930/**931* Returns the time that the file denoted by this abstract pathname was932* last modified.933*934* @apiNote935* While the unit of time of the return value is milliseconds, the936* granularity of the value depends on the underlying file system and may937* be larger. For example, some file systems use time stamps in units of938* seconds.939*940* <p> Where it is required to distinguish an I/O exception from the case941* where {@code 0L} is returned, or where several attributes of the942* same file are required at the same time, or where the time of last943* access or the creation time are required, then the {@link944* java.nio.file.Files#readAttributes(Path,Class,LinkOption[])945* Files.readAttributes} method may be used. If however only the946* time of last modification is required, then the947* {@link java.nio.file.Files#getLastModifiedTime(Path,LinkOption[])948* Files.getLastModifiedTime} method may be used instead.949*950* @return A {@code long} value representing the time the file was951* last modified, measured in milliseconds since the epoch952* (00:00:00 GMT, January 1, 1970), or {@code 0L} if the953* file does not exist or if an I/O error occurs. The value may954* be negative indicating the number of milliseconds before the955* epoch956*957* @throws SecurityException958* If a security manager exists and its {@link959* java.lang.SecurityManager#checkRead(java.lang.String)}960* method denies read access to the file961*/962public long lastModified() {963@SuppressWarnings("removal")964SecurityManager security = System.getSecurityManager();965if (security != null) {966security.checkRead(path);967}968if (isInvalid()) {969return 0L;970}971return fs.getLastModifiedTime(this);972}973974/**975* Returns the length of the file denoted by this abstract pathname.976* The return value is unspecified if this pathname denotes a directory.977*978* <p> Where it is required to distinguish an I/O exception from the case979* that {@code 0L} is returned, or where several attributes of the same file980* are required at the same time, then the {@link981* java.nio.file.Files#readAttributes(Path,Class,LinkOption[])982* Files.readAttributes} method may be used.983*984* @return The length, in bytes, of the file denoted by this abstract985* pathname, or {@code 0L} if the file does not exist. Some986* operating systems may return {@code 0L} for pathnames987* denoting system-dependent entities such as devices or pipes.988*989* @throws SecurityException990* If a security manager exists and its {@link991* java.lang.SecurityManager#checkRead(java.lang.String)}992* method denies read access to the file993*/994public long length() {995@SuppressWarnings("removal")996SecurityManager security = System.getSecurityManager();997if (security != null) {998security.checkRead(path);999}1000if (isInvalid()) {1001return 0L;1002}1003return fs.getLength(this);1004}100510061007/* -- File operations -- */10081009/**1010* Atomically creates a new, empty file named by this abstract pathname if1011* and only if a file with this name does not yet exist. The check for the1012* existence of the file and the creation of the file if it does not exist1013* are a single operation that is atomic with respect to all other1014* filesystem activities that might affect the file.1015* <P>1016* Note: this method should <i>not</i> be used for file-locking, as1017* the resulting protocol cannot be made to work reliably. The1018* {@link java.nio.channels.FileLock FileLock}1019* facility should be used instead.1020*1021* @return {@code true} if the named file does not exist and was1022* successfully created; {@code false} if the named file1023* already exists1024*1025* @throws IOException1026* If an I/O error occurred1027*1028* @throws SecurityException1029* If a security manager exists and its {@link1030* java.lang.SecurityManager#checkWrite(java.lang.String)}1031* method denies write access to the file1032*1033* @since 1.21034*/1035public boolean createNewFile() throws IOException {1036@SuppressWarnings("removal")1037SecurityManager security = System.getSecurityManager();1038if (security != null) security.checkWrite(path);1039if (isInvalid()) {1040throw new IOException("Invalid file path");1041}1042return fs.createFileExclusively(path);1043}10441045/**1046* Deletes the file or directory denoted by this abstract pathname. If1047* this pathname denotes a directory, then the directory must be empty in1048* order to be deleted.1049*1050* <p> Note that the {@link java.nio.file.Files} class defines the {@link1051* java.nio.file.Files#delete(Path) delete} method to throw an {@link IOException}1052* when a file cannot be deleted. This is useful for error reporting and to1053* diagnose why a file cannot be deleted.1054*1055* @return {@code true} if and only if the file or directory is1056* successfully deleted; {@code false} otherwise1057*1058* @throws SecurityException1059* If a security manager exists and its {@link1060* java.lang.SecurityManager#checkDelete} method denies1061* delete access to the file1062*/1063public boolean delete() {1064@SuppressWarnings("removal")1065SecurityManager security = System.getSecurityManager();1066if (security != null) {1067security.checkDelete(path);1068}1069if (isInvalid()) {1070return false;1071}1072return fs.delete(this);1073}10741075/**1076* Requests that the file or directory denoted by this abstract1077* pathname be deleted when the virtual machine terminates.1078* Files (or directories) are deleted in the reverse order that1079* they are registered. Invoking this method to delete a file or1080* directory that is already registered for deletion has no effect.1081* Deletion will be attempted only for normal termination of the1082* virtual machine, as defined by the Java Language Specification.1083*1084* <p> Once deletion has been requested, it is not possible to cancel the1085* request. This method should therefore be used with care.1086*1087* <P>1088* Note: this method should <i>not</i> be used for file-locking, as1089* the resulting protocol cannot be made to work reliably. The1090* {@link java.nio.channels.FileLock FileLock}1091* facility should be used instead.1092*1093* @throws SecurityException1094* If a security manager exists and its {@link1095* java.lang.SecurityManager#checkDelete} method denies1096* delete access to the file1097*1098* @see #delete1099*1100* @since 1.21101*/1102public void deleteOnExit() {1103@SuppressWarnings("removal")1104SecurityManager security = System.getSecurityManager();1105if (security != null) {1106security.checkDelete(path);1107}1108if (isInvalid()) {1109return;1110}1111DeleteOnExitHook.add(path);1112}11131114/**1115* Returns an array of strings naming the files and directories in the1116* directory denoted by this abstract pathname.1117*1118* <p> If this abstract pathname does not denote a directory, then this1119* method returns {@code null}. Otherwise an array of strings is1120* returned, one for each file or directory in the directory. Names1121* denoting the directory itself and the directory's parent directory are1122* not included in the result. Each string is a file name rather than a1123* complete path.1124*1125* <p> There is no guarantee that the name strings in the resulting array1126* will appear in any specific order; they are not, in particular,1127* guaranteed to appear in alphabetical order.1128*1129* <p> Note that the {@link java.nio.file.Files} class defines the {@link1130* java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method to1131* open a directory and iterate over the names of the files in the directory.1132* This may use less resources when working with very large directories, and1133* may be more responsive when working with remote directories.1134*1135* @return An array of strings naming the files and directories in the1136* directory denoted by this abstract pathname. The array will be1137* empty if the directory is empty. Returns {@code null} if1138* this abstract pathname does not denote a directory, or if an1139* I/O error occurs.1140*1141* @throws SecurityException1142* If a security manager exists and its {@link1143* SecurityManager#checkRead(String)} method denies read access to1144* the directory1145*/1146public String[] list() {1147return normalizedList();1148}11491150/**1151* Returns an array of strings naming the files and directories in the1152* directory denoted by this abstract pathname. The strings are1153* ensured to represent normalized paths.1154*1155* @return An array of strings naming the files and directories in the1156* directory denoted by this abstract pathname. The array will be1157* empty if the directory is empty. Returns {@code null} if1158* this abstract pathname does not denote a directory, or if an1159* I/O error occurs.1160*1161* @throws SecurityException1162* If a security manager exists and its {@link1163* SecurityManager#checkRead(String)} method denies read access to1164* the directory1165*/1166private final String[] normalizedList() {1167@SuppressWarnings("removal")1168SecurityManager security = System.getSecurityManager();1169if (security != null) {1170security.checkRead(path);1171}1172if (isInvalid()) {1173return null;1174}1175String[] s = fs.list(this);1176if (s != null && getClass() != File.class) {1177String[] normalized = new String[s.length];1178for (int i = 0; i < s.length; i++) {1179normalized[i] = fs.normalize(s[i]);1180}1181s = normalized;1182}1183return s;1184}11851186/**1187* Returns an array of strings naming the files and directories in the1188* directory denoted by this abstract pathname that satisfy the specified1189* filter. The behavior of this method is the same as that of the1190* {@link #list()} method, except that the strings in the returned array1191* must satisfy the filter. If the given {@code filter} is {@code null}1192* then all names are accepted. Otherwise, a name satisfies the filter if1193* and only if the value {@code true} results when the {@link1194* FilenameFilter#accept FilenameFilter.accept(File, String)} method1195* of the filter is invoked on this abstract pathname and the name of a1196* file or directory in the directory that it denotes.1197*1198* @param filter1199* A filename filter1200*1201* @return An array of strings naming the files and directories in the1202* directory denoted by this abstract pathname that were accepted1203* by the given {@code filter}. The array will be empty if the1204* directory is empty or if no names were accepted by the filter.1205* Returns {@code null} if this abstract pathname does not denote1206* a directory, or if an I/O error occurs.1207*1208* @throws SecurityException1209* If a security manager exists and its {@link1210* SecurityManager#checkRead(String)} method denies read access to1211* the directory1212*1213* @see java.nio.file.Files#newDirectoryStream(Path,String)1214*/1215public String[] list(FilenameFilter filter) {1216String names[] = normalizedList();1217if ((names == null) || (filter == null)) {1218return names;1219}1220List<String> v = new ArrayList<>();1221for (int i = 0 ; i < names.length ; i++) {1222if (filter.accept(this, names[i])) {1223v.add(names[i]);1224}1225}1226return v.toArray(new String[v.size()]);1227}12281229/**1230* Returns an array of abstract pathnames denoting the files in the1231* directory denoted by this abstract pathname.1232*1233* <p> If this abstract pathname does not denote a directory, then this1234* method returns {@code null}. Otherwise an array of {@code File} objects1235* is returned, one for each file or directory in the directory. Pathnames1236* denoting the directory itself and the directory's parent directory are1237* not included in the result. Each resulting abstract pathname is1238* constructed from this abstract pathname using the {@link #File(File,1239* String) File(File, String)} constructor. Therefore if this1240* pathname is absolute then each resulting pathname is absolute; if this1241* pathname is relative then each resulting pathname will be relative to1242* the same directory.1243*1244* <p> There is no guarantee that the name strings in the resulting array1245* will appear in any specific order; they are not, in particular,1246* guaranteed to appear in alphabetical order.1247*1248* <p> Note that the {@link java.nio.file.Files} class defines the {@link1249* java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method1250* to open a directory and iterate over the names of the files in the1251* directory. This may use less resources when working with very large1252* directories.1253*1254* @return An array of abstract pathnames denoting the files and1255* directories in the directory denoted by this abstract pathname.1256* The array will be empty if the directory is empty. Returns1257* {@code null} if this abstract pathname does not denote a1258* directory, or if an I/O error occurs.1259*1260* @throws SecurityException1261* If a security manager exists and its {@link1262* SecurityManager#checkRead(String)} method denies read access to1263* the directory1264*1265* @since 1.21266*/1267public File[] listFiles() {1268String[] ss = normalizedList();1269if (ss == null) return null;1270int n = ss.length;1271File[] fs = new File[n];1272for (int i = 0; i < n; i++) {1273fs[i] = new File(ss[i], this);1274}1275return fs;1276}12771278/**1279* Returns an array of abstract pathnames denoting the files and1280* directories in the directory denoted by this abstract pathname that1281* satisfy the specified filter. The behavior of this method is the same1282* as that of the {@link #listFiles()} method, except that the pathnames in1283* the returned array must satisfy the filter. If the given {@code filter}1284* is {@code null} then all pathnames are accepted. Otherwise, a pathname1285* satisfies the filter if and only if the value {@code true} results when1286* the {@link FilenameFilter#accept1287* FilenameFilter.accept(File, String)} method of the filter is1288* invoked on this abstract pathname and the name of a file or directory in1289* the directory that it denotes.1290*1291* @param filter1292* A filename filter1293*1294* @return An array of abstract pathnames denoting the files and1295* directories in the directory denoted by this abstract pathname.1296* The array will be empty if the directory is empty. Returns1297* {@code null} if this abstract pathname does not denote a1298* directory, or if an I/O error occurs.1299*1300* @throws SecurityException1301* If a security manager exists and its {@link1302* SecurityManager#checkRead(String)} method denies read access to1303* the directory1304*1305* @since 1.21306* @see java.nio.file.Files#newDirectoryStream(Path,String)1307*/1308public File[] listFiles(FilenameFilter filter) {1309String ss[] = normalizedList();1310if (ss == null) return null;1311ArrayList<File> files = new ArrayList<>();1312for (String s : ss)1313if ((filter == null) || filter.accept(this, s))1314files.add(new File(s, this));1315return files.toArray(new File[files.size()]);1316}13171318/**1319* Returns an array of abstract pathnames denoting the files and1320* directories in the directory denoted by this abstract pathname that1321* satisfy the specified filter. The behavior of this method is the same1322* as that of the {@link #listFiles()} method, except that the pathnames in1323* the returned array must satisfy the filter. If the given {@code filter}1324* is {@code null} then all pathnames are accepted. Otherwise, a pathname1325* satisfies the filter if and only if the value {@code true} results when1326* the {@link FileFilter#accept FileFilter.accept(File)} method of the1327* filter is invoked on the pathname.1328*1329* @param filter1330* A file filter1331*1332* @return An array of abstract pathnames denoting the files and1333* directories in the directory denoted by this abstract pathname.1334* The array will be empty if the directory is empty. Returns1335* {@code null} if this abstract pathname does not denote a1336* directory, or if an I/O error occurs.1337*1338* @throws SecurityException1339* If a security manager exists and its {@link1340* SecurityManager#checkRead(String)} method denies read access to1341* the directory1342*1343* @since 1.21344* @see java.nio.file.Files#newDirectoryStream(Path,java.nio.file.DirectoryStream.Filter)1345*/1346public File[] listFiles(FileFilter filter) {1347String ss[] = normalizedList();1348if (ss == null) return null;1349ArrayList<File> files = new ArrayList<>();1350for (String s : ss) {1351File f = new File(s, this);1352if ((filter == null) || filter.accept(f))1353files.add(f);1354}1355return files.toArray(new File[files.size()]);1356}13571358/**1359* Creates the directory named by this abstract pathname.1360*1361* @return {@code true} if and only if the directory was1362* created; {@code false} otherwise1363*1364* @throws SecurityException1365* If a security manager exists and its {@link1366* java.lang.SecurityManager#checkWrite(java.lang.String)}1367* method does not permit the named directory to be created1368*/1369public boolean mkdir() {1370@SuppressWarnings("removal")1371SecurityManager security = System.getSecurityManager();1372if (security != null) {1373security.checkWrite(path);1374}1375if (isInvalid()) {1376return false;1377}1378return fs.createDirectory(this);1379}13801381/**1382* Creates the directory named by this abstract pathname, including any1383* necessary but nonexistent parent directories. Note that if this1384* operation fails it may have succeeded in creating some of the necessary1385* parent directories.1386*1387* @return {@code true} if and only if the directory was created,1388* along with all necessary parent directories; {@code false}1389* otherwise1390*1391* @throws SecurityException1392* If a security manager exists and its {@link1393* java.lang.SecurityManager#checkRead(java.lang.String)}1394* method does not permit verification of the existence of the1395* named directory and all necessary parent directories; or if1396* the {@link1397* java.lang.SecurityManager#checkWrite(java.lang.String)}1398* method does not permit the named directory and all necessary1399* parent directories to be created1400*/1401public boolean mkdirs() {1402if (exists()) {1403return false;1404}1405if (mkdir()) {1406return true;1407}1408File canonFile = null;1409try {1410canonFile = getCanonicalFile();1411} catch (IOException e) {1412return false;1413}14141415File parent = canonFile.getParentFile();1416return (parent != null && (parent.mkdirs() || parent.exists()) &&1417canonFile.mkdir());1418}14191420/**1421* Renames the file denoted by this abstract pathname.1422*1423* <p> Many aspects of the behavior of this method are inherently1424* platform-dependent: The rename operation might not be able to move a1425* file from one filesystem to another, it might not be atomic, and it1426* might not succeed if a file with the destination abstract pathname1427* already exists. The return value should always be checked to make sure1428* that the rename operation was successful. As instances of {@code File}1429* are immutable, this File object is not changed to name the destination1430* file or directory.1431*1432* <p> Note that the {@link java.nio.file.Files} class defines the {@link1433* java.nio.file.Files#move move} method to move or rename a file in a1434* platform independent manner.1435*1436* @param dest The new abstract pathname for the named file1437*1438* @return {@code true} if and only if the renaming succeeded;1439* {@code false} otherwise1440*1441* @throws SecurityException1442* If a security manager exists and its {@link1443* java.lang.SecurityManager#checkWrite(java.lang.String)}1444* method denies write access to either the old or new pathnames1445*1446* @throws NullPointerException1447* If parameter {@code dest} is {@code null}1448*/1449public boolean renameTo(File dest) {1450if (dest == null) {1451throw new NullPointerException();1452}1453@SuppressWarnings("removal")1454SecurityManager security = System.getSecurityManager();1455if (security != null) {1456security.checkWrite(path);1457security.checkWrite(dest.path);1458}1459if (this.isInvalid() || dest.isInvalid()) {1460return false;1461}1462return fs.rename(this, dest);1463}14641465/**1466* Sets the last-modified time of the file or directory named by this1467* abstract pathname.1468*1469* <p> All platforms support file-modification times to the nearest second,1470* but some provide more precision. The argument will be truncated to fit1471* the supported precision. If the operation succeeds and no intervening1472* operations on the file take place, then the next invocation of the1473* {@link #lastModified} method will return the (possibly1474* truncated) {@code time} argument that was passed to this method.1475*1476* @param time The new last-modified time, measured in milliseconds since1477* the epoch (00:00:00 GMT, January 1, 1970)1478*1479* @return {@code true} if and only if the operation succeeded;1480* {@code false} otherwise1481*1482* @throws IllegalArgumentException If the argument is negative1483*1484* @throws SecurityException1485* If a security manager exists and its {@link1486* java.lang.SecurityManager#checkWrite(java.lang.String)}1487* method denies write access to the named file1488*1489* @since 1.21490*/1491public boolean setLastModified(long time) {1492if (time < 0) throw new IllegalArgumentException("Negative time");1493@SuppressWarnings("removal")1494SecurityManager security = System.getSecurityManager();1495if (security != null) {1496security.checkWrite(path);1497}1498if (isInvalid()) {1499return false;1500}1501return fs.setLastModifiedTime(this, time);1502}15031504/**1505* Marks the file or directory named by this abstract pathname so that1506* only read operations are allowed. After invoking this method the file1507* or directory will not change until it is either deleted or marked1508* to allow write access. On some platforms it may be possible to start the1509* Java virtual machine with special privileges that allow it to modify1510* files that are marked read-only. Whether or not a read-only file or1511* directory may be deleted depends upon the underlying system.1512*1513* @return {@code true} if and only if the operation succeeded;1514* {@code false} otherwise1515*1516* @throws SecurityException1517* If a security manager exists and its {@link1518* java.lang.SecurityManager#checkWrite(java.lang.String)}1519* method denies write access to the named file1520*1521* @since 1.21522*/1523public boolean setReadOnly() {1524@SuppressWarnings("removal")1525SecurityManager security = System.getSecurityManager();1526if (security != null) {1527security.checkWrite(path);1528}1529if (isInvalid()) {1530return false;1531}1532return fs.setReadOnly(this);1533}15341535/**1536* Sets the owner's or everybody's write permission for this abstract1537* pathname. On some platforms it may be possible to start the Java virtual1538* machine with special privileges that allow it to modify files that1539* disallow write operations.1540*1541* <p> The {@link java.nio.file.Files} class defines methods that operate on1542* file attributes including file permissions. This may be used when finer1543* manipulation of file permissions is required.1544*1545* @param writable1546* If {@code true}, sets the access permission to allow write1547* operations; if {@code false} to disallow write operations1548*1549* @param ownerOnly1550* If {@code true}, the write permission applies only to the1551* owner's write permission; otherwise, it applies to everybody. If1552* the underlying file system can not distinguish the owner's write1553* permission from that of others, then the permission will apply to1554* everybody, regardless of this value.1555*1556* @return {@code true} if and only if the operation succeeded. The1557* operation will fail if the user does not have permission to change1558* the access permissions of this abstract pathname.1559*1560* @throws SecurityException1561* If a security manager exists and its {@link1562* java.lang.SecurityManager#checkWrite(java.lang.String)}1563* method denies write access to the named file1564*1565* @since 1.61566*/1567public boolean setWritable(boolean writable, boolean ownerOnly) {1568@SuppressWarnings("removal")1569SecurityManager security = System.getSecurityManager();1570if (security != null) {1571security.checkWrite(path);1572}1573if (isInvalid()) {1574return false;1575}1576return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);1577}15781579/**1580* A convenience method to set the owner's write permission for this abstract1581* pathname. On some platforms it may be possible to start the Java virtual1582* machine with special privileges that allow it to modify files that1583* disallow write operations.1584*1585* <p> An invocation of this method of the form {@code file.setWritable(arg)}1586* behaves in exactly the same way as the invocation1587*1588* <pre>{@code1589* file.setWritable(arg, true)1590* }</pre>1591*1592* @param writable1593* If {@code true}, sets the access permission to allow write1594* operations; if {@code false} to disallow write operations1595*1596* @return {@code true} if and only if the operation succeeded. The1597* operation will fail if the user does not have permission to1598* change the access permissions of this abstract pathname.1599*1600* @throws SecurityException1601* If a security manager exists and its {@link1602* java.lang.SecurityManager#checkWrite(java.lang.String)}1603* method denies write access to the file1604*1605* @since 1.61606*/1607public boolean setWritable(boolean writable) {1608return setWritable(writable, true);1609}16101611/**1612* Sets the owner's or everybody's read permission for this abstract1613* pathname. On some platforms it may be possible to start the Java virtual1614* machine with special privileges that allow it to read files that are1615* marked as unreadable.1616*1617* <p> The {@link java.nio.file.Files} class defines methods that operate on1618* file attributes including file permissions. This may be used when finer1619* manipulation of file permissions is required.1620*1621* @param readable1622* If {@code true}, sets the access permission to allow read1623* operations; if {@code false} to disallow read operations1624*1625* @param ownerOnly1626* If {@code true}, the read permission applies only to the1627* owner's read permission; otherwise, it applies to everybody. If1628* the underlying file system can not distinguish the owner's read1629* permission from that of others, then the permission will apply to1630* everybody, regardless of this value.1631*1632* @return {@code true} if and only if the operation succeeded. The1633* operation will fail if the user does not have permission to1634* change the access permissions of this abstract pathname. If1635* {@code readable} is {@code false} and the underlying1636* file system does not implement a read permission, then the1637* operation will fail.1638*1639* @throws SecurityException1640* If a security manager exists and its {@link1641* java.lang.SecurityManager#checkWrite(java.lang.String)}1642* method denies write access to the file1643*1644* @since 1.61645*/1646public boolean setReadable(boolean readable, boolean ownerOnly) {1647@SuppressWarnings("removal")1648SecurityManager security = System.getSecurityManager();1649if (security != null) {1650security.checkWrite(path);1651}1652if (isInvalid()) {1653return false;1654}1655return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);1656}16571658/**1659* A convenience method to set the owner's read permission for this abstract1660* pathname. On some platforms it may be possible to start the Java virtual1661* machine with special privileges that allow it to read files that are1662* marked as unreadable.1663*1664* <p>An invocation of this method of the form {@code file.setReadable(arg)}1665* behaves in exactly the same way as the invocation1666*1667* <pre>{@code1668* file.setReadable(arg, true)1669* }</pre>1670*1671* @param readable1672* If {@code true}, sets the access permission to allow read1673* operations; if {@code false} to disallow read operations1674*1675* @return {@code true} if and only if the operation succeeded. The1676* operation will fail if the user does not have permission to1677* change the access permissions of this abstract pathname. If1678* {@code readable} is {@code false} and the underlying1679* file system does not implement a read permission, then the1680* operation will fail.1681*1682* @throws SecurityException1683* If a security manager exists and its {@link1684* java.lang.SecurityManager#checkWrite(java.lang.String)}1685* method denies write access to the file1686*1687* @since 1.61688*/1689public boolean setReadable(boolean readable) {1690return setReadable(readable, true);1691}16921693/**1694* Sets the owner's or everybody's execute permission for this abstract1695* pathname. On some platforms it may be possible to start the Java virtual1696* machine with special privileges that allow it to execute files that are1697* not marked executable.1698*1699* <p> The {@link java.nio.file.Files} class defines methods that operate on1700* file attributes including file permissions. This may be used when finer1701* manipulation of file permissions is required.1702*1703* @param executable1704* If {@code true}, sets the access permission to allow execute1705* operations; if {@code false} to disallow execute operations1706*1707* @param ownerOnly1708* If {@code true}, the execute permission applies only to the1709* owner's execute permission; otherwise, it applies to everybody.1710* If the underlying file system can not distinguish the owner's1711* execute permission from that of others, then the permission will1712* apply to everybody, regardless of this value.1713*1714* @return {@code true} if and only if the operation succeeded. The1715* operation will fail if the user does not have permission to1716* change the access permissions of this abstract pathname. If1717* {@code executable} is {@code false} and the underlying1718* file system does not implement an execute permission, then the1719* operation will fail.1720*1721* @throws SecurityException1722* If a security manager exists and its {@link1723* java.lang.SecurityManager#checkWrite(java.lang.String)}1724* method denies write access to the file1725*1726* @since 1.61727*/1728public boolean setExecutable(boolean executable, boolean ownerOnly) {1729@SuppressWarnings("removal")1730SecurityManager security = System.getSecurityManager();1731if (security != null) {1732security.checkWrite(path);1733}1734if (isInvalid()) {1735return false;1736}1737return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);1738}17391740/**1741* A convenience method to set the owner's execute permission for this1742* abstract pathname. On some platforms it may be possible to start the Java1743* virtual machine with special privileges that allow it to execute files1744* that are not marked executable.1745*1746* <p>An invocation of this method of the form {@code file.setExcutable(arg)}1747* behaves in exactly the same way as the invocation1748*1749* <pre>{@code1750* file.setExecutable(arg, true)1751* }</pre>1752*1753* @param executable1754* If {@code true}, sets the access permission to allow execute1755* operations; if {@code false} to disallow execute operations1756*1757* @return {@code true} if and only if the operation succeeded. The1758* operation will fail if the user does not have permission to1759* change the access permissions of this abstract pathname. If1760* {@code executable} is {@code false} and the underlying1761* file system does not implement an execute permission, then the1762* operation will fail.1763*1764* @throws SecurityException1765* If a security manager exists and its {@link1766* java.lang.SecurityManager#checkWrite(java.lang.String)}1767* method denies write access to the file1768*1769* @since 1.61770*/1771public boolean setExecutable(boolean executable) {1772return setExecutable(executable, true);1773}17741775/**1776* Tests whether the application can execute the file denoted by this1777* abstract pathname. On some platforms it may be possible to start the1778* Java virtual machine with special privileges that allow it to execute1779* files that are not marked executable. Consequently this method may return1780* {@code true} even though the file does not have execute permissions.1781*1782* @return {@code true} if and only if the abstract pathname exists1783* <em>and</em> the application is allowed to execute the file1784*1785* @throws SecurityException1786* If a security manager exists and its {@link1787* java.lang.SecurityManager#checkExec(java.lang.String)}1788* method denies execute access to the file1789*1790* @since 1.61791*/1792public boolean canExecute() {1793@SuppressWarnings("removal")1794SecurityManager security = System.getSecurityManager();1795if (security != null) {1796security.checkExec(path);1797}1798if (isInvalid()) {1799return false;1800}1801return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE);1802}180318041805/* -- Filesystem interface -- */18061807/**1808* List the available filesystem roots.1809*1810* <p> A particular Java platform may support zero or more1811* hierarchically-organized file systems. Each file system has a1812* {@code root} directory from which all other files in that file system1813* can be reached. Windows platforms, for example, have a root directory1814* for each active drive; UNIX platforms have a single root directory,1815* namely {@code "/"}. The set of available filesystem roots is affected1816* by various system-level operations such as the insertion or ejection of1817* removable media and the disconnecting or unmounting of physical or1818* virtual disk drives.1819*1820* <p> This method returns an array of {@code File} objects that denote the1821* root directories of the available filesystem roots. It is guaranteed1822* that the canonical pathname of any file physically present on the local1823* machine will begin with one of the roots returned by this method.1824*1825* <p> The canonical pathname of a file that resides on some other machine1826* and is accessed via a remote-filesystem protocol such as SMB or NFS may1827* or may not begin with one of the roots returned by this method. If the1828* pathname of a remote file is syntactically indistinguishable from the1829* pathname of a local file then it will begin with one of the roots1830* returned by this method. Thus, for example, {@code File} objects1831* denoting the root directories of the mapped network drives of a Windows1832* platform will be returned by this method, while {@code File} objects1833* containing UNC pathnames will not be returned by this method.1834*1835* <p> Unlike most methods in this class, this method does not throw1836* security exceptions. If a security manager exists and its {@link1837* SecurityManager#checkRead(String)} method denies read access to a1838* particular root directory, then that directory will not appear in the1839* result.1840*1841* @return An array of {@code File} objects denoting the available1842* filesystem roots, or {@code null} if the set of roots could not1843* be determined. The array will be empty if there are no1844* filesystem roots.1845*1846* @since 1.21847* @see java.nio.file.FileStore1848*/1849public static File[] listRoots() {1850return fs.listRoots();1851}185218531854/* -- Disk usage -- */18551856/**1857* Returns the size of the partition <a href="#partName">named</a> by this1858* abstract pathname. If the total number of bytes in the partition is1859* greater than {@link Long#MAX_VALUE}, then {@code Long.MAX_VALUE} will be1860* returned.1861*1862* @return The size, in bytes, of the partition or {@code 0L} if this1863* abstract pathname does not name a partition or if the size1864* cannot be obtained1865*1866* @throws SecurityException1867* If a security manager has been installed and it denies1868* {@link RuntimePermission}{@code ("getFileSystemAttributes")}1869* or its {@link SecurityManager#checkRead(String)} method denies1870* read access to the file named by this abstract pathname1871*1872* @since 1.61873* @see FileStore#getTotalSpace1874*/1875public long getTotalSpace() {1876@SuppressWarnings("removal")1877SecurityManager sm = System.getSecurityManager();1878if (sm != null) {1879sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));1880sm.checkRead(path);1881}1882if (isInvalid()) {1883return 0L;1884}1885long space = fs.getSpace(this, FileSystem.SPACE_TOTAL);1886return space >= 0L ? space : Long.MAX_VALUE;1887}18881889/**1890* Returns the number of unallocated bytes in the partition <a1891* href="#partName">named</a> by this abstract path name. If the1892* number of unallocated bytes in the partition is greater than1893* {@link Long#MAX_VALUE}, then {@code Long.MAX_VALUE} will be returned.1894*1895* <p> The returned number of unallocated bytes is a hint, but not1896* a guarantee, that it is possible to use most or any of these1897* bytes. The number of unallocated bytes is most likely to be1898* accurate immediately after this call. It is likely to be made1899* inaccurate by any external I/O operations including those made1900* on the system outside of this virtual machine. This method1901* makes no guarantee that write operations to this file system1902* will succeed.1903*1904* @return The number of unallocated bytes on the partition or {@code 0L}1905* if the abstract pathname does not name a partition or if this1906* number cannot be obtained. This value will be less than or1907* equal to the total file system size returned by1908* {@link #getTotalSpace}.1909*1910* @throws SecurityException1911* If a security manager has been installed and it denies1912* {@link RuntimePermission}{@code ("getFileSystemAttributes")}1913* or its {@link SecurityManager#checkRead(String)} method denies1914* read access to the file named by this abstract pathname1915*1916* @since 1.61917* @see FileStore#getUnallocatedSpace1918*/1919public long getFreeSpace() {1920@SuppressWarnings("removal")1921SecurityManager sm = System.getSecurityManager();1922if (sm != null) {1923sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));1924sm.checkRead(path);1925}1926if (isInvalid()) {1927return 0L;1928}1929long space = fs.getSpace(this, FileSystem.SPACE_FREE);1930return space >= 0L ? space : Long.MAX_VALUE;1931}19321933/**1934* Returns the number of bytes available to this virtual machine on the1935* partition <a href="#partName">named</a> by this abstract pathname. If1936* the number of available bytes in the partition is greater than1937* {@link Long#MAX_VALUE}, then {@code Long.MAX_VALUE} will be returned.1938* When possible, this method checks for write permissions and other1939* operating system restrictions and will therefore usually provide a more1940* accurate estimate of how much new data can actually be written than1941* {@link #getFreeSpace}.1942*1943* <p> The returned number of available bytes is a hint, but not a1944* guarantee, that it is possible to use most or any of these bytes. The1945* number of available bytes is most likely to be accurate immediately1946* after this call. It is likely to be made inaccurate by any external1947* I/O operations including those made on the system outside of this1948* virtual machine. This method makes no guarantee that write operations1949* to this file system will succeed.1950*1951* @return The number of available bytes on the partition or {@code 0L}1952* if the abstract pathname does not name a partition or if this1953* number cannot be obtained. On systems where this information1954* is not available, this method will be equivalent to a call to1955* {@link #getFreeSpace}.1956*1957* @throws SecurityException1958* If a security manager has been installed and it denies1959* {@link RuntimePermission}{@code ("getFileSystemAttributes")}1960* or its {@link SecurityManager#checkRead(String)} method denies1961* read access to the file named by this abstract pathname1962*1963* @since 1.61964* @see FileStore#getUsableSpace1965*/1966public long getUsableSpace() {1967@SuppressWarnings("removal")1968SecurityManager sm = System.getSecurityManager();1969if (sm != null) {1970sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));1971sm.checkRead(path);1972}1973if (isInvalid()) {1974return 0L;1975}1976long space = fs.getSpace(this, FileSystem.SPACE_USABLE);1977return space >= 0L ? space : Long.MAX_VALUE;1978}19791980/* -- Temporary files -- */19811982private static class TempDirectory {1983private TempDirectory() { }19841985// temporary directory location1986private static final File tmpdir = new File(1987GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));1988static File location() {1989return tmpdir;1990}19911992// file name generation1993private static final SecureRandom random = new SecureRandom();1994private static int shortenSubName(int subNameLength, int excess,1995int nameMin) {1996int newLength = Math.max(nameMin, subNameLength - excess);1997if (newLength < subNameLength) {1998return newLength;1999}2000return subNameLength;2001}2002@SuppressWarnings("removal")2003static File generateFile(String prefix, String suffix, File dir)2004throws IOException2005{2006long n = random.nextLong();2007String nus = Long.toUnsignedString(n);20082009// Use only the file name from the supplied prefix2010prefix = (new File(prefix)).getName();20112012int prefixLength = prefix.length();2013int nusLength = nus.length();2014int suffixLength = suffix.length();;20152016String name;2017int nameMax = fs.getNameMax(dir.getPath());2018int excess = prefixLength + nusLength + suffixLength - nameMax;2019if (excess <= 0) {2020name = prefix + nus + suffix;2021} else {2022// Name exceeds the maximum path component length: shorten it20232024// Attempt to shorten the prefix length to no less then 32025prefixLength = shortenSubName(prefixLength, excess, 3);2026excess = prefixLength + nusLength + suffixLength - nameMax;20272028if (excess > 0) {2029// Attempt to shorten the suffix length to no less than2030// 0 or 4 depending on whether it begins with a dot ('.')2031suffixLength = shortenSubName(suffixLength, excess,2032suffix.indexOf(".") == 0 ? 4 : 0);2033suffixLength = shortenSubName(suffixLength, excess, 3);2034excess = prefixLength + nusLength + suffixLength - nameMax;2035}20362037if (excess > 0 && excess <= nusLength - 5) {2038// Attempt to shorten the random character string length2039// to no less than 52040nusLength = shortenSubName(nusLength, excess, 5);2041}20422043StringBuilder sb =2044new StringBuilder(prefixLength + nusLength + suffixLength);2045sb.append(prefixLength < prefix.length() ?2046prefix.substring(0, prefixLength) : prefix);2047sb.append(nusLength < nus.length() ?2048nus.substring(0, nusLength) : nus);2049sb.append(suffixLength < suffix.length() ?2050suffix.substring(0, suffixLength) : suffix);2051name = sb.toString();2052}20532054// Normalize the path component2055name = fs.normalize(name);20562057File f = new File(dir, name);2058if (!name.equals(f.getName()) || f.isInvalid()) {2059if (System.getSecurityManager() != null)2060throw new IOException("Unable to create temporary file");2061else2062throw new IOException("Unable to create temporary file, "2063+ name);2064}2065return f;2066}2067}20682069/**2070* <p> Creates a new empty file in the specified directory, using the2071* given prefix and suffix strings to generate its name. If this method2072* returns successfully then it is guaranteed that:2073*2074* <ol>2075* <li> The file denoted by the returned abstract pathname did not exist2076* before this method was invoked, and2077* <li> Neither this method nor any of its variants will return the same2078* abstract pathname again in the current invocation of the virtual2079* machine.2080* </ol>2081*2082* This method provides only part of a temporary-file facility. To arrange2083* for a file created by this method to be deleted automatically, use the2084* {@link #deleteOnExit} method.2085*2086* <p> The {@code prefix} argument must be at least three characters2087* long. It is recommended that the prefix be a short, meaningful string2088* such as {@code "hjb"} or {@code "mail"}. The2089* {@code suffix} argument may be {@code null}, in which case the2090* suffix {@code ".tmp"} will be used.2091*2092* <p> To create the new file, the prefix and the suffix may first be2093* adjusted to fit the limitations of the underlying platform. If the2094* prefix is too long then it will be truncated, but its first three2095* characters will always be preserved. If the suffix is too long then it2096* too will be truncated, but if it begins with a period character2097* ({@code '.'}) then the period and the first three characters2098* following it will always be preserved. Once these adjustments have been2099* made the name of the new file will be generated by concatenating the2100* prefix, five or more internally-generated characters, and the suffix.2101*2102* <p> If the {@code directory} argument is {@code null} then the2103* system-dependent default temporary-file directory will be used. The2104* default temporary-file directory is specified by the system property2105* {@code java.io.tmpdir}. On UNIX systems the default value of this2106* property is typically {@code "/tmp"} or {@code "/var/tmp"}; on2107* Microsoft Windows systems it is typically {@code "C:\\WINNT\\TEMP"}. A different2108* value may be given to this system property when the Java virtual machine2109* is invoked, but programmatic changes to this property are not guaranteed2110* to have any effect upon the temporary directory used by this method.2111*2112* @param prefix The prefix string to be used in generating the file's2113* name; must be at least three characters long2114*2115* @param suffix The suffix string to be used in generating the file's2116* name; may be {@code null}, in which case the2117* suffix {@code ".tmp"} will be used2118*2119* @param directory The directory in which the file is to be created, or2120* {@code null} if the default temporary-file2121* directory is to be used2122*2123* @return An abstract pathname denoting a newly-created empty file2124*2125* @throws IllegalArgumentException2126* If the {@code prefix} argument contains fewer than three2127* characters2128*2129* @throws IOException If a file could not be created2130*2131* @throws SecurityException2132* If a security manager exists and its {@link2133* java.lang.SecurityManager#checkWrite(java.lang.String)}2134* method does not allow a file to be created2135*2136* @since 1.22137*/2138public static File createTempFile(String prefix, String suffix,2139File directory)2140throws IOException2141{2142if (prefix.length() < 3) {2143throw new IllegalArgumentException("Prefix string \"" + prefix +2144"\" too short: length must be at least 3");2145}2146if (suffix == null)2147suffix = ".tmp";21482149File tmpdir = (directory != null) ? directory2150: TempDirectory.location();2151@SuppressWarnings("removal")2152SecurityManager sm = System.getSecurityManager();2153File f;2154do {2155f = TempDirectory.generateFile(prefix, suffix, tmpdir);21562157if (sm != null) {2158try {2159sm.checkWrite(f.getPath());2160} catch (SecurityException se) {2161// don't reveal temporary directory location2162if (directory == null)2163throw new SecurityException("Unable to create temporary file");2164throw se;2165}2166}2167} while (fs.hasBooleanAttributes(f, FileSystem.BA_EXISTS));21682169if (!fs.createFileExclusively(f.getPath()))2170throw new IOException("Unable to create temporary file");21712172return f;2173}21742175/**2176* Creates an empty file in the default temporary-file directory, using2177* the given prefix and suffix to generate its name. Invoking this method2178* is equivalent to invoking {@link #createTempFile(java.lang.String,2179* java.lang.String, java.io.File)2180* createTempFile(prefix, suffix, null)}.2181*2182* <p> The {@link2183* java.nio.file.Files#createTempFile(String,String,java.nio.file.attribute.FileAttribute[])2184* Files.createTempFile} method provides an alternative method to create an2185* empty file in the temporary-file directory. Files created by that method2186* may have more restrictive access permissions to files created by this2187* method and so may be more suited to security-sensitive applications.2188*2189* @param prefix The prefix string to be used in generating the file's2190* name; must be at least three characters long2191*2192* @param suffix The suffix string to be used in generating the file's2193* name; may be {@code null}, in which case the2194* suffix {@code ".tmp"} will be used2195*2196* @return An abstract pathname denoting a newly-created empty file2197*2198* @throws IllegalArgumentException2199* If the {@code prefix} argument contains fewer than three2200* characters2201*2202* @throws IOException If a file could not be created2203*2204* @throws SecurityException2205* If a security manager exists and its {@link2206* java.lang.SecurityManager#checkWrite(java.lang.String)}2207* method does not allow a file to be created2208*2209* @since 1.22210* @see java.nio.file.Files#createTempDirectory(String,FileAttribute[])2211*/2212public static File createTempFile(String prefix, String suffix)2213throws IOException2214{2215return createTempFile(prefix, suffix, null);2216}22172218/* -- Basic infrastructure -- */22192220/**2221* Compares two abstract pathnames lexicographically. The ordering2222* defined by this method depends upon the underlying system. On UNIX2223* systems, alphabetic case is significant in comparing pathnames; on2224* Microsoft Windows systems it is not.2225*2226* @param pathname The abstract pathname to be compared to this abstract2227* pathname2228*2229* @return Zero if the argument is equal to this abstract pathname, a2230* value less than zero if this abstract pathname is2231* lexicographically less than the argument, or a value greater2232* than zero if this abstract pathname is lexicographically2233* greater than the argument2234*2235* @since 1.22236*/2237public int compareTo(File pathname) {2238return fs.compare(this, pathname);2239}22402241/**2242* Tests this abstract pathname for equality with the given object.2243* Returns {@code true} if and only if the argument is not2244* {@code null} and is an abstract pathname that is the same as this2245* abstract pathname. Whether or not two abstract2246* pathnames are equal depends upon the underlying operating system.2247* On UNIX systems, alphabetic case is significant in comparing pathnames;2248* on Microsoft Windows systems it is not.2249*2250* @apiNote This method only tests whether the abstract pathnames are equal;2251* it does not access the file system and the file is not required2252* to exist.2253*2254* @param obj The object to be compared with this abstract pathname2255*2256* @return {@code true} if and only if the objects are the same;2257* {@code false} otherwise2258*2259* @see #compareTo(File)2260* @see java.nio.file.Files#isSameFile(Path,Path)2261*/2262public boolean equals(Object obj) {2263if (obj instanceof File file) {2264return compareTo(file) == 0;2265}2266return false;2267}22682269/**2270* Computes a hash code for this abstract pathname. Because equality of2271* abstract pathnames is inherently system-dependent, so is the computation2272* of their hash codes. On UNIX systems, the hash code of an abstract2273* pathname is equal to the exclusive <em>or</em> of the hash code2274* of its pathname string and the decimal value2275* {@code 1234321}. On Microsoft Windows systems, the hash2276* code is equal to the exclusive <em>or</em> of the hash code of2277* its pathname string converted to lower case and the decimal2278* value {@code 1234321}. Locale is not taken into account on2279* lowercasing the pathname string.2280*2281* @return A hash code for this abstract pathname2282*/2283public int hashCode() {2284return fs.hashCode(this);2285}22862287/**2288* Returns the pathname string of this abstract pathname. This is just the2289* string returned by the {@link #getPath} method.2290*2291* @return The string form of this abstract pathname2292*/2293public String toString() {2294return getPath();2295}22962297/**2298* WriteObject is called to save this filename.2299* The separator character is saved also so it can be replaced2300* in case the path is reconstituted on a different host type.2301*2302* @serialData Default fields followed by separator character.2303*2304* @param s the {@code ObjectOutputStream} to which data is written2305* @throws IOException if an I/O error occurs2306*/2307@java.io.Serial2308private synchronized void writeObject(java.io.ObjectOutputStream s)2309throws IOException2310{2311s.defaultWriteObject();2312s.writeChar(separatorChar); // Add the separator character2313}23142315/**2316* readObject is called to restore this filename.2317* The original separator character is read. If it is different2318* than the separator character on this system, then the old separator2319* is replaced by the local separator.2320*2321* @param s the {@code ObjectInputStream} from which data is read2322* @throws IOException if an I/O error occurs2323* @throws ClassNotFoundException if a serialized class cannot be loaded2324*/2325@java.io.Serial2326private synchronized void readObject(java.io.ObjectInputStream s)2327throws IOException, ClassNotFoundException2328{2329ObjectInputStream.GetField fields = s.readFields();2330String pathField = (String)fields.get("path", null);2331char sep = s.readChar(); // read the previous separator char2332if (sep != separatorChar)2333pathField = pathField.replace(sep, separatorChar);2334String path = fs.normalize(pathField);2335UNSAFE.putReference(this, PATH_OFFSET, path);2336UNSAFE.putIntVolatile(this, PREFIX_LENGTH_OFFSET, fs.prefixLength(path));2337}23382339private static final jdk.internal.misc.Unsafe UNSAFE2340= jdk.internal.misc.Unsafe.getUnsafe();2341private static final long PATH_OFFSET2342= UNSAFE.objectFieldOffset(File.class, "path");2343private static final long PREFIX_LENGTH_OFFSET2344= UNSAFE.objectFieldOffset(File.class, "prefixLength");23452346/** use serialVersionUID from JDK 1.0.2 for interoperability */2347@java.io.Serial2348private static final long serialVersionUID = 301077366599181567L;23492350// -- Integration with java.nio.file --23512352private transient volatile Path filePath;23532354/**2355* Returns a {@link Path java.nio.file.Path} object constructed from2356* this abstract path. The resulting {@code Path} is associated with the2357* {@link java.nio.file.FileSystems#getDefault default-filesystem}.2358*2359* <p> The first invocation of this method works as if invoking it were2360* equivalent to evaluating the expression:2361* <blockquote><pre>2362* {@link java.nio.file.FileSystems#getDefault FileSystems.getDefault}().{@link2363* java.nio.file.FileSystem#getPath getPath}(this.{@link #getPath getPath}());2364* </pre></blockquote>2365* Subsequent invocations of this method return the same {@code Path}.2366*2367* <p> If this abstract pathname is the empty abstract pathname then this2368* method returns a {@code Path} that may be used to access the current2369* user directory.2370*2371* @return a {@code Path} constructed from this abstract path2372*2373* @throws java.nio.file.InvalidPathException2374* if a {@code Path} object cannot be constructed from the abstract2375* path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath})2376*2377* @since 1.72378* @see Path#toFile2379*/2380public Path toPath() {2381Path result = filePath;2382if (result == null) {2383synchronized (this) {2384result = filePath;2385if (result == null) {2386result = FileSystems.getDefault().getPath(path);2387filePath = result;2388}2389}2390}2391return result;2392}2393}239423952396