• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package java.io;
19 
20 import java.net.URI;
21 import java.net.URISyntaxException;
22 import java.net.URL;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Random;
26 import libcore.io.ErrnoException;
27 import libcore.io.IoUtils;
28 import libcore.io.Libcore;
29 import libcore.io.StructStat;
30 import libcore.io.StructStatFs;
31 import org.apache.harmony.luni.util.DeleteOnExit;
32 import static libcore.io.OsConstants.*;
33 
34 /**
35  * An "abstract" representation of a file system entity identified by a
36  * pathname. The pathname may be absolute (relative to the root directory
37  * of the file system) or relative to the current directory in which the program
38  * is running.
39  *
40  * <p>The actual file referenced by a {@code File} may or may not exist. It may
41  * also, despite the name {@code File}, be a directory or other non-regular
42  * file.
43  *
44  * <p>This class provides limited functionality for getting/setting file
45  * permissions, file type, and last modified time.
46  *
47  * <p>On Android strings are converted to UTF-8 byte sequences when sending filenames to
48  * the operating system, and byte sequences returned by the operating system (from the
49  * various {@code list} methods) are converted to strings by decoding them as UTF-8
50  * byte sequences.
51  *
52  * @see java.io.Serializable
53  * @see java.lang.Comparable
54  */
55 public class File implements Serializable, Comparable<File> {
56 
57     private static final long serialVersionUID = 301077366599181567L;
58 
59     /**
60      * Reusing a Random makes temporary filenames slightly harder to predict.
61      * (Random is thread-safe.)
62      */
63     private static final Random tempFileRandom = new Random();
64 
65     /**
66      * The system-dependent character used to separate components in filenames ('/').
67      * Use of this (rather than hard-coding '/') helps portability to other operating systems.
68      *
69      * <p>This field is initialized from the system property "file.separator".
70      * Later changes to that property will have no effect on this field or this class.
71      */
72     public static final char separatorChar;
73 
74     /**
75      * The system-dependent string used to separate components in filenames ('/').
76      * See {@link #separatorChar}.
77      */
78     public static final String separator;
79 
80     /**
81      * The system-dependent character used to separate components in search paths (':').
82      * This is used to split such things as the PATH environment variable and classpath
83      * system properties into lists of directories to be searched.
84      *
85      * <p>This field is initialized from the system property "path.separator".
86      * Later changes to that property will have no effect on this field or this class.
87      */
88     public static final char pathSeparatorChar;
89 
90     /**
91      * The system-dependent string used to separate components in search paths (":").
92      * See {@link #pathSeparatorChar}.
93      */
94     public static final String pathSeparator;
95 
96     /**
97      * The path we return from getPath. This is almost the path we were
98      * given, but without duplicate adjacent slashes and without trailing
99      * slashes (except for the special case of the root directory). This
100      * path may be the empty string.
101      *
102      * This can't be final because we override readObject.
103      */
104     private String path;
105 
106     static {
107         separatorChar = System.getProperty("file.separator", "/").charAt(0);
108         pathSeparatorChar = System.getProperty("path.separator", ":").charAt(0);
109         separator = String.valueOf(separatorChar);
110         pathSeparator = String.valueOf(pathSeparatorChar);
111     }
112 
113     /**
114      * Constructs a new file using the specified directory and name.
115      *
116      * @param dir
117      *            the directory where the file is stored.
118      * @param name
119      *            the file's name.
120      * @throws NullPointerException
121      *             if {@code name} is {@code null}.
122      */
File(File dir, String name)123     public File(File dir, String name) {
124         this(dir == null ? null : dir.getPath(), name);
125     }
126 
127     /**
128      * Constructs a new file using the specified path.
129      *
130      * @param path
131      *            the path to be used for the file.
132      */
File(String path)133     public File(String path) {
134         this.path = fixSlashes(path);
135     }
136 
137     /**
138      * Constructs a new File using the specified directory path and file name,
139      * placing a path separator between the two.
140      *
141      * @param dirPath
142      *            the path to the directory where the file is stored.
143      * @param name
144      *            the file's name.
145      * @throws NullPointerException
146      *             if {@code name == null}.
147      */
File(String dirPath, String name)148     public File(String dirPath, String name) {
149         if (name == null) {
150             throw new NullPointerException();
151         }
152         if (dirPath == null || dirPath.isEmpty()) {
153             this.path = fixSlashes(name);
154         } else if (name.isEmpty()) {
155             this.path = fixSlashes(dirPath);
156         } else {
157             this.path = fixSlashes(join(dirPath, name));
158         }
159     }
160 
161     /**
162      * Constructs a new File using the path of the specified URI. {@code uri}
163      * needs to be an absolute and hierarchical Unified Resource Identifier with
164      * file scheme and non-empty path component, but with undefined authority,
165      * query or fragment components.
166      *
167      * @param uri
168      *            the Unified Resource Identifier that is used to construct this
169      *            file.
170      * @throws IllegalArgumentException
171      *             if {@code uri} does not comply with the conditions above.
172      * @see #toURI
173      * @see java.net.URI
174      */
File(URI uri)175     public File(URI uri) {
176         // check pre-conditions
177         checkURI(uri);
178         this.path = fixSlashes(uri.getPath());
179     }
180 
181     // Removes duplicate adjacent slashes and any trailing slash.
fixSlashes(String origPath)182     private static String fixSlashes(String origPath) {
183         // Remove duplicate adjacent slashes.
184         boolean lastWasSlash = false;
185         char[] newPath = origPath.toCharArray();
186         int length = newPath.length;
187         int newLength = 0;
188         for (int i = 0; i < length; ++i) {
189             char ch = newPath[i];
190             if (ch == '/') {
191                 if (!lastWasSlash) {
192                     newPath[newLength++] = separatorChar;
193                     lastWasSlash = true;
194                 }
195             } else {
196                 newPath[newLength++] = ch;
197                 lastWasSlash = false;
198             }
199         }
200         // Remove any trailing slash (unless this is the root of the file system).
201         if (lastWasSlash && newLength > 1) {
202             newLength--;
203         }
204         // Reuse the original string if possible.
205         return (newLength != length) ? new String(newPath, 0, newLength) : origPath;
206     }
207 
208     // Joins two path components, adding a separator only if necessary.
join(String prefix, String suffix)209     private static String join(String prefix, String suffix) {
210         int prefixLength = prefix.length();
211         boolean haveSlash = (prefixLength > 0 && prefix.charAt(prefixLength - 1) == separatorChar);
212         if (!haveSlash) {
213             haveSlash = (suffix.length() > 0 && suffix.charAt(0) == separatorChar);
214         }
215         return haveSlash ? (prefix + suffix) : (prefix + separatorChar + suffix);
216     }
217 
checkURI(URI uri)218     private static void checkURI(URI uri) {
219         if (!uri.isAbsolute()) {
220             throw new IllegalArgumentException("URI is not absolute: " + uri);
221         } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) {
222             throw new IllegalArgumentException("URI is not hierarchical: " + uri);
223         }
224         if (!"file".equals(uri.getScheme())) {
225             throw new IllegalArgumentException("Expected file scheme in URI: " + uri);
226         }
227         String rawPath = uri.getRawPath();
228         if (rawPath == null || rawPath.isEmpty()) {
229             throw new IllegalArgumentException("Expected non-empty path in URI: " + uri);
230         }
231         if (uri.getRawAuthority() != null) {
232             throw new IllegalArgumentException("Found authority in URI: " + uri);
233         }
234         if (uri.getRawQuery() != null) {
235             throw new IllegalArgumentException("Found query in URI: " + uri);
236         }
237         if (uri.getRawFragment() != null) {
238             throw new IllegalArgumentException("Found fragment in URI: " + uri);
239         }
240     }
241 
242     /**
243      * Returns the file system roots. On Android and other Unix systems, there is
244      * a single root, {@code /}.
245      */
listRoots()246     public static File[] listRoots() {
247         return new File[] { new File("/") };
248     }
249 
250     /**
251      * Tests whether or not this process is allowed to execute this file.
252      * Note that this is a best-effort result; the only way to be certain is
253      * to actually attempt the operation.
254      *
255      * @return {@code true} if this file can be executed, {@code false} otherwise.
256      * @since 1.6
257      */
canExecute()258     public boolean canExecute() {
259         return doAccess(X_OK);
260     }
261 
262     /**
263      * Indicates whether the current context is allowed to read from this file.
264      *
265      * @return {@code true} if this file can be read, {@code false} otherwise.
266      */
canRead()267     public boolean canRead() {
268         return doAccess(R_OK);
269     }
270 
271     /**
272      * Indicates whether the current context is allowed to write to this file.
273      *
274      * @return {@code true} if this file can be written, {@code false}
275      *         otherwise.
276      */
canWrite()277     public boolean canWrite() {
278         return doAccess(W_OK);
279     }
280 
doAccess(int mode)281     private boolean doAccess(int mode) {
282         try {
283             return Libcore.os.access(path, mode);
284         } catch (ErrnoException errnoException) {
285             return false;
286         }
287     }
288 
289     /**
290      * Returns the relative sort ordering of the paths for this file and the
291      * file {@code another}. The ordering is platform dependent.
292      *
293      * @param another
294      *            a file to compare this file to
295      * @return an int determined by comparing the two paths. Possible values are
296      *         described in the Comparable interface.
297      * @see Comparable
298      */
compareTo(File another)299     public int compareTo(File another) {
300         return this.getPath().compareTo(another.getPath());
301     }
302 
303     /**
304      * Deletes this file. Directories must be empty before they will be deleted.
305      *
306      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
307      * Callers must check the return value.
308      *
309      * @return {@code true} if this file was deleted, {@code false} otherwise.
310      */
delete()311     public boolean delete() {
312         try {
313             Libcore.os.remove(path);
314             return true;
315         } catch (ErrnoException errnoException) {
316             return false;
317         }
318     }
319 
320     /**
321      * Schedules this file to be automatically deleted when the VM terminates normally.
322      *
323      * <p><i>Note that on Android, the application lifecycle does not include VM termination,
324      * so calling this method will not ensure that files are deleted</i>. Instead, you should
325      * use the most appropriate out of:
326      * <ul>
327      * <li>Use a {@code finally} clause to manually invoke {@link #delete}.
328      * <li>Maintain your own set of files to delete, and process it at an appropriate point
329      * in your application's lifecycle.
330      * <li>Use the Unix trick of deleting the file as soon as all readers and writers have
331      * opened it. No new readers/writers will be able to access the file, but all existing
332      * ones will still have access until the last one closes the file.
333      * </ul>
334      */
deleteOnExit()335     public void deleteOnExit() {
336         DeleteOnExit.getInstance().addFile(getAbsolutePath());
337     }
338 
339     /**
340      * Compares {@code obj} to this file and returns {@code true} if they
341      * represent the <em>same</em> object using a path specific comparison.
342      *
343      * @param obj
344      *            the object to compare this file with.
345      * @return {@code true} if {@code obj} is the same as this object,
346      *         {@code false} otherwise.
347      */
348     @Override
equals(Object obj)349     public boolean equals(Object obj) {
350         if (!(obj instanceof File)) {
351             return false;
352         }
353         return path.equals(((File) obj).getPath());
354     }
355 
356     /**
357      * Returns a boolean indicating whether this file can be found on the
358      * underlying file system.
359      *
360      * @return {@code true} if this file exists, {@code false} otherwise.
361      */
exists()362     public boolean exists() {
363         return doAccess(F_OK);
364     }
365 
366     /**
367      * Returns the absolute path of this file. An absolute path is a path that starts at a root
368      * of the file system. On Android, there is only one root: {@code /}.
369      *
370      * <p>A common use for absolute paths is when passing paths to a {@code Process} as
371      * command-line arguments, to remove the requirement implied by relative paths, that the
372      * child must have the same working directory as its parent.
373      */
getAbsolutePath()374     public String getAbsolutePath() {
375         if (isAbsolute()) {
376             return path;
377         }
378         String userDir = System.getProperty("user.dir");
379         return path.isEmpty() ? userDir : join(userDir, path);
380     }
381 
382     /**
383      * Returns a new file constructed using the absolute path of this file.
384      * Equivalent to {@code new File(this.getAbsolutePath())}.
385      */
getAbsoluteFile()386     public File getAbsoluteFile() {
387         return new File(getAbsolutePath());
388     }
389 
390     /**
391      * Returns the canonical path of this file.
392      * An <i>absolute</i> path is one that begins at the root of the file system.
393      * A <i>canonical</i> path is an absolute path with symbolic links
394      * and references to "." or ".." resolved. If a path element does not exist (or
395      * is not searchable), there is a conflict between interpreting canonicalization
396      * as a textual operation (where "a/../b" is "b" even if "a" does not exist) .
397      *
398      * <p>Most callers should use {@link #getAbsolutePath} instead. A canonical path is
399      * significantly more expensive to compute, and not generally useful. The primary
400      * use for canonical paths is determining whether two paths point to the same file by
401      * comparing the canonicalized paths.
402      *
403      * <p>It can be actively harmful to use a canonical path, specifically because
404      * canonicalization removes symbolic links. It's wise to assume that a symbolic link
405      * is present for a reason, and that that reason is because the link may need to change.
406      * Canonicalization removes this layer of indirection. Good code should generally avoid
407      * caching canonical paths.
408      *
409      * @return the canonical path of this file.
410      * @throws IOException
411      *             if an I/O error occurs.
412      */
getCanonicalPath()413     public String getCanonicalPath() throws IOException {
414         return realpath(getAbsolutePath());
415     }
416 
417     /**
418      * TODO: move this stuff to libcore.os.
419      * @hide
420      */
realpath(String path)421     private static native String realpath(String path);
readlink(String path)422     private static native String readlink(String path);
423 
424     /**
425      * Returns a new file created using the canonical path of this file.
426      * Equivalent to {@code new File(this.getCanonicalPath())}.
427      *
428      * @return the new file constructed from this file's canonical path.
429      * @throws IOException
430      *             if an I/O error occurs.
431      */
getCanonicalFile()432     public File getCanonicalFile() throws IOException {
433         return new File(getCanonicalPath());
434     }
435 
436     /**
437      * Returns the name of the file or directory represented by this file.
438      *
439      * @return this file's name or an empty string if there is no name part in
440      *         the file's path.
441      */
getName()442     public String getName() {
443         int separatorIndex = path.lastIndexOf(separator);
444         return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
445     }
446 
447     /**
448      * Returns the pathname of the parent of this file. This is the path up to
449      * but not including the last name. {@code null} is returned if there is no
450      * parent.
451      *
452      * @return this file's parent pathname or {@code null}.
453      */
getParent()454     public String getParent() {
455         int length = path.length(), firstInPath = 0;
456         if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') {
457             firstInPath = 2;
458         }
459         int index = path.lastIndexOf(separatorChar);
460         if (index == -1 && firstInPath > 0) {
461             index = 2;
462         }
463         if (index == -1 || path.charAt(length - 1) == separatorChar) {
464             return null;
465         }
466         if (path.indexOf(separatorChar) == index
467                 && path.charAt(firstInPath) == separatorChar) {
468             return path.substring(0, index + 1);
469         }
470         return path.substring(0, index);
471     }
472 
473     /**
474      * Returns a new file made from the pathname of the parent of this file.
475      * This is the path up to but not including the last name. {@code null} is
476      * returned when there is no parent.
477      *
478      * @return a new file representing this file's parent or {@code null}.
479      */
getParentFile()480     public File getParentFile() {
481         String tempParent = getParent();
482         if (tempParent == null) {
483             return null;
484         }
485         return new File(tempParent);
486     }
487 
488     /**
489      * Returns the path of this file.
490      *
491      * @return this file's path.
492      */
getPath()493     public String getPath() {
494         return path;
495     }
496 
497     /**
498      * Returns an integer hash code for the receiver. Any two objects for which
499      * {@code equals} returns {@code true} must return the same hash code.
500      *
501      * @return this files's hash value.
502      * @see #equals
503      */
504     @Override
hashCode()505     public int hashCode() {
506         return getPath().hashCode() ^ 1234321;
507     }
508 
509     /**
510      * Indicates if this file's pathname is absolute. Whether a pathname is
511      * absolute is platform specific. On Android, absolute paths start with
512      * the character '/'.
513      *
514      * @return {@code true} if this file's pathname is absolute, {@code false}
515      *         otherwise.
516      * @see #getPath
517      */
isAbsolute()518     public boolean isAbsolute() {
519         return path.length() > 0 && path.charAt(0) == separatorChar;
520     }
521 
522     /**
523      * Indicates if this file represents a <em>directory</em> on the
524      * underlying file system.
525      *
526      * @return {@code true} if this file is a directory, {@code false}
527      *         otherwise.
528      */
isDirectory()529     public boolean isDirectory() {
530         try {
531             return S_ISDIR(Libcore.os.stat(path).st_mode);
532         } catch (ErrnoException errnoException) {
533             // The RI returns false on error. (Even for errors like EACCES or ELOOP.)
534             return false;
535         }
536     }
537 
538     /**
539      * Indicates if this file represents a <em>file</em> on the underlying
540      * file system.
541      *
542      * @return {@code true} if this file is a file, {@code false} otherwise.
543      */
isFile()544     public boolean isFile() {
545         try {
546             return S_ISREG(Libcore.os.stat(path).st_mode);
547         } catch (ErrnoException errnoException) {
548             // The RI returns false on error. (Even for errors like EACCES or ELOOP.)
549             return false;
550         }
551     }
552 
553     /**
554      * Returns whether or not this file is a hidden file as defined by the
555      * operating system. The notion of "hidden" is system-dependent. For Unix
556      * systems a file is considered hidden if its name starts with a ".". For
557      * Windows systems there is an explicit flag in the file system for this
558      * purpose.
559      *
560      * @return {@code true} if the file is hidden, {@code false} otherwise.
561      */
isHidden()562     public boolean isHidden() {
563         if (path.isEmpty()) {
564             return false;
565         }
566         return getName().startsWith(".");
567     }
568 
569     /**
570      * Returns the time when this file was last modified, measured in
571      * milliseconds since January 1st, 1970, midnight.
572      * Returns 0 if the file does not exist.
573      *
574      * @return the time when this file was last modified.
575      */
lastModified()576     public long lastModified() {
577         try {
578             return Libcore.os.stat(path).st_mtime * 1000L;
579         } catch (ErrnoException errnoException) {
580             // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.)
581             return 0;
582         }
583     }
584 
585     /**
586      * Sets the time this file was last modified, measured in milliseconds since
587      * January 1st, 1970, midnight.
588      *
589      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
590      * Callers must check the return value.
591      *
592      * @param time
593      *            the last modification time for this file.
594      * @return {@code true} if the operation is successful, {@code false}
595      *         otherwise.
596      * @throws IllegalArgumentException
597      *             if {@code time < 0}.
598      */
setLastModified(long time)599     public boolean setLastModified(long time) {
600         if (time < 0) {
601             throw new IllegalArgumentException("time < 0");
602         }
603         return setLastModifiedImpl(path, time);
604     }
605 
setLastModifiedImpl(String path, long time)606     private static native boolean setLastModifiedImpl(String path, long time);
607 
608     /**
609      * Equivalent to setWritable(false, false).
610      *
611      * @see #setWritable(boolean, boolean)
612      */
setReadOnly()613     public boolean setReadOnly() {
614         return setWritable(false, false);
615     }
616 
617     /**
618      * Manipulates the execute permissions for the abstract path designated by
619      * this file.
620      *
621      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
622      * Callers must check the return value.
623      *
624      * @param executable
625      *            To allow execute permission if true, otherwise disallow
626      * @param ownerOnly
627      *            To manipulate execute permission only for owner if true,
628      *            otherwise for everyone. The manipulation will apply to
629      *            everyone regardless of this value if the underlying system
630      *            does not distinguish owner and other users.
631      * @return true if and only if the operation succeeded. If the user does not
632      *         have permission to change the access permissions of this abstract
633      *         pathname the operation will fail. If the underlying file system
634      *         does not support execute permission and the value of executable
635      *         is false, this operation will fail.
636      * @since 1.6
637      */
setExecutable(boolean executable, boolean ownerOnly)638     public boolean setExecutable(boolean executable, boolean ownerOnly) {
639         return doChmod(ownerOnly ? S_IXUSR : (S_IXUSR | S_IXGRP | S_IXOTH), executable);
640     }
641 
642     /**
643      * Equivalent to setExecutable(executable, true).
644      * @see #setExecutable(boolean, boolean)
645      * @since 1.6
646      */
setExecutable(boolean executable)647     public boolean setExecutable(boolean executable) {
648         return setExecutable(executable, true);
649     }
650 
651     /**
652      * Manipulates the read permissions for the abstract path designated by this
653      * file.
654      *
655      * @param readable
656      *            To allow read permission if true, otherwise disallow
657      * @param ownerOnly
658      *            To manipulate read permission only for owner if true,
659      *            otherwise for everyone. The manipulation will apply to
660      *            everyone regardless of this value if the underlying system
661      *            does not distinguish owner and other users.
662      * @return true if and only if the operation succeeded. If the user does not
663      *         have permission to change the access permissions of this abstract
664      *         pathname the operation will fail. If the underlying file system
665      *         does not support read permission and the value of readable is
666      *         false, this operation will fail.
667      * @since 1.6
668      */
setReadable(boolean readable, boolean ownerOnly)669     public boolean setReadable(boolean readable, boolean ownerOnly) {
670         return doChmod(ownerOnly ? S_IRUSR : (S_IRUSR | S_IRGRP | S_IROTH), readable);
671     }
672 
673     /**
674      * Equivalent to setReadable(readable, true).
675      * @see #setReadable(boolean, boolean)
676      * @since 1.6
677      */
setReadable(boolean readable)678     public boolean setReadable(boolean readable) {
679         return setReadable(readable, true);
680     }
681 
682     /**
683      * Manipulates the write permissions for the abstract path designated by this
684      * file.
685      *
686      * @param writable
687      *            To allow write permission if true, otherwise disallow
688      * @param ownerOnly
689      *            To manipulate write permission only for owner if true,
690      *            otherwise for everyone. The manipulation will apply to
691      *            everyone regardless of this value if the underlying system
692      *            does not distinguish owner and other users.
693      * @return true if and only if the operation succeeded. If the user does not
694      *         have permission to change the access permissions of this abstract
695      *         pathname the operation will fail.
696      * @since 1.6
697      */
setWritable(boolean writable, boolean ownerOnly)698     public boolean setWritable(boolean writable, boolean ownerOnly) {
699         return doChmod(ownerOnly ? S_IWUSR : (S_IWUSR | S_IWGRP | S_IWOTH), writable);
700     }
701 
702     /**
703      * Equivalent to setWritable(writable, true).
704      * @see #setWritable(boolean, boolean)
705      * @since 1.6
706      */
setWritable(boolean writable)707     public boolean setWritable(boolean writable) {
708         return setWritable(writable, true);
709     }
710 
doChmod(int mask, boolean set)711     private boolean doChmod(int mask, boolean set) {
712         try {
713             StructStat sb = Libcore.os.stat(path);
714             int newMode = set ? (sb.st_mode | mask) : (sb.st_mode & ~mask);
715             Libcore.os.chmod(path, newMode);
716             return true;
717         } catch (ErrnoException errnoException) {
718             return false;
719         }
720     }
721 
722     /**
723      * Returns the length of this file in bytes.
724      * Returns 0 if the file does not exist.
725      * The result for a directory is not defined.
726      *
727      * @return the number of bytes in this file.
728      */
length()729     public long length() {
730         try {
731             return Libcore.os.stat(path).st_size;
732         } catch (ErrnoException errnoException) {
733             // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.)
734             return 0;
735         }
736     }
737 
738     /**
739      * Returns an array of strings with the file names in the directory
740      * represented by this file. The result is {@code null} if this file is not
741      * a directory.
742      * <p>
743      * The entries {@code .} and {@code ..} representing the current and parent
744      * directory are not returned as part of the list.
745      *
746      * @return an array of strings with file names or {@code null}.
747      */
list()748     public String[] list() {
749         return listImpl(path);
750     }
751 
listImpl(String path)752     private static native String[] listImpl(String path);
753 
754     /**
755      * Gets a list of the files in the directory represented by this file. This
756      * list is then filtered through a FilenameFilter and the names of files
757      * with matching names are returned as an array of strings. Returns
758      * {@code null} if this file is not a directory. If {@code filter} is
759      * {@code null} then all filenames match.
760      * <p>
761      * The entries {@code .} and {@code ..} representing the current and parent
762      * directories are not returned as part of the list.
763      *
764      * @param filter
765      *            the filter to match names against, may be {@code null}.
766      * @return an array of files or {@code null}.
767      */
list(FilenameFilter filter)768     public String[] list(FilenameFilter filter) {
769         String[] filenames = list();
770         if (filter == null || filenames == null) {
771             return filenames;
772         }
773         List<String> result = new ArrayList<String>(filenames.length);
774         for (String filename : filenames) {
775             if (filter.accept(this, filename)) {
776                 result.add(filename);
777             }
778         }
779         return result.toArray(new String[result.size()]);
780     }
781 
782     /**
783      * Returns an array of files contained in the directory represented by this
784      * file. The result is {@code null} if this file is not a directory. The
785      * paths of the files in the array are absolute if the path of this file is
786      * absolute, they are relative otherwise.
787      *
788      * @return an array of files or {@code null}.
789      */
listFiles()790     public File[] listFiles() {
791         return filenamesToFiles(list());
792     }
793 
794     /**
795      * Gets a list of the files in the directory represented by this file. This
796      * list is then filtered through a FilenameFilter and files with matching
797      * names are returned as an array of files. Returns {@code null} if this
798      * file is not a directory. If {@code filter} is {@code null} then all
799      * filenames match.
800      * <p>
801      * The entries {@code .} and {@code ..} representing the current and parent
802      * directories are not returned as part of the list.
803      *
804      * @param filter
805      *            the filter to match names against, may be {@code null}.
806      * @return an array of files or {@code null}.
807      */
listFiles(FilenameFilter filter)808     public File[] listFiles(FilenameFilter filter) {
809         return filenamesToFiles(list(filter));
810     }
811 
812     /**
813      * Gets a list of the files in the directory represented by this file. This
814      * list is then filtered through a FileFilter and matching files are
815      * returned as an array of files. Returns {@code null} if this file is not a
816      * directory. If {@code filter} is {@code null} then all files match.
817      * <p>
818      * The entries {@code .} and {@code ..} representing the current and parent
819      * directories are not returned as part of the list.
820      *
821      * @param filter
822      *            the filter to match names against, may be {@code null}.
823      * @return an array of files or {@code null}.
824      */
listFiles(FileFilter filter)825     public File[] listFiles(FileFilter filter) {
826         File[] files = listFiles();
827         if (filter == null || files == null) {
828             return files;
829         }
830         List<File> result = new ArrayList<File>(files.length);
831         for (File file : files) {
832             if (filter.accept(file)) {
833                 result.add(file);
834             }
835         }
836         return result.toArray(new File[result.size()]);
837     }
838 
839     /**
840      * Converts a String[] containing filenames to a File[].
841      * Note that the filenames must not contain slashes.
842      * This method is to remove duplication in the implementation
843      * of File.list's overloads.
844      */
filenamesToFiles(String[] filenames)845     private File[] filenamesToFiles(String[] filenames) {
846         if (filenames == null) {
847             return null;
848         }
849         int count = filenames.length;
850         File[] result = new File[count];
851         for (int i = 0; i < count; ++i) {
852             result[i] = new File(this, filenames[i]);
853         }
854         return result;
855     }
856 
857     /**
858      * Creates the directory named by the trailing filename of this file. Does
859      * not create the complete path required to create this directory.
860      *
861      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
862      * Callers must check the return value.
863      *
864      * @return {@code true} if the directory has been created, {@code false}
865      *         otherwise.
866      * @see #mkdirs
867      */
mkdir()868     public boolean mkdir() {
869         try {
870             // On Android, we don't want default permissions to allow global access.
871             Libcore.os.mkdir(path, S_IRWXU);
872             return true;
873         } catch (ErrnoException errnoException) {
874             return false;
875         }
876     }
877 
878     /**
879      * Creates the directory named by the trailing filename of this file,
880      * including the complete directory path required to create this directory.
881      *
882      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
883      * Callers must check the return value.
884      *
885      * @return {@code true} if the necessary directories have been created,
886      *         {@code false} if the target directory already exists or one of
887      *         the directories can not be created.
888      * @see #mkdir
889      */
mkdirs()890     public boolean mkdirs() {
891         /* If the terminal directory already exists, answer false */
892         if (exists()) {
893             return false;
894         }
895 
896         /* If the receiver can be created, answer true */
897         if (mkdir()) {
898             return true;
899         }
900 
901         String parentDir = getParent();
902         /* If there is no parent and we were not created, answer false */
903         if (parentDir == null) {
904             return false;
905         }
906 
907         /* Otherwise, try to create a parent directory and then this directory */
908         return (new File(parentDir).mkdirs() && mkdir());
909     }
910 
911     /**
912      * Creates a new, empty file on the file system according to the path
913      * information stored in this file. This method returns true if it creates
914      * a file, false if the file already existed. Note that it returns false
915      * even if the file is not a file (because it's a directory, say).
916      *
917      * <p>This method is not generally useful. For creating temporary files,
918      * use {@link #createTempFile} instead. For reading/writing files, use {@link FileInputStream},
919      * {@link FileOutputStream}, or {@link RandomAccessFile}, all of which can create files.
920      *
921      * <p>Note that this method does <i>not</i> throw {@code IOException} if the file
922      * already exists, even if it's not a regular file. Callers should always check the
923      * return value, and may additionally want to call {@link #isFile}.
924      *
925      * @return true if the file has been created, false if it
926      *         already exists.
927      * @throws IOException if it's not possible to create the file.
928      */
createNewFile()929     public boolean createNewFile() throws IOException {
930         FileDescriptor fd = null;
931         try {
932             // On Android, we don't want default permissions to allow global access.
933             fd = Libcore.os.open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
934             return true;
935         } catch (ErrnoException errnoException) {
936             if (errnoException.errno == EEXIST) {
937                 // The file already exists.
938                 return false;
939             }
940             throw errnoException.rethrowAsIOException();
941         } finally {
942             IoUtils.close(fd); // TODO: should we suppress IOExceptions thrown here?
943         }
944     }
945 
946     /**
947      * Creates an empty temporary file using the given prefix and suffix as part
948      * of the file name. If {@code suffix} is null, {@code .tmp} is used. This
949      * method is a convenience method that calls
950      * {@link #createTempFile(String, String, File)} with the third argument
951      * being {@code null}.
952      *
953      * @param prefix
954      *            the prefix to the temp file name.
955      * @param suffix
956      *            the suffix to the temp file name.
957      * @return the temporary file.
958      * @throws IOException
959      *             if an error occurs when writing the file.
960      */
createTempFile(String prefix, String suffix)961     public static File createTempFile(String prefix, String suffix) throws IOException {
962         return createTempFile(prefix, suffix, null);
963     }
964 
965     /**
966      * Creates an empty temporary file in the given directory using the given
967      * prefix and suffix as part of the file name. If {@code suffix} is null, {@code .tmp} is used.
968      *
969      * <p>Note that this method does <i>not</i> call {@link #deleteOnExit}, but see the
970      * documentation for that method before you call it manually.
971      *
972      * @param prefix
973      *            the prefix to the temp file name.
974      * @param suffix
975      *            the suffix to the temp file name.
976      * @param directory
977      *            the location to which the temp file is to be written, or
978      *            {@code null} for the default location for temporary files,
979      *            which is taken from the "java.io.tmpdir" system property. It
980      *            may be necessary to set this property to an existing, writable
981      *            directory for this method to work properly.
982      * @return the temporary file.
983      * @throws IllegalArgumentException
984      *             if the length of {@code prefix} is less than 3.
985      * @throws IOException
986      *             if an error occurs when writing the file.
987      */
createTempFile(String prefix, String suffix, File directory)988     public static File createTempFile(String prefix, String suffix, File directory)
989             throws IOException {
990         // Force a prefix null check first
991         if (prefix.length() < 3) {
992             throw new IllegalArgumentException("prefix must be at least 3 characters");
993         }
994         if (suffix == null) {
995             suffix = ".tmp";
996         }
997         File tmpDirFile = directory;
998         if (tmpDirFile == null) {
999             String tmpDir = System.getProperty("java.io.tmpdir", ".");
1000             tmpDirFile = new File(tmpDir);
1001         }
1002         File result;
1003         do {
1004             result = new File(tmpDirFile, prefix + tempFileRandom.nextInt() + suffix);
1005         } while (!result.createNewFile());
1006         return result;
1007     }
1008 
1009     /**
1010      * Renames this file to {@code newPath}. This operation is supported for both
1011      * files and directories.
1012      *
1013      * <p>Many failures are possible. Some of the more likely failures include:
1014      * <ul>
1015      * <li>Write permission is required on the directories containing both the source and
1016      * destination paths.
1017      * <li>Search permission is required for all parents of both paths.
1018      * <li>Both paths be on the same mount point. On Android, applications are most likely to hit
1019      * this restriction when attempting to copy between internal storage and an SD card.
1020      * </ul>
1021      *
1022      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
1023      * Callers must check the return value.
1024      *
1025      * @param newPath the new path.
1026      * @return true on success.
1027      */
renameTo(File newPath)1028     public boolean renameTo(File newPath) {
1029         try {
1030             Libcore.os.rename(path, newPath.path);
1031             return true;
1032         } catch (ErrnoException errnoException) {
1033             return false;
1034         }
1035     }
1036 
1037     /**
1038      * Returns a string containing a concise, human-readable description of this
1039      * file.
1040      *
1041      * @return a printable representation of this file.
1042      */
1043     @Override
toString()1044     public String toString() {
1045         return path;
1046     }
1047 
1048     /**
1049      * Returns a Uniform Resource Identifier for this file. The URI is system
1050      * dependent and may not be transferable between different operating / file
1051      * systems.
1052      *
1053      * @return an URI for this file.
1054      */
toURI()1055     public URI toURI() {
1056         String name = getAbsoluteName();
1057         try {
1058             if (!name.startsWith("/")) {
1059                 // start with sep.
1060                 return new URI("file", null, "/" + name, null, null);
1061             } else if (name.startsWith("//")) {
1062                 return new URI("file", "", name, null); // UNC path
1063             }
1064             return new URI("file", null, name, null, null);
1065         } catch (URISyntaxException e) {
1066             // this should never happen
1067             return null;
1068         }
1069     }
1070 
1071     /**
1072      * Returns a Uniform Resource Locator for this file. The URL is system
1073      * dependent and may not be transferable between different operating / file
1074      * systems.
1075      *
1076      * @return a URL for this file.
1077      * @throws java.net.MalformedURLException
1078      *             if the path cannot be transformed into a URL.
1079      * @deprecated use {@link #toURI} and {@link java.net.URI#toURL} to get
1080      * correct escaping of illegal characters.
1081      */
1082     @Deprecated
toURL()1083     public URL toURL() throws java.net.MalformedURLException {
1084         String name = getAbsoluteName();
1085         if (!name.startsWith("/")) {
1086             // start with sep.
1087             return new URL("file", "", -1, "/" + name, null);
1088         } else if (name.startsWith("//")) {
1089             return new URL("file:" + name); // UNC path
1090         }
1091         return new URL("file", "", -1, name, null);
1092     }
1093 
1094     // TODO: is this really necessary, or can it be replaced with getAbsolutePath?
getAbsoluteName()1095     private String getAbsoluteName() {
1096         File f = getAbsoluteFile();
1097         String name = f.getPath();
1098         if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) {
1099             // Directories must end with a slash
1100             name = name + "/";
1101         }
1102         if (separatorChar != '/') { // Must convert slashes.
1103             name = name.replace(separatorChar, '/');
1104         }
1105         return name;
1106     }
1107 
writeObject(ObjectOutputStream stream)1108     private void writeObject(ObjectOutputStream stream) throws IOException {
1109         stream.defaultWriteObject();
1110         stream.writeChar(separatorChar);
1111     }
1112 
readObject(ObjectInputStream stream)1113     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
1114         stream.defaultReadObject();
1115         char inSeparator = stream.readChar();
1116         this.path = fixSlashes(path.replace(inSeparator, separatorChar));
1117     }
1118 
1119     /**
1120      * Returns the total size in bytes of the partition containing this path.
1121      * Returns 0 if this path does not exist.
1122      *
1123      * @since 1.6
1124      */
getTotalSpace()1125     public long getTotalSpace() {
1126         try {
1127             StructStatFs sb = Libcore.os.statfs(path);
1128             return sb.f_blocks * sb.f_bsize; // total block count * block size in bytes.
1129         } catch (ErrnoException errnoException) {
1130             return 0;
1131         }
1132     }
1133 
1134     /**
1135      * Returns the number of usable free bytes on the partition containing this path.
1136      * Returns 0 if this path does not exist.
1137      *
1138      * <p>Note that this is likely to be an optimistic over-estimate and should not
1139      * be taken as a guarantee your application can actually write this many bytes.
1140      * On Android (and other Unix-based systems), this method returns the number of free bytes
1141      * available to non-root users, regardless of whether you're actually running as root,
1142      * and regardless of any quota or other restrictions that might apply to the user.
1143      * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.)
1144      *
1145      * @since 1.6
1146      */
getUsableSpace()1147     public long getUsableSpace() {
1148         try {
1149             StructStatFs sb = Libcore.os.statfs(path);
1150             return sb.f_bavail * sb.f_bsize; // non-root free block count * block size in bytes.
1151         } catch (ErrnoException errnoException) {
1152             return 0;
1153         }
1154     }
1155 
1156     /**
1157      * Returns the number of free bytes on the partition containing this path.
1158      * Returns 0 if this path does not exist.
1159      *
1160      * <p>Note that this is likely to be an optimistic over-estimate and should not
1161      * be taken as a guarantee your application can actually write this many bytes.
1162      *
1163      * @since 1.6
1164      */
getFreeSpace()1165     public long getFreeSpace() {
1166         try {
1167             StructStatFs sb = Libcore.os.statfs(path);
1168             return sb.f_bfree * sb.f_bsize; // free block count * block size in bytes.
1169         } catch (ErrnoException errnoException) {
1170             return 0;
1171         }
1172     }
1173 }
1174