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