• 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("name == null");
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 this file, assuming its parents exist.
859      * Use {@link #mkdirs} if you also want to create missing parents.
860      *
861      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
862      * Callers must check the return value. Note also that this method returns
863      * false if the directory already existed. If you want to know whether the
864      * directory exists on return, either use {@code (f.mkdir() || f.isDirectory())}
865      * or simply ignore the return value from this method and simply call {@link #isDirectory}.
866      *
867      * @return {@code true} if the directory was created,
868      *         {@code false} on failure or if the directory already existed.
869      */
mkdir()870     public boolean mkdir() {
871         try {
872             mkdirErrno();
873             return true;
874         } catch (ErrnoException errnoException) {
875             return false;
876         }
877     }
878 
mkdirErrno()879     private void mkdirErrno() throws ErrnoException {
880         // On Android, we don't want default permissions to allow global access.
881         Libcore.os.mkdir(path, S_IRWXU);
882     }
883 
884     /**
885      * Creates the directory named by this file, creating missing parent
886      * directories if necessary.
887      * Use {@link #mkdir} if you don't want to create missing parents.
888      *
889      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
890      * Callers must check the return value. Note also that this method returns
891      * false if the directory already existed. If you want to know whether the
892      * directory exists on return, either use {@code (f.mkdirs() || f.isDirectory())}
893      * or simply ignore the return value from this method and simply call {@link #isDirectory}.
894      *
895      * @return {@code true} if the directory was created,
896      *         {@code false} on failure or if the directory already existed.
897      */
mkdirs()898     public boolean mkdirs() {
899         return mkdirs(false);
900     }
901 
mkdirs(boolean resultIfExists)902     private boolean mkdirs(boolean resultIfExists) {
903         try {
904             // Try to create the directory directly.
905             mkdirErrno();
906             return true;
907         } catch (ErrnoException errnoException) {
908             if (errnoException.errno == ENOENT) {
909                 // If the parent was missing, try to create it and then try again.
910                 File parent = getParentFile();
911                 return parent != null && parent.mkdirs(true) && mkdir();
912             } else if (errnoException.errno == EEXIST) {
913                 return resultIfExists;
914             }
915             return false;
916         }
917     }
918 
919     /**
920      * Creates a new, empty file on the file system according to the path
921      * information stored in this file. This method returns true if it creates
922      * a file, false if the file already existed. Note that it returns false
923      * even if the file is not a file (because it's a directory, say).
924      *
925      * <p>This method is not generally useful. For creating temporary files,
926      * use {@link #createTempFile} instead. For reading/writing files, use {@link FileInputStream},
927      * {@link FileOutputStream}, or {@link RandomAccessFile}, all of which can create files.
928      *
929      * <p>Note that this method does <i>not</i> throw {@code IOException} if the file
930      * already exists, even if it's not a regular file. Callers should always check the
931      * return value, and may additionally want to call {@link #isFile}.
932      *
933      * @return true if the file has been created, false if it
934      *         already exists.
935      * @throws IOException if it's not possible to create the file.
936      */
createNewFile()937     public boolean createNewFile() throws IOException {
938         FileDescriptor fd = null;
939         try {
940             // On Android, we don't want default permissions to allow global access.
941             fd = Libcore.os.open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
942             return true;
943         } catch (ErrnoException errnoException) {
944             if (errnoException.errno == EEXIST) {
945                 // The file already exists.
946                 return false;
947             }
948             throw errnoException.rethrowAsIOException();
949         } finally {
950             IoUtils.close(fd); // TODO: should we suppress IOExceptions thrown here?
951         }
952     }
953 
954     /**
955      * Creates an empty temporary file using the given prefix and suffix as part
956      * of the file name. If {@code suffix} is null, {@code .tmp} is used. This
957      * method is a convenience method that calls
958      * {@link #createTempFile(String, String, File)} with the third argument
959      * being {@code null}.
960      *
961      * @param prefix
962      *            the prefix to the temp file name.
963      * @param suffix
964      *            the suffix to the temp file name.
965      * @return the temporary file.
966      * @throws IOException
967      *             if an error occurs when writing the file.
968      */
createTempFile(String prefix, String suffix)969     public static File createTempFile(String prefix, String suffix) throws IOException {
970         return createTempFile(prefix, suffix, null);
971     }
972 
973     /**
974      * Creates an empty temporary file in the given directory using the given
975      * prefix and suffix as part of the file name. If {@code suffix} is null, {@code .tmp} is used.
976      *
977      * <p>Note that this method does <i>not</i> call {@link #deleteOnExit}, but see the
978      * documentation for that method before you call it manually.
979      *
980      * @param prefix
981      *            the prefix to the temp file name.
982      * @param suffix
983      *            the suffix to the temp file name.
984      * @param directory
985      *            the location to which the temp file is to be written, or
986      *            {@code null} for the default location for temporary files,
987      *            which is taken from the "java.io.tmpdir" system property. It
988      *            may be necessary to set this property to an existing, writable
989      *            directory for this method to work properly.
990      * @return the temporary file.
991      * @throws IllegalArgumentException
992      *             if the length of {@code prefix} is less than 3.
993      * @throws IOException
994      *             if an error occurs when writing the file.
995      */
createTempFile(String prefix, String suffix, File directory)996     public static File createTempFile(String prefix, String suffix, File directory)
997             throws IOException {
998         // Force a prefix null check first
999         if (prefix.length() < 3) {
1000             throw new IllegalArgumentException("prefix must be at least 3 characters");
1001         }
1002         if (suffix == null) {
1003             suffix = ".tmp";
1004         }
1005         File tmpDirFile = directory;
1006         if (tmpDirFile == null) {
1007             String tmpDir = System.getProperty("java.io.tmpdir", ".");
1008             tmpDirFile = new File(tmpDir);
1009         }
1010         File result;
1011         do {
1012             result = new File(tmpDirFile, prefix + tempFileRandom.nextInt() + suffix);
1013         } while (!result.createNewFile());
1014         return result;
1015     }
1016 
1017     /**
1018      * Renames this file to {@code newPath}. This operation is supported for both
1019      * files and directories.
1020      *
1021      * <p>Many failures are possible. Some of the more likely failures include:
1022      * <ul>
1023      * <li>Write permission is required on the directories containing both the source and
1024      * destination paths.
1025      * <li>Search permission is required for all parents of both paths.
1026      * <li>Both paths be on the same mount point. On Android, applications are most likely to hit
1027      * this restriction when attempting to copy between internal storage and an SD card.
1028      * </ul>
1029      *
1030      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
1031      * Callers must check the return value.
1032      *
1033      * @param newPath the new path.
1034      * @return true on success.
1035      */
renameTo(File newPath)1036     public boolean renameTo(File newPath) {
1037         try {
1038             Libcore.os.rename(path, newPath.path);
1039             return true;
1040         } catch (ErrnoException errnoException) {
1041             return false;
1042         }
1043     }
1044 
1045     /**
1046      * Returns a string containing a concise, human-readable description of this
1047      * file.
1048      *
1049      * @return a printable representation of this file.
1050      */
1051     @Override
toString()1052     public String toString() {
1053         return path;
1054     }
1055 
1056     /**
1057      * Returns a Uniform Resource Identifier for this file. The URI is system
1058      * dependent and may not be transferable between different operating / file
1059      * systems.
1060      *
1061      * @return an URI for this file.
1062      */
toURI()1063     public URI toURI() {
1064         String name = getAbsoluteName();
1065         try {
1066             if (!name.startsWith("/")) {
1067                 // start with sep.
1068                 return new URI("file", null, "/" + name, null, null);
1069             } else if (name.startsWith("//")) {
1070                 return new URI("file", "", name, null); // UNC path
1071             }
1072             return new URI("file", null, name, null, null);
1073         } catch (URISyntaxException e) {
1074             // this should never happen
1075             return null;
1076         }
1077     }
1078 
1079     /**
1080      * Returns a Uniform Resource Locator for this file. The URL is system
1081      * dependent and may not be transferable between different operating / file
1082      * systems.
1083      *
1084      * @return a URL for this file.
1085      * @throws java.net.MalformedURLException
1086      *             if the path cannot be transformed into a URL.
1087      * @deprecated use {@link #toURI} and {@link java.net.URI#toURL} to get
1088      * correct escaping of illegal characters.
1089      */
1090     @Deprecated
toURL()1091     public URL toURL() throws java.net.MalformedURLException {
1092         String name = getAbsoluteName();
1093         if (!name.startsWith("/")) {
1094             // start with sep.
1095             return new URL("file", "", -1, "/" + name, null);
1096         } else if (name.startsWith("//")) {
1097             return new URL("file:" + name); // UNC path
1098         }
1099         return new URL("file", "", -1, name, null);
1100     }
1101 
1102     // TODO: is this really necessary, or can it be replaced with getAbsolutePath?
getAbsoluteName()1103     private String getAbsoluteName() {
1104         File f = getAbsoluteFile();
1105         String name = f.getPath();
1106         if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) {
1107             // Directories must end with a slash
1108             name = name + "/";
1109         }
1110         if (separatorChar != '/') { // Must convert slashes.
1111             name = name.replace(separatorChar, '/');
1112         }
1113         return name;
1114     }
1115 
writeObject(ObjectOutputStream stream)1116     private void writeObject(ObjectOutputStream stream) throws IOException {
1117         stream.defaultWriteObject();
1118         stream.writeChar(separatorChar);
1119     }
1120 
readObject(ObjectInputStream stream)1121     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
1122         stream.defaultReadObject();
1123         char inSeparator = stream.readChar();
1124         this.path = fixSlashes(path.replace(inSeparator, separatorChar));
1125     }
1126 
1127     /**
1128      * Returns the total size in bytes of the partition containing this path.
1129      * Returns 0 if this path does not exist.
1130      *
1131      * @since 1.6
1132      */
getTotalSpace()1133     public long getTotalSpace() {
1134         try {
1135             StructStatFs sb = Libcore.os.statfs(path);
1136             return sb.f_blocks * sb.f_bsize; // total block count * block size in bytes.
1137         } catch (ErrnoException errnoException) {
1138             return 0;
1139         }
1140     }
1141 
1142     /**
1143      * Returns the number of usable free bytes on the partition containing this path.
1144      * Returns 0 if this path does not exist.
1145      *
1146      * <p>Note that this is likely to be an optimistic over-estimate and should not
1147      * be taken as a guarantee your application can actually write this many bytes.
1148      * On Android (and other Unix-based systems), this method returns the number of free bytes
1149      * available to non-root users, regardless of whether you're actually running as root,
1150      * and regardless of any quota or other restrictions that might apply to the user.
1151      * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.)
1152      *
1153      * @since 1.6
1154      */
getUsableSpace()1155     public long getUsableSpace() {
1156         try {
1157             StructStatFs sb = Libcore.os.statfs(path);
1158             return sb.f_bavail * sb.f_bsize; // non-root free block count * block size in bytes.
1159         } catch (ErrnoException errnoException) {
1160             return 0;
1161         }
1162     }
1163 
1164     /**
1165      * Returns the number of free bytes on the partition containing this path.
1166      * Returns 0 if this path does not exist.
1167      *
1168      * <p>Note that this is likely to be an optimistic over-estimate and should not
1169      * be taken as a guarantee your application can actually write this many bytes.
1170      *
1171      * @since 1.6
1172      */
getFreeSpace()1173     public long getFreeSpace() {
1174         try {
1175             StructStatFs sb = Libcore.os.statfs(path);
1176             return sb.f_bfree * sb.f_bsize; // free block count * block size in bytes.
1177         } catch (ErrnoException errnoException) {
1178             return 0;
1179         }
1180     }
1181 }
1182