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