• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.io;
28 
29 import java.net.URI;
30 import java.net.URL;
31 import java.net.MalformedURLException;
32 import java.net.URISyntaxException;
33 import java.util.List;
34 import java.util.ArrayList;
35 
36 /**
37  * An abstract representation of file and directory pathnames.
38  *
39  * <p> User interfaces and operating systems use system-dependent <em>pathname
40  * strings</em> to name files and directories.  This class presents an
41  * abstract, system-independent view of hierarchical pathnames.  An
42  * <em>abstract pathname</em> has two components:
43  *
44  * <ol>
45  * <li> An optional system-dependent <em>prefix</em> string,
46  *      such as a disk-drive specifier, <code>"/"</code>&nbsp;for the UNIX root
47  *      directory, or <code>"\\\\"</code>&nbsp;for a Microsoft Windows UNC pathname, and
48  * <li> A sequence of zero or more string <em>names</em>.
49  * </ol>
50  *
51  * The first name in an abstract pathname may be a directory name or, in the
52  * case of Microsoft Windows UNC pathnames, a hostname.  Each subsequent name
53  * in an abstract pathname denotes a directory; the last name may denote
54  * either a directory or a file.  The <em>empty</em> abstract pathname has no
55  * prefix and an empty name sequence.
56  *
57  * <p> The conversion of a pathname string to or from an abstract pathname is
58  * inherently system-dependent.  When an abstract pathname is converted into a
59  * pathname string, each name is separated from the next by a single copy of
60  * the default <em>separator character</em>.  The default name-separator
61  * character is defined by the system property <code>file.separator</code>, and
62  * is made available in the public static fields <code>{@link
63  * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
64  * When a pathname string is converted into an abstract pathname, the names
65  * within it may be separated by the default name-separator character or by any
66  * other name-separator character that is supported by the underlying system.
67  *
68  * <p> A pathname, whether abstract or in string form, may be either
69  * <em>absolute</em> or <em>relative</em>.  An absolute pathname is complete in
70  * that no other information is required in order to locate the file that it
71  * denotes.  A relative pathname, in contrast, must be interpreted in terms of
72  * information taken from some other pathname.  By default the classes in the
73  * <code>java.io</code> package always resolve relative pathnames against the
74  * current user directory.  This directory is named by the system property
75  * <code>user.dir</code>, and is typically the directory in which the Java
76  * virtual machine was invoked.
77  *
78  * <p> The <em>parent</em> of an abstract pathname may be obtained by invoking
79  * the {@link #getParent} method of this class and consists of the pathname's
80  * prefix and each name in the pathname's name sequence except for the last.
81  * Each directory's absolute pathname is an ancestor of any <tt>File</tt>
82  * object with an absolute abstract pathname which begins with the directory's
83  * absolute pathname.  For example, the directory denoted by the abstract
84  * pathname <tt>"/usr"</tt> is an ancestor of the directory denoted by the
85  * pathname <tt>"/usr/local/bin"</tt>.
86  *
87  * <p> The prefix concept is used to handle root directories on UNIX platforms,
88  * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,
89  * as follows:
90  *
91  * <ul>
92  *
93  * <li> For UNIX platforms, the prefix of an absolute pathname is always
94  * <code>"/"</code>.  Relative pathnames have no prefix.  The abstract pathname
95  * denoting the root directory has the prefix <code>"/"</code> and an empty
96  * name sequence.
97  *
98  * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive
99  * specifier consists of the drive letter followed by <code>":"</code> and
100  * possibly followed by <code>"\\"</code> if the pathname is absolute.  The
101  * prefix of a UNC pathname is <code>"\\\\"</code>; the hostname and the share
102  * name are the first two names in the name sequence.  A relative pathname that
103  * does not specify a drive has no prefix.
104  *
105  * </ul>
106  *
107  * <p> Instances of this class may or may not denote an actual file-system
108  * object such as a file or a directory.  If it does denote such an object
109  * then that object resides in a <i>partition</i>.  A partition is an
110  * operating system-specific portion of storage for a file system.  A single
111  * storage device (e.g. a physical disk-drive, flash memory, CD-ROM) may
112  * contain multiple partitions.  The object, if any, will reside on the
113  * partition <a name="partName">named</a> by some ancestor of the absolute
114  * form of this pathname.
115  *
116  * <p> A file system may implement restrictions to certain operations on the
117  * actual file-system object, such as reading, writing, and executing.  These
118  * restrictions are collectively known as <i>access permissions</i>.  The file
119  * system may have multiple sets of access permissions on a single object.
120  * For example, one set may apply to the object's <i>owner</i>, and another
121  * may apply to all other users.  The access permissions on an object may
122  * cause some methods in this class to fail.
123  *
124  * <p> Instances of the <code>File</code> class are immutable; that is, once
125  * created, the abstract pathname represented by a <code>File</code> object
126  * will never change.
127  *
128  * <p>On Android, the underlying filesystem encoding for filenames is always UTF-8.
129  *
130  * @author  unascribed
131  * @since   JDK1.0
132  */
133 
134 public class File
135     implements Serializable, Comparable<File>
136 {
137 
138     /**
139      * The FileSystem object representing the platform's local file system.
140      */
141     static private final FileSystem fs = FileSystem.getFileSystem();
142 
143     /**
144      * This abstract pathname's normalized pathname string. A normalized
145      * pathname string uses the default name-separator character and does not
146      * contain any duplicate or redundant separators.
147      *
148      * @serial
149      */
150     private String path;
151 
152     /**
153      * Enum type that indicates the status of a file path.
154      */
155     private static enum PathStatus { INVALID, CHECKED };
156 
157     /**
158      * The flag indicating whether the file path is invalid.
159      */
160     private transient PathStatus status = null;
161 
162     /**
163      * Check if the file has an invalid path. Currently, the inspection of
164      * a file path is very limited, and it only covers Nul character check.
165      * Returning true means the path is definitely invalid/garbage. But
166      * returning false does not guarantee that the path is valid.
167      *
168      * @return true if the file path is invalid.
169      */
isInvalid()170     final boolean isInvalid() {
171         if (status == null) {
172             status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
173                                                        : PathStatus.INVALID;
174         }
175         return status == PathStatus.INVALID;
176     }
177 
178     /**
179      * The length of this abstract pathname's prefix, or zero if it has no
180      * prefix.
181      */
182     private transient int prefixLength;
183 
184     /**
185      * Returns the length of this abstract pathname's prefix.
186      * For use by FileSystem classes.
187      */
getPrefixLength()188     int getPrefixLength() {
189         return prefixLength;
190     }
191 
192     /**
193      * The system-dependent default name-separator character.  This field is
194      * initialized to contain the first character of the value of the system
195      * property <code>file.separator</code>.  On UNIX systems the value of this
196      * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\\'</code>.
197      *
198      * @see     java.lang.System#getProperty(java.lang.String)
199      */
200     public static final char separatorChar = fs.getSeparator();
201 
202     /**
203      * The system-dependent default name-separator character, represented as a
204      * string for convenience.  This string contains a single character, namely
205      * <code>{@link #separatorChar}</code>.
206      */
207     public static final String separator = "" + separatorChar;
208 
209     /**
210      * The system-dependent path-separator character.  This field is
211      * initialized to contain the first character of the value of the system
212      * property <code>path.separator</code>.  This character is used to
213      * separate filenames in a sequence of files given as a <em>path list</em>.
214      * On UNIX systems, this character is <code>':'</code>; on Microsoft Windows systems it
215      * is <code>';'</code>.
216      *
217      * @see     java.lang.System#getProperty(java.lang.String)
218      */
219     public static final char pathSeparatorChar = fs.getPathSeparator();
220 
221     /**
222      * The system-dependent path-separator character, represented as a string
223      * for convenience.  This string contains a single character, namely
224      * <code>{@link #pathSeparatorChar}</code>.
225      */
226     public static final String pathSeparator = "" + pathSeparatorChar;
227 
228 
229     /* -- Constructors -- */
230 
231     /**
232      * Internal constructor for already-normalized pathname strings.
233      */
File(String pathname, int prefixLength)234     private File(String pathname, int prefixLength) {
235         this.path = pathname;
236         this.prefixLength = prefixLength;
237     }
238 
239     /**
240      * Internal constructor for already-normalized pathname strings.
241      * The parameter order is used to disambiguate this method from the
242      * public(File, String) constructor.
243      */
File(String child, File parent)244     private File(String child, File parent) {
245         assert parent.path != null;
246         assert (!parent.path.equals(""));
247         this.path = fs.resolve(parent.path, child);
248         this.prefixLength = parent.prefixLength;
249     }
250 
251     /**
252      * Creates a new <code>File</code> instance by converting the given
253      * pathname string into an abstract pathname.  If the given string is
254      * the empty string, then the result is the empty abstract pathname.
255      *
256      * @param   pathname  A pathname string
257      * @throws  NullPointerException
258      *          If the <code>pathname</code> argument is <code>null</code>
259      */
File(String pathname)260     public File(String pathname) {
261         if (pathname == null) {
262             throw new NullPointerException();
263         }
264         this.path = fs.normalize(pathname);
265         this.prefixLength = fs.prefixLength(this.path);
266     }
267 
268     /* Note: The two-argument File constructors do not interpret an empty
269        parent abstract pathname as the current user directory.  An empty parent
270        instead causes the child to be resolved against the system-dependent
271        directory defined by the FileSystem.getDefaultParent method.  On Unix
272        this default is "/", while on Microsoft Windows it is "\\".  This is required for
273        compatibility with the original behavior of this class. */
274 
275     /**
276      * Creates a new <code>File</code> instance from a parent pathname string
277      * and a child pathname string.
278      *
279      * <p> If <code>parent</code> is <code>null</code> then the new
280      * <code>File</code> instance is created as if by invoking the
281      * single-argument <code>File</code> constructor on the given
282      * <code>child</code> pathname string.
283      *
284      * <p> Otherwise the <code>parent</code> pathname string is taken to denote
285      * a directory, and the <code>child</code> pathname string is taken to
286      * denote either a directory or a file.  If the <code>child</code> pathname
287      * string is absolute then it is converted into a relative pathname in a
288      * system-dependent way.  If <code>parent</code> is the empty string then
289      * the new <code>File</code> instance is created by converting
290      * <code>child</code> into an abstract pathname and resolving the result
291      * against a system-dependent default directory.  Otherwise each pathname
292      * string is converted into an abstract pathname and the child abstract
293      * pathname is resolved against the parent.
294      *
295      * @param   parent  The parent pathname string
296      * @param   child   The child pathname string
297      * @throws  NullPointerException
298      *          If <code>child</code> is <code>null</code>
299      */
File(String parent, String child)300     public File(String parent, String child) {
301         if (child == null) {
302             throw new NullPointerException();
303         }
304         if (parent != null && !parent.isEmpty()) {
305             this.path = fs.resolve(fs.normalize(parent),
306                                    fs.normalize(child));
307         } else {
308             this.path = fs.normalize(child);
309         }
310         this.prefixLength = fs.prefixLength(this.path);
311     }
312 
313     /**
314      * Creates a new <code>File</code> instance from a parent abstract
315      * pathname and a child pathname string.
316      *
317      * <p> If <code>parent</code> is <code>null</code> then the new
318      * <code>File</code> instance is created as if by invoking the
319      * single-argument <code>File</code> constructor on the given
320      * <code>child</code> pathname string.
321      *
322      * <p> Otherwise the <code>parent</code> abstract pathname is taken to
323      * denote a directory, and the <code>child</code> pathname string is taken
324      * to denote either a directory or a file.  If the <code>child</code>
325      * pathname string is absolute then it is converted into a relative
326      * pathname in a system-dependent way.  If <code>parent</code> is the empty
327      * abstract pathname then the new <code>File</code> instance is created by
328      * converting <code>child</code> into an abstract pathname and resolving
329      * the result against a system-dependent default directory.  Otherwise each
330      * pathname string is converted into an abstract pathname and the child
331      * abstract pathname is resolved against the parent.
332      *
333      * @param   parent  The parent abstract pathname
334      * @param   child   The child pathname string
335      * @throws  NullPointerException
336      *          If <code>child</code> is <code>null</code>
337      */
File(File parent, String child)338     public File(File parent, String child) {
339         if (child == null) {
340             throw new NullPointerException();
341         }
342         if (parent != null) {
343             if (parent.path.equals("")) {
344                 this.path = fs.resolve(fs.getDefaultParent(),
345                                        fs.normalize(child));
346             } else {
347                 this.path = fs.resolve(parent.path,
348                                        fs.normalize(child));
349             }
350         } else {
351             this.path = fs.normalize(child);
352         }
353         this.prefixLength = fs.prefixLength(this.path);
354     }
355 
356     /**
357      * Creates a new <tt>File</tt> instance by converting the given
358      * <tt>file:</tt> URI into an abstract pathname.
359      *
360      * <p> The exact form of a <tt>file:</tt> URI is system-dependent, hence
361      * the transformation performed by this constructor is also
362      * system-dependent.
363      *
364      * <p> For a given abstract pathname <i>f</i> it is guaranteed that
365      *
366      * <blockquote><tt>
367      * new File(</tt><i>&nbsp;f</i><tt>.{@link #toURI() toURI}()).equals(</tt><i>&nbsp;f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
368      * </tt></blockquote>
369      *
370      * so long as the original abstract pathname, the URI, and the new abstract
371      * pathname are all created in (possibly different invocations of) the same
372      * Java virtual machine.  This relationship typically does not hold,
373      * however, when a <tt>file:</tt> URI that is created in a virtual machine
374      * on one operating system is converted into an abstract pathname in a
375      * virtual machine on a different operating system.
376      *
377      * @param  uri
378      *         An absolute, hierarchical URI with a scheme equal to
379      *         <tt>"file"</tt>, a non-empty path component, and undefined
380      *         authority, query, and fragment components
381      *
382      * @throws  NullPointerException
383      *          If <tt>uri</tt> is <tt>null</tt>
384      *
385      * @throws  IllegalArgumentException
386      *          If the preconditions on the parameter do not hold
387      *
388      * @see #toURI()
389      * @see java.net.URI
390      * @since 1.4
391      */
File(URI uri)392     public File(URI uri) {
393 
394         // Check our many preconditions
395         if (!uri.isAbsolute())
396             throw new IllegalArgumentException("URI is not absolute");
397         if (uri.isOpaque())
398             throw new IllegalArgumentException("URI is not hierarchical");
399         String scheme = uri.getScheme();
400         if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
401             throw new IllegalArgumentException("URI scheme is not \"file\"");
402         if (uri.getAuthority() != null)
403             throw new IllegalArgumentException("URI has an authority component");
404         if (uri.getFragment() != null)
405             throw new IllegalArgumentException("URI has a fragment component");
406         if (uri.getQuery() != null)
407             throw new IllegalArgumentException("URI has a query component");
408         String p = uri.getPath();
409         if (p.equals(""))
410             throw new IllegalArgumentException("URI path component is empty");
411 
412         // Okay, now initialize
413         p = fs.fromURIPath(p);
414         if (File.separatorChar != '/')
415             p = p.replace('/', File.separatorChar);
416         this.path = fs.normalize(p);
417         this.prefixLength = fs.prefixLength(this.path);
418     }
419 
420 
421     /* -- Path-component accessors -- */
422 
423     /**
424      * Returns the name of the file or directory denoted by this abstract
425      * pathname.  This is just the last name in the pathname's name
426      * sequence.  If the pathname's name sequence is empty, then the empty
427      * string is returned.
428      *
429      * @return  The name of the file or directory denoted by this abstract
430      *          pathname, or the empty string if this pathname's name sequence
431      *          is empty
432      */
getName()433     public String getName() {
434         int index = path.lastIndexOf(separatorChar);
435         if (index < prefixLength) return path.substring(prefixLength);
436         return path.substring(index + 1);
437     }
438 
439     /**
440      * Returns the pathname string of this abstract pathname's parent, or
441      * <code>null</code> if this pathname does not name a parent directory.
442      *
443      * <p> The <em>parent</em> of an abstract pathname consists of the
444      * pathname's prefix, if any, and each name in the pathname's name
445      * sequence except for the last.  If the name sequence is empty then
446      * the pathname does not name a parent directory.
447      *
448      * @return  The pathname string of the parent directory named by this
449      *          abstract pathname, or <code>null</code> if this pathname
450      *          does not name a parent
451      */
getParent()452     public String getParent() {
453         int index = path.lastIndexOf(separatorChar);
454         if (index < prefixLength) {
455             if ((prefixLength > 0) && (path.length() > prefixLength))
456                 return path.substring(0, prefixLength);
457             return null;
458         }
459         return path.substring(0, index);
460     }
461 
462     /**
463      * Returns the abstract pathname of this abstract pathname's parent,
464      * or <code>null</code> if this pathname does not name a parent
465      * directory.
466      *
467      * <p> The <em>parent</em> of an abstract pathname consists of the
468      * pathname's prefix, if any, and each name in the pathname's name
469      * sequence except for the last.  If the name sequence is empty then
470      * the pathname does not name a parent directory.
471      *
472      * @return  The abstract pathname of the parent directory named by this
473      *          abstract pathname, or <code>null</code> if this pathname
474      *          does not name a parent
475      *
476      * @since 1.2
477      */
getParentFile()478     public File getParentFile() {
479         String p = this.getParent();
480         if (p == null) return null;
481         return new File(p, this.prefixLength);
482     }
483 
484     /**
485      * Converts this abstract pathname into a pathname string.  The resulting
486      * string uses the {@link #separator default name-separator character} to
487      * separate the names in the name sequence.
488      *
489      * @return  The string form of this abstract pathname
490      */
getPath()491     public String getPath() {
492         return path;
493     }
494 
495 
496     /* -- Path operations -- */
497 
498     /**
499      * Tests whether this abstract pathname is absolute.  The definition of
500      * absolute pathname is system dependent.  On Android, absolute paths start with
501      * the character '/'.
502      *
503      * @return  <code>true</code> if this abstract pathname is absolute,
504      *          <code>false</code> otherwise
505      */
isAbsolute()506     public boolean isAbsolute() {
507         return fs.isAbsolute(this);
508     }
509 
510     /**
511      * Returns the absolute path of this file. An absolute path is a path that starts at a root
512      * of the file system. On Android, there is only one root: {@code /}.
513      *
514      * <p>A common use for absolute paths is when passing paths to a {@code Process} as
515      * command-line arguments, to remove the requirement implied by relative paths, that the
516      * child must have the same working directory as its parent.
517      *
518      * @return  The absolute pathname string denoting the same file or
519      *          directory as this abstract pathname
520      *
521      * @see     java.io.File#isAbsolute()
522      */
getAbsolutePath()523     public String getAbsolutePath() {
524         return fs.resolve(this);
525     }
526 
527     /**
528      * Returns the absolute form of this abstract pathname.  Equivalent to
529      * <code>new&nbsp;File(this.{@link #getAbsolutePath})</code>.
530      *
531      * @return  The absolute abstract pathname denoting the same file or
532      *          directory as this abstract pathname
533      *
534      * @throws  SecurityException
535      *          If a required system property value cannot be accessed.
536      *
537      * @since 1.2
538      */
getAbsoluteFile()539     public File getAbsoluteFile() {
540         String absPath = getAbsolutePath();
541         return new File(absPath, fs.prefixLength(absPath));
542     }
543 
544     /**
545      * Returns the canonical pathname string of this abstract pathname.
546      *
547      * <p> A canonical pathname is both absolute and unique.  The precise
548      * definition of canonical form is system-dependent.  This method first
549      * converts this pathname to absolute form if necessary, as if by invoking the
550      * {@link #getAbsolutePath} method, and then maps it to its unique form in a
551      * system-dependent way.  This typically involves removing redundant names
552      * such as <tt>"."</tt> and <tt>".."</tt> from the pathname, resolving
553      * symbolic links (on UNIX platforms), and converting drive letters to a
554      * standard case (on Microsoft Windows platforms).
555      *
556      * <p> Every pathname that denotes an existing file or directory has a
557      * unique canonical form.  Every pathname that denotes a nonexistent file
558      * or directory also has a unique canonical form.  The canonical form of
559      * the pathname of a nonexistent file or directory may be different from
560      * the canonical form of the same pathname after the file or directory is
561      * created.  Similarly, the canonical form of the pathname of an existing
562      * file or directory may be different from the canonical form of the same
563      * pathname after the file or directory is deleted.
564      *
565      * @return  The canonical pathname string denoting the same file or
566      *          directory as this abstract pathname
567      *
568      * @throws  IOException
569      *          If an I/O error occurs, which is possible because the
570      *          construction of the canonical pathname may require
571      *          filesystem queries
572      *
573      * @throws  SecurityException
574      *          If a required system property value cannot be accessed, or
575      *          if a security manager exists and its <code>{@link
576      *          java.lang.SecurityManager#checkRead}</code> method denies
577      *          read access to the file
578      *
579      * @since   JDK1.1
580      * @see     Path#toRealPath
581      */
getCanonicalPath()582     public String getCanonicalPath() throws IOException {
583         if (isInvalid()) {
584             throw new IOException("Invalid file path");
585         }
586         return fs.canonicalize(fs.resolve(this));
587     }
588 
589     /**
590      * Returns the canonical form of this abstract pathname.  Equivalent to
591      * <code>new&nbsp;File(this.{@link #getCanonicalPath})</code>.
592      *
593      * @return  The canonical pathname string denoting the same file or
594      *          directory as this abstract pathname
595      *
596      * @throws  IOException
597      *          If an I/O error occurs, which is possible because the
598      *          construction of the canonical pathname may require
599      *          filesystem queries
600      *
601      * @throws  SecurityException
602      *          If a required system property value cannot be accessed, or
603      *          if a security manager exists and its <code>{@link
604      *          java.lang.SecurityManager#checkRead}</code> method denies
605      *          read access to the file
606      *
607      * @since 1.2
608      * @see     Path#toRealPath
609      */
getCanonicalFile()610     public File getCanonicalFile() throws IOException {
611         String canonPath = getCanonicalPath();
612         return new File(canonPath, fs.prefixLength(canonPath));
613     }
614 
slashify(String path, boolean isDirectory)615     private static String slashify(String path, boolean isDirectory) {
616         String p = path;
617         if (File.separatorChar != '/')
618             p = p.replace(File.separatorChar, '/');
619         if (!p.startsWith("/"))
620             p = "/" + p;
621         if (!p.endsWith("/") && isDirectory)
622             p = p + "/";
623         return p;
624     }
625 
626     /**
627      * Converts this abstract pathname into a <code>file:</code> URL.  The
628      * exact form of the URL is system-dependent.  If it can be determined that
629      * the file denoted by this abstract pathname is a directory, then the
630      * resulting URL will end with a slash.
631      *
632      * @return  A URL object representing the equivalent file URL
633      *
634      * @throws  MalformedURLException
635      *          If the path cannot be parsed as a URL
636      *
637      * @see     #toURI()
638      * @see     java.net.URI
639      * @see     java.net.URI#toURL()
640      * @see     java.net.URL
641      * @since   1.2
642      *
643      * @deprecated This method does not automatically escape characters that
644      * are illegal in URLs.  It is recommended that new code convert an
645      * abstract pathname into a URL by first converting it into a URI, via the
646      * {@link #toURI() toURI} method, and then converting the URI into a URL
647      * via the {@link java.net.URI#toURL() URI.toURL} method.
648      */
649     @Deprecated
toURL()650     public URL toURL() throws MalformedURLException {
651         if (isInvalid()) {
652             throw new MalformedURLException("Invalid file path");
653         }
654         return new URL("file", "", slashify(getAbsolutePath(),
655                 getAbsoluteFile().isDirectory()));
656     }
657 
658     /**
659      * Constructs a <tt>file:</tt> URI that represents this abstract pathname.
660      *
661      * <p> The exact form of the URI is system-dependent.  If it can be
662      * determined that the file denoted by this abstract pathname is a
663      * directory, then the resulting URI will end with a slash.
664      *
665      * <p> For a given abstract pathname <i>f</i>, it is guaranteed that
666      *
667      * <blockquote><tt>
668      * new {@link #File(java.net.URI) File}(</tt><i>&nbsp;f</i><tt>.toURI()).equals(</tt><i>&nbsp;f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
669      * </tt></blockquote>
670      *
671      * so long as the original abstract pathname, the URI, and the new abstract
672      * pathname are all created in (possibly different invocations of) the same
673      * Java virtual machine.  Due to the system-dependent nature of abstract
674      * pathnames, however, this relationship typically does not hold when a
675      * <tt>file:</tt> URI that is created in a virtual machine on one operating
676      * system is converted into an abstract pathname in a virtual machine on a
677      * different operating system.
678      *
679      * <p> Note that when this abstract pathname represents a UNC pathname then
680      * all components of the UNC (including the server name component) are encoded
681      * in the {@code URI} path. The authority component is undefined, meaning
682      * that it is represented as {@code null}.
683      *
684      * @return  An absolute, hierarchical URI with a scheme equal to
685      *          <tt>"file"</tt>, a path representing this abstract pathname,
686      *          and undefined authority, query, and fragment components
687      * @throws SecurityException If a required system property value cannot
688      * be accessed.
689      *
690      * @see #File(java.net.URI)
691      * @see java.net.URI
692      * @see java.net.URI#toURL()
693      * @since 1.4
694      */
toURI()695     public URI toURI() {
696         try {
697             File f = getAbsoluteFile();
698             String sp = slashify(f.getPath(), f.isDirectory());
699             if (sp.startsWith("//"))
700                 sp = "//" + sp;
701             return new URI("file", null, sp, null);
702         } catch (URISyntaxException x) {
703             throw new Error(x);         // Can't happen
704         }
705     }
706 
707 
708     /* -- Attribute accessors -- */
709 
710     /**
711      * Tests whether the application can read the file denoted by this
712      * abstract pathname.
713      *
714      * @return  <code>true</code> if and only if the file specified by this
715      *          abstract pathname exists <em>and</em> can be read by the
716      *          application; <code>false</code> otherwise
717      *
718      * @throws  SecurityException
719      *          If a security manager exists and its <code>{@link
720      *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
721      *          method denies read access to the file
722      */
canRead()723     public boolean canRead() {
724         SecurityManager security = System.getSecurityManager();
725         if (security != null) {
726             security.checkRead(path);
727         }
728         if (isInvalid()) {
729             return false;
730         }
731         return fs.checkAccess(this, FileSystem.ACCESS_READ);
732     }
733 
734     /**
735      * Tests whether the application can modify the file denoted by this
736      * abstract pathname.
737      *
738      * @return  <code>true</code> if and only if the file system actually
739      *          contains a file denoted by this abstract pathname <em>and</em>
740      *          the application is allowed to write to the file;
741      *          <code>false</code> otherwise.
742      *
743      * @throws  SecurityException
744      *          If a security manager exists and its <code>{@link
745      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
746      *          method denies write access to the file
747      */
canWrite()748     public boolean canWrite() {
749         SecurityManager security = System.getSecurityManager();
750         if (security != null) {
751             security.checkWrite(path);
752         }
753         if (isInvalid()) {
754             return false;
755         }
756         return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
757     }
758 
759     /**
760      * Tests whether the file or directory denoted by this abstract pathname
761      * exists.
762      *
763      * @return  <code>true</code> if and only if the file or directory denoted
764      *          by this abstract pathname exists; <code>false</code> otherwise
765      *
766      * @throws  SecurityException
767      *          If a security manager exists and its <code>{@link
768      *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
769      *          method denies read access to the file or directory
770      */
exists()771     public boolean exists() {
772         SecurityManager security = System.getSecurityManager();
773         if (security != null) {
774             security.checkRead(path);
775         }
776         if (isInvalid()) {
777             return false;
778         }
779 
780         return fs.checkAccess(this, FileSystem.ACCESS_OK);
781     }
782 
783     /**
784      * Tests whether the file denoted by this abstract pathname is a
785      * directory.
786      *
787      * @return <code>true</code> if and only if the file denoted by this
788      *          abstract pathname exists <em>and</em> is a directory;
789      *          <code>false</code> otherwise
790      *
791      * @throws  SecurityException
792      *          If a security manager exists and its <code>{@link
793      *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
794      *          method denies read access to the file
795      */
isDirectory()796     public boolean isDirectory() {
797         SecurityManager security = System.getSecurityManager();
798         if (security != null) {
799             security.checkRead(path);
800         }
801         if (isInvalid()) {
802             return false;
803         }
804         return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
805                 != 0);
806     }
807 
808     /**
809      * Tests whether the file denoted by this abstract pathname is a normal
810      * file.  A file is <em>normal</em> if it is not a directory and, in
811      * addition, satisfies other system-dependent criteria.  Any non-directory
812      * file created by a Java application is guaranteed to be a normal file.
813      *
814      * @return  <code>true</code> if and only if the file denoted by this
815      *          abstract pathname exists <em>and</em> is a normal file;
816      *          <code>false</code> otherwise
817      *
818      * @throws  SecurityException
819      *          If a security manager exists and its <code>{@link
820      *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
821      *          method denies read access to the file
822      */
isFile()823     public boolean isFile() {
824         SecurityManager security = System.getSecurityManager();
825         if (security != null) {
826             security.checkRead(path);
827         }
828         if (isInvalid()) {
829             return false;
830         }
831         return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
832     }
833 
834     /**
835      * Tests whether the file named by this abstract pathname is a hidden
836      * file.  The exact definition of <em>hidden</em> is system-dependent.  On
837      * UNIX systems, a file is considered to be hidden if its name begins with
838      * a period character (<code>'.'</code>).  On Microsoft Windows systems, a file is
839      * considered to be hidden if it has been marked as such in the filesystem.
840      *
841      * @return  <code>true</code> if and only if the file denoted by this
842      *          abstract pathname is hidden according to the conventions of the
843      *          underlying platform
844      *
845      * @throws  SecurityException
846      *          If a security manager exists and its <code>{@link
847      *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
848      *          method denies read access to the file
849      *
850      * @since 1.2
851      */
isHidden()852     public boolean isHidden() {
853         SecurityManager security = System.getSecurityManager();
854         if (security != null) {
855             security.checkRead(path);
856         }
857         if (isInvalid()) {
858             return false;
859         }
860         return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
861     }
862 
863     /**
864      * Returns the time that the file denoted by this abstract pathname was
865      * last modified.
866      *
867      * @return  A <code>long</code> value representing the time the file was
868      *          last modified, measured in milliseconds since the epoch
869      *          (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
870      *          file does not exist or if an I/O error occurs
871      *
872      * @throws  SecurityException
873      *          If a security manager exists and its <code>{@link
874      *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
875      *          method denies read access to the file
876      */
lastModified()877     public long lastModified() {
878         SecurityManager security = System.getSecurityManager();
879         if (security != null) {
880             security.checkRead(path);
881         }
882         if (isInvalid()) {
883             return 0L;
884         }
885         return fs.getLastModifiedTime(this);
886     }
887 
888     /**
889      * Returns the length of the file denoted by this abstract pathname.
890      * The return value is unspecified if this pathname denotes a directory.
891      *
892      * @return  The length, in bytes, of the file denoted by this abstract
893      *          pathname, or <code>0L</code> if the file does not exist.  Some
894      *          operating systems may return <code>0L</code> for pathnames
895      *          denoting system-dependent entities such as devices or pipes.
896      *
897      * @throws  SecurityException
898      *          If a security manager exists and its <code>{@link
899      *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
900      *          method denies read access to the file
901      */
length()902     public long length() {
903         SecurityManager security = System.getSecurityManager();
904         if (security != null) {
905             security.checkRead(path);
906         }
907         if (isInvalid()) {
908             return 0L;
909         }
910         return fs.getLength(this);
911     }
912 
913 
914     /* -- File operations -- */
915 
916     /**
917      * Atomically creates a new, empty file named by this abstract pathname if
918      * and only if a file with this name does not yet exist.  The check for the
919      * existence of the file and the creation of the file if it does not exist
920      * are a single operation that is atomic with respect to all other
921      * filesystem activities that might affect the file.
922      * <P>
923      * Note: this method should <i>not</i> be used for file-locking, as
924      * the resulting protocol cannot be made to work reliably. The
925      * {@link java.nio.channels.FileLock FileLock}
926      * facility should be used instead.
927      *
928      * @return  <code>true</code> if the named file does not exist and was
929      *          successfully created; <code>false</code> if the named file
930      *          already exists
931      *
932      * @throws  IOException
933      *          If an I/O error occurred
934      *
935      * @throws  SecurityException
936      *          If a security manager exists and its <code>{@link
937      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
938      *          method denies write access to the file
939      *
940      * @since 1.2
941      */
createNewFile()942     public boolean createNewFile() throws IOException {
943         SecurityManager security = System.getSecurityManager();
944         if (security != null) security.checkWrite(path);
945         if (isInvalid()) {
946             throw new IOException("Invalid file path");
947         }
948         return fs.createFileExclusively(path);
949     }
950 
951     /**
952      * Deletes the file or directory denoted by this abstract pathname.  If
953      * this pathname denotes a directory, then the directory must be empty in
954      * order to be deleted.
955      *
956      * @return  <code>true</code> if and only if the file or directory is
957      *          successfully deleted; <code>false</code> otherwise
958      *
959      * @throws  SecurityException
960      *          If a security manager exists and its <code>{@link
961      *          java.lang.SecurityManager#checkDelete}</code> method denies
962      *          delete access to the file
963      */
delete()964     public boolean delete() {
965         SecurityManager security = System.getSecurityManager();
966         if (security != null) {
967             security.checkDelete(path);
968         }
969         if (isInvalid()) {
970             return false;
971         }
972         return fs.delete(this);
973     }
974 
975     /**
976      * Requests that the file or directory denoted by this abstract
977      * pathname be deleted when the virtual machine terminates.
978      * Files (or directories) are deleted in the reverse order that
979      * they are registered. Invoking this method to delete a file or
980      * directory that is already registered for deletion has no effect.
981      * Deletion will be attempted only for normal termination of the
982      * virtual machine, as defined by the Java Language Specification.
983      *
984      * <p> Once deletion has been requested, it is not possible to cancel the
985      * request.  This method should therefore be used with care.
986      *
987      * <P>
988      * Note: this method should <i>not</i> be used for file-locking, as
989      * the resulting protocol cannot be made to work reliably. The
990      * {@link java.nio.channels.FileLock FileLock}
991      * facility should be used instead.
992      *
993      * <p><i>Note that on Android, the application lifecycle does not include VM termination,
994      * so calling this method will not ensure that files are deleted</i>. Instead, you should
995      * use the most appropriate out of:
996      * <ul>
997      * <li>Use a {@code finally} clause to manually invoke {@link #delete}.
998      * <li>Maintain your own set of files to delete, and process it at an appropriate point
999      * in your application's lifecycle.
1000      * <li>Use the Unix trick of deleting the file as soon as all readers and writers have
1001      * opened it. No new readers/writers will be able to access the file, but all existing
1002      * ones will still have access until the last one closes the file.
1003      * </ul>
1004      *
1005      * @throws  SecurityException
1006      *          If a security manager exists and its <code>{@link
1007      *          java.lang.SecurityManager#checkDelete}</code> method denies
1008      *          delete access to the file
1009      *
1010      * @see #delete
1011      *
1012      * @since 1.2
1013      */
deleteOnExit()1014     public void deleteOnExit() {
1015         SecurityManager security = System.getSecurityManager();
1016         if (security != null) {
1017             security.checkDelete(path);
1018         }
1019         if (isInvalid()) {
1020             return;
1021         }
1022         DeleteOnExitHook.add(path);
1023     }
1024 
1025     /**
1026      * Returns an array of strings naming the files and directories in the
1027      * directory denoted by this abstract pathname.
1028      *
1029      * <p> If this abstract pathname does not denote a directory, then this
1030      * method returns {@code null}.  Otherwise an array of strings is
1031      * returned, one for each file or directory in the directory.  Names
1032      * denoting the directory itself and the directory's parent directory are
1033      * not included in the result.  Each string is a file name rather than a
1034      * complete path.
1035      *
1036      * <p> There is no guarantee that the name strings in the resulting array
1037      * will appear in any specific order; they are not, in particular,
1038      * guaranteed to appear in alphabetical order.
1039      *
1040      * @return  An array of strings naming the files and directories in the
1041      *          directory denoted by this abstract pathname.  The array will be
1042      *          empty if the directory is empty.  Returns {@code null} if
1043      *          this abstract pathname does not denote a directory, or if an
1044      *          I/O error occurs.
1045      *
1046      * @throws  SecurityException
1047      *          If a security manager exists and its {@link
1048      *          SecurityManager#checkRead(String)} method denies read access to
1049      *          the directory
1050      */
list()1051     public String[] list() {
1052         SecurityManager security = System.getSecurityManager();
1053         if (security != null) {
1054             security.checkRead(path);
1055         }
1056         if (isInvalid()) {
1057             return null;
1058         }
1059         return fs.list(this);
1060     }
1061 
1062     /**
1063      * Returns an array of strings naming the files and directories in the
1064      * directory denoted by this abstract pathname that satisfy the specified
1065      * filter.  The behavior of this method is the same as that of the
1066      * {@link #list()} method, except that the strings in the returned array
1067      * must satisfy the filter.  If the given {@code filter} is {@code null}
1068      * then all names are accepted.  Otherwise, a name satisfies the filter if
1069      * and only if the value {@code true} results when the {@link
1070      * FilenameFilter#accept FilenameFilter.accept(File,&nbsp;String)} method
1071      * of the filter is invoked on this abstract pathname and the name of a
1072      * file or directory in the directory that it denotes.
1073      *
1074      * @param  filter
1075      *         A filename filter
1076      *
1077      * @return  An array of strings naming the files and directories in the
1078      *          directory denoted by this abstract pathname that were accepted
1079      *          by the given {@code filter}.  The array will be empty if the
1080      *          directory is empty or if no names were accepted by the filter.
1081      *          Returns {@code null} if this abstract pathname does not denote
1082      *          a directory, or if an I/O error occurs.
1083      *
1084      * @throws  SecurityException
1085      *          If a security manager exists and its {@link
1086      *          SecurityManager#checkRead(String)} method denies read access to
1087      *          the directory
1088      *
1089      */
list(FilenameFilter filter)1090     public String[] list(FilenameFilter filter) {
1091         String names[] = list();
1092         if ((names == null) || (filter == null)) {
1093             return names;
1094         }
1095         List<String> v = new ArrayList<>();
1096         for (int i = 0 ; i < names.length ; i++) {
1097             if (filter.accept(this, names[i])) {
1098                 v.add(names[i]);
1099             }
1100         }
1101         return v.toArray(new String[v.size()]);
1102     }
1103 
1104     /**
1105      * Returns an array of abstract pathnames denoting the files in the
1106      * directory denoted by this abstract pathname.
1107      *
1108      * <p> If this abstract pathname does not denote a directory, then this
1109      * method returns {@code null}.  Otherwise an array of {@code File} objects
1110      * is returned, one for each file or directory in the directory.  Pathnames
1111      * denoting the directory itself and the directory's parent directory are
1112      * not included in the result.  Each resulting abstract pathname is
1113      * constructed from this abstract pathname using the {@link #File(File,
1114      * String) File(File,&nbsp;String)} constructor.  Therefore if this
1115      * pathname is absolute then each resulting pathname is absolute; if this
1116      * pathname is relative then each resulting pathname will be relative to
1117      * the same directory.
1118      *
1119      * <p> There is no guarantee that the name strings in the resulting array
1120      * will appear in any specific order; they are not, in particular,
1121      * guaranteed to appear in alphabetical order.
1122      *
1123      * @return  An array of abstract pathnames denoting the files and
1124      *          directories in the directory denoted by this abstract pathname.
1125      *          The array will be empty if the directory is empty.  Returns
1126      *          {@code null} if this abstract pathname does not denote a
1127      *          directory, or if an I/O error occurs.
1128      *
1129      * @throws  SecurityException
1130      *          If a security manager exists and its {@link
1131      *          SecurityManager#checkRead(String)} method denies read access to
1132      *          the directory
1133      *
1134      * @since  1.2
1135      */
listFiles()1136     public File[] listFiles() {
1137         String[] ss = list();
1138         if (ss == null) return null;
1139         int n = ss.length;
1140         File[] fs = new File[n];
1141         for (int i = 0; i < n; i++) {
1142             fs[i] = new File(ss[i], this);
1143         }
1144         return fs;
1145     }
1146 
1147     /**
1148      * Returns an array of abstract pathnames denoting the files and
1149      * directories in the directory denoted by this abstract pathname that
1150      * satisfy the specified filter.  The behavior of this method is the same
1151      * as that of the {@link #listFiles()} method, except that the pathnames in
1152      * the returned array must satisfy the filter.  If the given {@code filter}
1153      * is {@code null} then all pathnames are accepted.  Otherwise, a pathname
1154      * satisfies the filter if and only if the value {@code true} results when
1155      * the {@link FilenameFilter#accept
1156      * FilenameFilter.accept(File,&nbsp;String)} method of the filter is
1157      * invoked on this abstract pathname and the name of a file or directory in
1158      * the directory that it denotes.
1159      *
1160      * @param  filter
1161      *         A filename filter
1162      *
1163      * @return  An array of abstract pathnames denoting the files and
1164      *          directories in the directory denoted by this abstract pathname.
1165      *          The array will be empty if the directory is empty.  Returns
1166      *          {@code null} if this abstract pathname does not denote a
1167      *          directory, or if an I/O error occurs.
1168      *
1169      * @throws  SecurityException
1170      *          If a security manager exists and its {@link
1171      *          SecurityManager#checkRead(String)} method denies read access to
1172      *          the directory
1173      *
1174      * @since  1.2
1175      */
listFiles(FilenameFilter filter)1176     public File[] listFiles(FilenameFilter filter) {
1177         String ss[] = list();
1178         if (ss == null) return null;
1179         ArrayList<File> files = new ArrayList<>();
1180         for (String s : ss)
1181             if ((filter == null) || filter.accept(this, s))
1182                 files.add(new File(s, this));
1183         return files.toArray(new File[files.size()]);
1184     }
1185 
1186     /**
1187      * Returns an array of abstract pathnames denoting the files and
1188      * directories in the directory denoted by this abstract pathname that
1189      * satisfy the specified filter.  The behavior of this method is the same
1190      * as that of the {@link #listFiles()} method, except that the pathnames in
1191      * the returned array must satisfy the filter.  If the given {@code filter}
1192      * is {@code null} then all pathnames are accepted.  Otherwise, a pathname
1193      * satisfies the filter if and only if the value {@code true} results when
1194      * the {@link FileFilter#accept FileFilter.accept(File)} method of the
1195      * filter is invoked on the pathname.
1196      *
1197      * @param  filter
1198      *         A file filter
1199      *
1200      * @return  An array of abstract pathnames denoting the files and
1201      *          directories in the directory denoted by this abstract pathname.
1202      *          The array will be empty if the directory is empty.  Returns
1203      *          {@code null} if this abstract pathname does not denote a
1204      *          directory, or if an I/O error occurs.
1205      *
1206      * @throws  SecurityException
1207      *          If a security manager exists and its {@link
1208      *          SecurityManager#checkRead(String)} method denies read access to
1209      *          the directory
1210      *
1211      * @since  1.2
1212      */
listFiles(FileFilter filter)1213     public File[] listFiles(FileFilter filter) {
1214         String ss[] = list();
1215         if (ss == null) return null;
1216         ArrayList<File> files = new ArrayList<>();
1217         for (String s : ss) {
1218             File f = new File(s, this);
1219             if ((filter == null) || filter.accept(f))
1220                 files.add(f);
1221         }
1222         return files.toArray(new File[files.size()]);
1223     }
1224 
1225     /**
1226      * Creates the directory named by this abstract pathname.
1227      *
1228      * @return  <code>true</code> if and only if the directory was
1229      *          created; <code>false</code> otherwise
1230      *
1231      * @throws  SecurityException
1232      *          If a security manager exists and its <code>{@link
1233      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1234      *          method does not permit the named directory to be created
1235      */
mkdir()1236     public boolean mkdir() {
1237         SecurityManager security = System.getSecurityManager();
1238         if (security != null) {
1239             security.checkWrite(path);
1240         }
1241         if (isInvalid()) {
1242             return false;
1243         }
1244         return fs.createDirectory(this);
1245     }
1246 
1247     /**
1248      * Creates the directory named by this abstract pathname, including any
1249      * necessary but nonexistent parent directories.  Note that if this
1250      * operation fails it may have succeeded in creating some of the necessary
1251      * parent directories.
1252      *
1253      * @return  <code>true</code> if and only if the directory was created,
1254      *          along with all necessary parent directories; <code>false</code>
1255      *          otherwise
1256      *
1257      * @throws  SecurityException
1258      *          If a security manager exists and its <code>{@link
1259      *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
1260      *          method does not permit verification of the existence of the
1261      *          named directory and all necessary parent directories; or if
1262      *          the <code>{@link
1263      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1264      *          method does not permit the named directory and all necessary
1265      *          parent directories to be created
1266      */
mkdirs()1267     public boolean mkdirs() {
1268         if (exists()) {
1269             return false;
1270         }
1271         if (mkdir()) {
1272             return true;
1273         }
1274         File canonFile = null;
1275         try {
1276             canonFile = getCanonicalFile();
1277         } catch (IOException e) {
1278             return false;
1279         }
1280 
1281         File parent = canonFile.getParentFile();
1282         return (parent != null && (parent.mkdirs() || parent.exists()) &&
1283                 canonFile.mkdir());
1284     }
1285 
1286     /**
1287      * Renames the file denoted by this abstract pathname.
1288      *
1289      * <p>Many failures are possible. Some of the more likely failures include:
1290      * <ul>
1291      * <li>Write permission is required on the directories containing both the source and
1292      * destination paths.
1293      * <li>Search permission is required for all parents of both paths.
1294      * <li>Both paths be on the same mount point. On Android, applications are most likely to hit
1295      * this restriction when attempting to copy between internal storage and an SD card.
1296      * </ul>
1297      *
1298      * <p>The return value should always be checked to make sure
1299      * that the rename operation was successful.
1300      *
1301      * @param  dest  The new abstract pathname for the named file
1302      *
1303      * @return  <code>true</code> if and only if the renaming succeeded;
1304      *          <code>false</code> otherwise
1305      *
1306      * @throws  SecurityException
1307      *          If a security manager exists and its <code>{@link
1308      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1309      *          method denies write access to either the old or new pathnames
1310      *
1311      * @throws  NullPointerException
1312      *          If parameter <code>dest</code> is <code>null</code>
1313      */
renameTo(File dest)1314     public boolean renameTo(File dest) {
1315         SecurityManager security = System.getSecurityManager();
1316         if (security != null) {
1317             security.checkWrite(path);
1318             security.checkWrite(dest.path);
1319         }
1320         if (dest == null) {
1321             throw new NullPointerException();
1322         }
1323         if (this.isInvalid() || dest.isInvalid()) {
1324             return false;
1325         }
1326         return fs.rename(this, dest);
1327     }
1328 
1329     /**
1330      * Sets the last-modified time of the file or directory named by this
1331      * abstract pathname.
1332      *
1333      * <p> All platforms support file-modification times to the nearest second,
1334      * but some provide more precision.  The argument will be truncated to fit
1335      * the supported precision.  If the operation succeeds and no intervening
1336      * operations on the file take place, then the next invocation of the
1337      * <code>{@link #lastModified}</code> method will return the (possibly
1338      * truncated) <code>time</code> argument that was passed to this method.
1339      *
1340      * @param  time  The new last-modified time, measured in milliseconds since
1341      *               the epoch (00:00:00 GMT, January 1, 1970)
1342      *
1343      * @return <code>true</code> if and only if the operation succeeded;
1344      *          <code>false</code> otherwise
1345      *
1346      * @throws  IllegalArgumentException  If the argument is negative
1347      *
1348      * @throws  SecurityException
1349      *          If a security manager exists and its <code>{@link
1350      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1351      *          method denies write access to the named file
1352      *
1353      * @since 1.2
1354      */
setLastModified(long time)1355     public boolean setLastModified(long time) {
1356         if (time < 0) throw new IllegalArgumentException("Negative time");
1357         SecurityManager security = System.getSecurityManager();
1358         if (security != null) {
1359             security.checkWrite(path);
1360         }
1361         if (isInvalid()) {
1362             return false;
1363         }
1364         return fs.setLastModifiedTime(this, time);
1365     }
1366 
1367     /**
1368      * Marks the file or directory named by this abstract pathname so that
1369      * only read operations are allowed.  After invoking this method the file
1370      * or directory is guaranteed not to change until it is either deleted or
1371      * marked to allow write access.  Whether or not a read-only file or
1372      * directory may be deleted depends upon the underlying system.
1373      *
1374      * @return <code>true</code> if and only if the operation succeeded;
1375      *          <code>false</code> otherwise
1376      *
1377      * @throws  SecurityException
1378      *          If a security manager exists and its <code>{@link
1379      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1380      *          method denies write access to the named file
1381      *
1382      * @since 1.2
1383      */
setReadOnly()1384     public boolean setReadOnly() {
1385         SecurityManager security = System.getSecurityManager();
1386         if (security != null) {
1387             security.checkWrite(path);
1388         }
1389         if (isInvalid()) {
1390             return false;
1391         }
1392         return fs.setReadOnly(this);
1393     }
1394 
1395     /**
1396      * Sets the owner's or everybody's write permission for this abstract
1397      * pathname.
1398      *
1399      * @param   writable
1400      *          If <code>true</code>, sets the access permission to allow write
1401      *          operations; if <code>false</code> to disallow write operations
1402      *
1403      * @param   ownerOnly
1404      *          If <code>true</code>, the write permission applies only to the
1405      *          owner's write permission; otherwise, it applies to everybody.  If
1406      *          the underlying file system can not distinguish the owner's write
1407      *          permission from that of others, then the permission will apply to
1408      *          everybody, regardless of this value.
1409      *
1410      * @return  <code>true</code> if and only if the operation succeeded. The
1411      *          operation will fail if the user does not have permission to change
1412      *          the access permissions of this abstract pathname.
1413      *
1414      * @throws  SecurityException
1415      *          If a security manager exists and its <code>{@link
1416      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1417      *          method denies write access to the named file
1418      *
1419      * @since 1.6
1420      */
setWritable(boolean writable, boolean ownerOnly)1421     public boolean setWritable(boolean writable, boolean ownerOnly) {
1422         SecurityManager security = System.getSecurityManager();
1423         if (security != null) {
1424             security.checkWrite(path);
1425         }
1426         if (isInvalid()) {
1427             return false;
1428         }
1429         return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);
1430     }
1431 
1432     /**
1433      * A convenience method to set the owner's write permission for this abstract
1434      * pathname.
1435      *
1436      * <p> An invocation of this method of the form <tt>file.setWritable(arg)</tt>
1437      * behaves in exactly the same way as the invocation
1438      *
1439      * <pre>
1440      *     file.setWritable(arg, true) </pre>
1441      *
1442      * @param   writable
1443      *          If <code>true</code>, sets the access permission to allow write
1444      *          operations; if <code>false</code> to disallow write operations
1445      *
1446      * @return  <code>true</code> if and only if the operation succeeded.  The
1447      *          operation will fail if the user does not have permission to
1448      *          change the access permissions of this abstract pathname.
1449      *
1450      * @throws  SecurityException
1451      *          If a security manager exists and its <code>{@link
1452      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1453      *          method denies write access to the file
1454      *
1455      * @since 1.6
1456      */
setWritable(boolean writable)1457     public boolean setWritable(boolean writable) {
1458         return setWritable(writable, true);
1459     }
1460 
1461     /**
1462      * Sets the owner's or everybody's read permission for this abstract
1463      * pathname.
1464      *
1465      * @param   readable
1466      *          If <code>true</code>, sets the access permission to allow read
1467      *          operations; if <code>false</code> to disallow read operations
1468      *
1469      * @param   ownerOnly
1470      *          If <code>true</code>, the read permission applies only to the
1471      *          owner's read permission; otherwise, it applies to everybody.  If
1472      *          the underlying file system can not distinguish the owner's read
1473      *          permission from that of others, then the permission will apply to
1474      *          everybody, regardless of this value.
1475      *
1476      * @return  <code>true</code> if and only if the operation succeeded.  The
1477      *          operation will fail if the user does not have permission to
1478      *          change the access permissions of this abstract pathname.  If
1479      *          <code>readable</code> is <code>false</code> and the underlying
1480      *          file system does not implement a read permission, then the
1481      *          operation will fail.
1482      *
1483      * @throws  SecurityException
1484      *          If a security manager exists and its <code>{@link
1485      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1486      *          method denies write access to the file
1487      *
1488      * @since 1.6
1489      */
setReadable(boolean readable, boolean ownerOnly)1490     public boolean setReadable(boolean readable, boolean ownerOnly) {
1491         SecurityManager security = System.getSecurityManager();
1492         if (security != null) {
1493             security.checkWrite(path);
1494         }
1495         if (isInvalid()) {
1496             return false;
1497         }
1498         return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);
1499     }
1500 
1501     /**
1502      * A convenience method to set the owner's read permission for this abstract
1503      * pathname.
1504      *
1505      * <p>An invocation of this method of the form <tt>file.setReadable(arg)</tt>
1506      * behaves in exactly the same way as the invocation
1507      *
1508      * <pre>
1509      *     file.setReadable(arg, true) </pre>
1510      *
1511      * @param  readable
1512      *          If <code>true</code>, sets the access permission to allow read
1513      *          operations; if <code>false</code> to disallow read operations
1514      *
1515      * @return  <code>true</code> if and only if the operation succeeded.  The
1516      *          operation will fail if the user does not have permission to
1517      *          change the access permissions of this abstract pathname.  If
1518      *          <code>readable</code> is <code>false</code> and the underlying
1519      *          file system does not implement a read permission, then the
1520      *          operation will fail.
1521      *
1522      * @throws  SecurityException
1523      *          If a security manager exists and its <code>{@link
1524      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1525      *          method denies write access to the file
1526      *
1527      * @since 1.6
1528      */
setReadable(boolean readable)1529     public boolean setReadable(boolean readable) {
1530         return setReadable(readable, true);
1531     }
1532 
1533     /**
1534      * Sets the owner's or everybody's execute permission for this abstract
1535      * pathname.
1536      *
1537      * @param   executable
1538      *          If <code>true</code>, sets the access permission to allow execute
1539      *          operations; if <code>false</code> to disallow execute operations
1540      *
1541      * @param   ownerOnly
1542      *          If <code>true</code>, the execute permission applies only to the
1543      *          owner's execute permission; otherwise, it applies to everybody.
1544      *          If the underlying file system can not distinguish the owner's
1545      *          execute permission from that of others, then the permission will
1546      *          apply to everybody, regardless of this value.
1547      *
1548      * @return  <code>true</code> if and only if the operation succeeded.  The
1549      *          operation will fail if the user does not have permission to
1550      *          change the access permissions of this abstract pathname.  If
1551      *          <code>executable</code> is <code>false</code> and the underlying
1552      *          file system does not implement an execute permission, then the
1553      *          operation will fail.
1554      *
1555      * @throws  SecurityException
1556      *          If a security manager exists and its <code>{@link
1557      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1558      *          method denies write access to the file
1559      *
1560      * @since 1.6
1561      */
setExecutable(boolean executable, boolean ownerOnly)1562     public boolean setExecutable(boolean executable, boolean ownerOnly) {
1563         SecurityManager security = System.getSecurityManager();
1564         if (security != null) {
1565             security.checkWrite(path);
1566         }
1567         if (isInvalid()) {
1568             return false;
1569         }
1570         return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);
1571     }
1572 
1573     /**
1574      * A convenience method to set the owner's execute permission for this abstract
1575      * pathname.
1576      *
1577      * <p>An invocation of this method of the form <tt>file.setExcutable(arg)</tt>
1578      * behaves in exactly the same way as the invocation
1579      *
1580      * <pre>
1581      *     file.setExecutable(arg, true) </pre>
1582      *
1583      * @param   executable
1584      *          If <code>true</code>, sets the access permission to allow execute
1585      *          operations; if <code>false</code> to disallow execute operations
1586      *
1587      * @return   <code>true</code> if and only if the operation succeeded.  The
1588      *           operation will fail if the user does not have permission to
1589      *           change the access permissions of this abstract pathname.  If
1590      *           <code>executable</code> is <code>false</code> and the underlying
1591      *           file system does not implement an excute permission, then the
1592      *           operation will fail.
1593      *
1594      * @throws  SecurityException
1595      *          If a security manager exists and its <code>{@link
1596      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1597      *          method denies write access to the file
1598      *
1599      * @since 1.6
1600      */
setExecutable(boolean executable)1601     public boolean setExecutable(boolean executable) {
1602         return setExecutable(executable, true);
1603     }
1604 
1605     /**
1606      * Tests whether the application can execute the file denoted by this
1607      * abstract pathname.
1608      *
1609      * @return  <code>true</code> if and only if the abstract pathname exists
1610      *          <em>and</em> the application is allowed to execute the file
1611      *
1612      * @throws  SecurityException
1613      *          If a security manager exists and its <code>{@link
1614      *          java.lang.SecurityManager#checkExec(java.lang.String)}</code>
1615      *          method denies execute access to the file
1616      *
1617      * @since 1.6
1618      */
canExecute()1619     public boolean canExecute() {
1620         SecurityManager security = System.getSecurityManager();
1621         if (security != null) {
1622             security.checkExec(path);
1623         }
1624         if (isInvalid()) {
1625             return false;
1626         }
1627         return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE);
1628     }
1629 
1630 
1631     /* -- Filesystem interface -- */
1632 
1633 
1634     /**
1635      * Returns the file system roots. On Android and other Unix systems, there is
1636      * a single root, {@code /}.
1637      */
listRoots()1638     public static File[] listRoots() {
1639         return fs.listRoots();
1640     }
1641 
1642 
1643     /* -- Disk usage -- */
1644 
1645     /**
1646      * Returns the size of the partition <a href="#partName">named</a> by this
1647      * abstract pathname.
1648      *
1649      * @return  The size, in bytes, of the partition or <tt>0L</tt> if this
1650      *          abstract pathname does not name a partition
1651      *
1652      * @throws  SecurityException
1653      *          If a security manager has been installed and it denies
1654      *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
1655      *          or its {@link SecurityManager#checkRead(String)} method denies
1656      *          read access to the file named by this abstract pathname
1657      *
1658      * @since  1.6
1659      */
getTotalSpace()1660     public long getTotalSpace() {
1661         SecurityManager sm = System.getSecurityManager();
1662         if (sm != null) {
1663             sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1664             sm.checkRead(path);
1665         }
1666         if (isInvalid()) {
1667             return 0L;
1668         }
1669         return fs.getSpace(this, FileSystem.SPACE_TOTAL);
1670     }
1671 
1672     /**
1673      * Returns the number of unallocated bytes in the partition <a
1674      * href="#partName">named</a> by this abstract path name.
1675      *
1676      * <p> The returned number of unallocated bytes is a hint, but not
1677      * a guarantee, that it is possible to use most or any of these
1678      * bytes.  The number of unallocated bytes is most likely to be
1679      * accurate immediately after this call.  It is likely to be made
1680      * inaccurate by any external I/O operations including those made
1681      * on the system outside of this virtual machine.  This method
1682      * makes no guarantee that write operations to this file system
1683      * will succeed.
1684      *
1685      * @return  The number of unallocated bytes on the partition or <tt>0L</tt>
1686      *          if the abstract pathname does not name a partition.  This
1687      *          value will be less than or equal to the total file system size
1688      *          returned by {@link #getTotalSpace}.
1689      *
1690      * @throws  SecurityException
1691      *          If a security manager has been installed and it denies
1692      *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
1693      *          or its {@link SecurityManager#checkRead(String)} method denies
1694      *          read access to the file named by this abstract pathname
1695      *
1696      * @since  1.6
1697      */
getFreeSpace()1698     public long getFreeSpace() {
1699         SecurityManager sm = System.getSecurityManager();
1700         if (sm != null) {
1701             sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1702             sm.checkRead(path);
1703         }
1704         if (isInvalid()) {
1705             return 0L;
1706         }
1707         return fs.getSpace(this, FileSystem.SPACE_FREE);
1708     }
1709 
1710     /**
1711      * Returns the number of bytes available to this virtual machine on the
1712      * partition <a href="#partName">named</a> by this abstract pathname.  When
1713      * possible, this method checks for write permissions and other operating
1714      * system restrictions and will therefore usually provide a more accurate
1715      * estimate of how much new data can actually be written than {@link
1716      * #getFreeSpace}.
1717      *
1718      * <p> The returned number of available bytes is a hint, but not a
1719      * guarantee, that it is possible to use most or any of these bytes.  The
1720      * number of unallocated bytes is most likely to be accurate immediately
1721      * after this call.  It is likely to be made inaccurate by any external
1722      * I/O operations including those made on the system outside of this
1723      * virtual machine.  This method makes no guarantee that write operations
1724      * to this file system will succeed.
1725      *
1726      * <p> On Android (and other Unix-based systems), this method returns the number of free bytes
1727      * available to non-root users, regardless of whether you're actually running as root,
1728      * and regardless of any quota or other restrictions that might apply to the user.
1729      * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.)
1730      *
1731      * @return  The number of available bytes on the partition or <tt>0L</tt>
1732      *          if the abstract pathname does not name a partition.  On
1733      *          systems where this information is not available, this method
1734      *          will be equivalent to a call to {@link #getFreeSpace}.
1735      *
1736      * @throws  SecurityException
1737      *          If a security manager has been installed and it denies
1738      *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
1739      *          or its {@link SecurityManager#checkRead(String)} method denies
1740      *          read access to the file named by this abstract pathname
1741      *
1742      * @since  1.6
1743      */
getUsableSpace()1744     public long getUsableSpace() {
1745         SecurityManager sm = System.getSecurityManager();
1746         if (sm != null) {
1747             sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1748             sm.checkRead(path);
1749         }
1750         if (isInvalid()) {
1751             return 0L;
1752         }
1753         return fs.getSpace(this, FileSystem.SPACE_USABLE);
1754     }
1755 
1756     /* -- Temporary files -- */
1757 
1758     // file name generation
generateTempFile(String prefix, String suffix, File dir)1759     private static File generateTempFile(String prefix, String suffix, File dir)
1760             throws IOException
1761     {
1762         // Android-changed: Use Math.randomIntInternal. This (pseudo) random number
1763         // is initialized post-fork
1764         int n = Math.randomIntInternal();
1765         if (n == Integer.MIN_VALUE) {
1766             n = 0;      // corner case
1767         } else {
1768             n = Math.abs(n);
1769         }
1770         String name = prefix + Integer.toString(n) + suffix;
1771         File f = new File(dir, name);
1772         if (!name.equals(f.getName()))
1773             throw new IOException("Unable to create temporary file");
1774         return f;
1775     }
1776 
1777     /**
1778      * <p> Creates a new empty file in the specified directory, using the
1779      * given prefix and suffix strings to generate its name.  If this method
1780      * returns successfully then it is guaranteed that:
1781      *
1782      * <ol>
1783      * <li> The file denoted by the returned abstract pathname did not exist
1784      *      before this method was invoked, and
1785      * <li> Neither this method nor any of its variants will return the same
1786      *      abstract pathname again in the current invocation of the virtual
1787      *      machine.
1788      * </ol>
1789      *
1790      * This method provides only part of a temporary-file facility.  To arrange
1791      * for a file created by this method to be deleted automatically, use the
1792      * <code>{@link #deleteOnExit}</code> method.
1793      *
1794      * <p> The <code>prefix</code> argument must be at least three characters
1795      * long.  It is recommended that the prefix be a short, meaningful string
1796      * such as <code>"hjb"</code> or <code>"mail"</code>.  The
1797      * <code>suffix</code> argument may be <code>null</code>, in which case the
1798      * suffix <code>".tmp"</code> will be used.
1799      *
1800      * <p> To create the new file, the prefix and the suffix may first be
1801      * adjusted to fit the limitations of the underlying platform.  If the
1802      * prefix is too long then it will be truncated, but its first three
1803      * characters will always be preserved.  If the suffix is too long then it
1804      * too will be truncated, but if it begins with a period character
1805      * (<code>'.'</code>) then the period and the first three characters
1806      * following it will always be preserved.  Once these adjustments have been
1807      * made the name of the new file will be generated by concatenating the
1808      * prefix, five or more internally-generated characters, and the suffix.
1809      *
1810      * <p> If the <code>directory</code> argument is <code>null</code> then the
1811      * system-dependent default temporary-file directory will be used.  The
1812      * default temporary-file directory is specified by the system property
1813      * <code>java.io.tmpdir</code>.  On UNIX systems the default value of this
1814      * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on
1815      * Microsoft Windows systems it is typically <code>"C:\\WINNT\\TEMP"</code>.  A different
1816      * value may be given to this system property when the Java virtual machine
1817      * is invoked, but programmatic changes to this property are not guaranteed
1818      * to have any effect upon the temporary directory used by this method.
1819      *
1820      * @param  prefix     The prefix string to be used in generating the file's
1821      *                    name; must be at least three characters long
1822      *
1823      * @param  suffix     The suffix string to be used in generating the file's
1824      *                    name; may be <code>null</code>, in which case the
1825      *                    suffix <code>".tmp"</code> will be used
1826      *
1827      * @param  directory  The directory in which the file is to be created, or
1828      *                    <code>null</code> if the default temporary-file
1829      *                    directory is to be used
1830      *
1831      * @return  An abstract pathname denoting a newly-created empty file
1832      *
1833      * @throws  IllegalArgumentException
1834      *          If the <code>prefix</code> argument contains fewer than three
1835      *          characters
1836      *
1837      * @throws  IOException  If a file could not be created
1838      *
1839      * @throws  SecurityException
1840      *          If a security manager exists and its <code>{@link
1841      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1842      *          method does not allow a file to be created
1843      *
1844      * @since 1.2
1845      */
createTempFile(String prefix, String suffix, File directory)1846     public static File createTempFile(String prefix, String suffix,
1847                                       File directory)
1848         throws IOException
1849     {
1850         if (prefix.length() < 3)
1851             throw new IllegalArgumentException("Prefix string too short");
1852         if (suffix == null)
1853             suffix = ".tmp";
1854 
1855         File tmpdir = (directory != null) ? directory
1856                                           : new File(System.getProperty("java.io.tmpdir", "."));
1857         File f;
1858         try {
1859             do {
1860                 f = generateTempFile(prefix, suffix, tmpdir);
1861             } while (f.exists());
1862             if (!f.createNewFile())
1863                 throw new IOException("Unable to create temporary file");
1864         } catch (SecurityException se) {
1865             // don't reveal temporary directory location
1866             if (directory == null)
1867                 throw new SecurityException("Unable to create temporary file");
1868             throw se;
1869         }
1870         return f;
1871     }
1872 
1873     /**
1874      * Creates an empty file in the default temporary-file directory, using
1875      * the given prefix and suffix to generate its name. Invoking this method
1876      * is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
1877      * java.lang.String, java.io.File)
1878      * createTempFile(prefix,&nbsp;suffix,&nbsp;null)}</code>.
1879      *
1880      * @param  prefix     The prefix string to be used in generating the file's
1881      *                    name; must be at least three characters long
1882      *
1883      * @param  suffix     The suffix string to be used in generating the file's
1884      *                    name; may be <code>null</code>, in which case the
1885      *                    suffix <code>".tmp"</code> will be used
1886      *
1887      * @return  An abstract pathname denoting a newly-created empty file
1888      *
1889      * @throws  IllegalArgumentException
1890      *          If the <code>prefix</code> argument contains fewer than three
1891      *          characters
1892      *
1893      * @throws  IOException  If a file could not be created
1894      *
1895      * @throws  SecurityException
1896      *          If a security manager exists and its <code>{@link
1897      *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1898      *          method does not allow a file to be created
1899      *
1900      * @since 1.2
1901      */
createTempFile(String prefix, String suffix)1902     public static File createTempFile(String prefix, String suffix)
1903         throws IOException
1904     {
1905         return createTempFile(prefix, suffix, null);
1906     }
1907 
1908     /* -- Basic infrastructure -- */
1909 
1910     /**
1911      * Compares two abstract pathnames lexicographically.  The ordering
1912      * defined by this method depends upon the underlying system.  On UNIX
1913      * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
1914      * systems it is not.
1915      *
1916      * @param   pathname  The abstract pathname to be compared to this abstract
1917      *                    pathname
1918      *
1919      * @return  Zero if the argument is equal to this abstract pathname, a
1920      *          value less than zero if this abstract pathname is
1921      *          lexicographically less than the argument, or a value greater
1922      *          than zero if this abstract pathname is lexicographically
1923      *          greater than the argument
1924      *
1925      * @since   1.2
1926      */
compareTo(File pathname)1927     public int compareTo(File pathname) {
1928         return fs.compare(this, pathname);
1929     }
1930 
1931     /**
1932      * Tests this abstract pathname for equality with the given object.
1933      * Returns <code>true</code> if and only if the argument is not
1934      * <code>null</code> and is an abstract pathname that denotes the same file
1935      * or directory as this abstract pathname.  Whether or not two abstract
1936      * pathnames are equal depends upon the underlying system.  On UNIX
1937      * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
1938      * systems it is not.
1939      *
1940      * @param   obj   The object to be compared with this abstract pathname
1941      *
1942      * @return  <code>true</code> if and only if the objects are the same;
1943      *          <code>false</code> otherwise
1944      */
equals(Object obj)1945     public boolean equals(Object obj) {
1946         if ((obj != null) && (obj instanceof File)) {
1947             return compareTo((File)obj) == 0;
1948         }
1949         return false;
1950     }
1951 
1952     /**
1953      * Computes a hash code for this abstract pathname.  Because equality of
1954      * abstract pathnames is inherently system-dependent, so is the computation
1955      * of their hash codes.  On UNIX systems, the hash code of an abstract
1956      * pathname is equal to the exclusive <em>or</em> of the hash code
1957      * of its pathname string and the decimal value
1958      * <code>1234321</code>.  On Microsoft Windows systems, the hash
1959      * code is equal to the exclusive <em>or</em> of the hash code of
1960      * its pathname string converted to lower case and the decimal
1961      * value <code>1234321</code>.  Locale is not taken into account on
1962      * lowercasing the pathname string.
1963      *
1964      * @return  A hash code for this abstract pathname
1965      */
hashCode()1966     public int hashCode() {
1967         return fs.hashCode(this);
1968     }
1969 
1970     /**
1971      * Returns the pathname string of this abstract pathname.  This is just the
1972      * string returned by the <code>{@link #getPath}</code> method.
1973      *
1974      * @return  The string form of this abstract pathname
1975      */
toString()1976     public String toString() {
1977         return getPath();
1978     }
1979 
1980     /**
1981      * WriteObject is called to save this filename.
1982      * The separator character is saved also so it can be replaced
1983      * in case the path is reconstituted on a different host type.
1984      * <p>
1985      * @serialData  Default fields followed by separator character.
1986      */
writeObject(java.io.ObjectOutputStream s)1987     private synchronized void writeObject(java.io.ObjectOutputStream s)
1988         throws IOException
1989     {
1990         s.defaultWriteObject();
1991         s.writeChar(this.separatorChar); // Add the separator character
1992     }
1993 
1994     /**
1995      * readObject is called to restore this filename.
1996      * The original separator character is read.  If it is different
1997      * than the separator character on this system, then the old separator
1998      * is replaced by the local separator.
1999      */
readObject(java.io.ObjectInputStream s)2000     private synchronized void readObject(java.io.ObjectInputStream s)
2001          throws IOException, ClassNotFoundException
2002     {
2003         ObjectInputStream.GetField fields = s.readFields();
2004         String pathField = (String)fields.get("path", null);
2005         char sep = s.readChar(); // read the previous separator char
2006         if (sep != separatorChar)
2007             pathField = pathField.replace(sep, separatorChar);
2008         this.path = fs.normalize(pathField);
2009         this.prefixLength = fs.prefixLength(this.path);
2010     }
2011 
2012     /** use serialVersionUID from JDK 1.0.2 for interoperability */
2013     private static final long serialVersionUID = 301077366599181567L;
2014 }
2015