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 18package java.io; 19 20import java.net.URI; 21import java.net.URISyntaxException; 22import java.net.URL; 23import java.util.ArrayList; 24import java.util.List; 25import java.util.Random; 26import libcore.io.ErrnoException; 27import libcore.io.IoUtils; 28import libcore.io.Libcore; 29import libcore.io.StructStat; 30import libcore.io.StructStatVfs; 31import org.apache.harmony.luni.util.DeleteOnExit; 32import 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 */ 55public 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 */ 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 */ 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 */ 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 */ 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. 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. 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 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 */ 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 */ 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 */ 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 */ 277 public boolean canWrite() { 278 return doAccess(W_OK); 279 } 280 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 413 public String getCanonicalPath() throws IOException { 414 return realpath(getAbsolutePath()); 415 } 416 417 /** 418 * TODO: move this stuff to libcore.os. 419 * @hide 420 */ 421 private static native String realpath(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 */ 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 */ 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 */ 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 */ 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 public String getPath() { 492 return path; 493 } 494 495 /** 496 * Returns an integer hash code for the receiver. Any two objects for which 497 * {@code equals} returns {@code true} must return the same hash code. 498 * 499 * @return this files's hash value. 500 * @see #equals 501 */ 502 @Override 503 public int hashCode() { 504 return getPath().hashCode() ^ 1234321; 505 } 506 507 /** 508 * Indicates if this file's pathname is absolute. Whether a pathname is 509 * absolute is platform specific. On Android, absolute paths start with 510 * the character '/'. 511 * 512 * @return {@code true} if this file's pathname is absolute, {@code false} 513 * otherwise. 514 * @see #getPath 515 */ 516 public boolean isAbsolute() { 517 return path.length() > 0 && path.charAt(0) == separatorChar; 518 } 519 520 /** 521 * Indicates if this file represents a <em>directory</em> on the 522 * underlying file system. 523 * 524 * @return {@code true} if this file is a directory, {@code false} 525 * otherwise. 526 */ 527 public boolean isDirectory() { 528 try { 529 return S_ISDIR(Libcore.os.stat(path).st_mode); 530 } catch (ErrnoException errnoException) { 531 // The RI returns false on error. (Even for errors like EACCES or ELOOP.) 532 return false; 533 } 534 } 535 536 /** 537 * Indicates if this file represents a <em>file</em> on the underlying 538 * file system. 539 * 540 * @return {@code true} if this file is a file, {@code false} otherwise. 541 */ 542 public boolean isFile() { 543 try { 544 return S_ISREG(Libcore.os.stat(path).st_mode); 545 } catch (ErrnoException errnoException) { 546 // The RI returns false on error. (Even for errors like EACCES or ELOOP.) 547 return false; 548 } 549 } 550 551 /** 552 * Returns whether or not this file is a hidden file as defined by the 553 * operating system. The notion of "hidden" is system-dependent. For Unix 554 * systems a file is considered hidden if its name starts with a ".". For 555 * Windows systems there is an explicit flag in the file system for this 556 * purpose. 557 * 558 * @return {@code true} if the file is hidden, {@code false} otherwise. 559 */ 560 public boolean isHidden() { 561 if (path.isEmpty()) { 562 return false; 563 } 564 return getName().startsWith("."); 565 } 566 567 /** 568 * Returns the time when this file was last modified, measured in 569 * milliseconds since January 1st, 1970, midnight. 570 * Returns 0 if the file does not exist. 571 * 572 * @return the time when this file was last modified. 573 */ 574 public long lastModified() { 575 try { 576 return Libcore.os.stat(path).st_mtime * 1000L; 577 } catch (ErrnoException errnoException) { 578 // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.) 579 return 0; 580 } 581 } 582 583 /** 584 * Sets the time this file was last modified, measured in milliseconds since 585 * January 1st, 1970, midnight. 586 * 587 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 588 * Callers must check the return value. 589 * 590 * @param time 591 * the last modification time for this file. 592 * @return {@code true} if the operation is successful, {@code false} 593 * otherwise. 594 * @throws IllegalArgumentException 595 * if {@code time < 0}. 596 */ 597 public boolean setLastModified(long time) { 598 if (time < 0) { 599 throw new IllegalArgumentException("time < 0"); 600 } 601 return setLastModifiedImpl(path, time); 602 } 603 604 private static native boolean setLastModifiedImpl(String path, long time); 605 606 /** 607 * Equivalent to setWritable(false, false). 608 * 609 * @see #setWritable(boolean, boolean) 610 */ 611 public boolean setReadOnly() { 612 return setWritable(false, false); 613 } 614 615 /** 616 * Manipulates the execute permissions for the abstract path designated by 617 * this file. 618 * 619 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 620 * Callers must check the return value. 621 * 622 * @param executable 623 * To allow execute permission if true, otherwise disallow 624 * @param ownerOnly 625 * To manipulate execute permission only for owner if true, 626 * otherwise for everyone. The manipulation will apply to 627 * everyone regardless of this value if the underlying system 628 * does not distinguish owner and other users. 629 * @return true if and only if the operation succeeded. If the user does not 630 * have permission to change the access permissions of this abstract 631 * pathname the operation will fail. If the underlying file system 632 * does not support execute permission and the value of executable 633 * is false, this operation will fail. 634 * @since 1.6 635 */ 636 public boolean setExecutable(boolean executable, boolean ownerOnly) { 637 return doChmod(ownerOnly ? S_IXUSR : (S_IXUSR | S_IXGRP | S_IXOTH), executable); 638 } 639 640 /** 641 * Equivalent to setExecutable(executable, true). 642 * @see #setExecutable(boolean, boolean) 643 * @since 1.6 644 */ 645 public boolean setExecutable(boolean executable) { 646 return setExecutable(executable, true); 647 } 648 649 /** 650 * Manipulates the read permissions for the abstract path designated by this 651 * file. 652 * 653 * @param readable 654 * To allow read permission if true, otherwise disallow 655 * @param ownerOnly 656 * To manipulate read permission only for owner if true, 657 * otherwise for everyone. The manipulation will apply to 658 * everyone regardless of this value if the underlying system 659 * does not distinguish owner and other users. 660 * @return true if and only if the operation succeeded. If the user does not 661 * have permission to change the access permissions of this abstract 662 * pathname the operation will fail. If the underlying file system 663 * does not support read permission and the value of readable is 664 * false, this operation will fail. 665 * @since 1.6 666 */ 667 public boolean setReadable(boolean readable, boolean ownerOnly) { 668 return doChmod(ownerOnly ? S_IRUSR : (S_IRUSR | S_IRGRP | S_IROTH), readable); 669 } 670 671 /** 672 * Equivalent to setReadable(readable, true). 673 * @see #setReadable(boolean, boolean) 674 * @since 1.6 675 */ 676 public boolean setReadable(boolean readable) { 677 return setReadable(readable, true); 678 } 679 680 /** 681 * Manipulates the write permissions for the abstract path designated by this 682 * file. 683 * 684 * @param writable 685 * To allow write permission if true, otherwise disallow 686 * @param ownerOnly 687 * To manipulate write permission only for owner if true, 688 * otherwise for everyone. The manipulation will apply to 689 * everyone regardless of this value if the underlying system 690 * does not distinguish owner and other users. 691 * @return true if and only if the operation succeeded. If the user does not 692 * have permission to change the access permissions of this abstract 693 * pathname the operation will fail. 694 * @since 1.6 695 */ 696 public boolean setWritable(boolean writable, boolean ownerOnly) { 697 return doChmod(ownerOnly ? S_IWUSR : (S_IWUSR | S_IWGRP | S_IWOTH), writable); 698 } 699 700 /** 701 * Equivalent to setWritable(writable, true). 702 * @see #setWritable(boolean, boolean) 703 * @since 1.6 704 */ 705 public boolean setWritable(boolean writable) { 706 return setWritable(writable, true); 707 } 708 709 private boolean doChmod(int mask, boolean set) { 710 try { 711 StructStat sb = Libcore.os.stat(path); 712 int newMode = set ? (sb.st_mode | mask) : (sb.st_mode & ~mask); 713 Libcore.os.chmod(path, newMode); 714 return true; 715 } catch (ErrnoException errnoException) { 716 return false; 717 } 718 } 719 720 /** 721 * Returns the length of this file in bytes. 722 * Returns 0 if the file does not exist. 723 * The result for a directory is not defined. 724 * 725 * @return the number of bytes in this file. 726 */ 727 public long length() { 728 try { 729 return Libcore.os.stat(path).st_size; 730 } catch (ErrnoException errnoException) { 731 // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.) 732 return 0; 733 } 734 } 735 736 /** 737 * Returns an array of strings with the file names in the directory 738 * represented by this file. The result is {@code null} if this file is not 739 * a directory. 740 * <p> 741 * The entries {@code .} and {@code ..} representing the current and parent 742 * directory are not returned as part of the list. 743 * 744 * @return an array of strings with file names or {@code null}. 745 */ 746 public String[] list() { 747 return listImpl(path); 748 } 749 750 private static native String[] listImpl(String path); 751 752 /** 753 * Gets a list of the files in the directory represented by this file. This 754 * list is then filtered through a FilenameFilter and the names of files 755 * with matching names are returned as an array of strings. Returns 756 * {@code null} if this file is not a directory. If {@code filter} is 757 * {@code null} then all filenames match. 758 * <p> 759 * The entries {@code .} and {@code ..} representing the current and parent 760 * directories are not returned as part of the list. 761 * 762 * @param filter 763 * the filter to match names against, may be {@code null}. 764 * @return an array of files or {@code null}. 765 */ 766 public String[] list(FilenameFilter filter) { 767 String[] filenames = list(); 768 if (filter == null || filenames == null) { 769 return filenames; 770 } 771 List<String> result = new ArrayList<String>(filenames.length); 772 for (String filename : filenames) { 773 if (filter.accept(this, filename)) { 774 result.add(filename); 775 } 776 } 777 return result.toArray(new String[result.size()]); 778 } 779 780 /** 781 * Returns an array of files contained in the directory represented by this 782 * file. The result is {@code null} if this file is not a directory. The 783 * paths of the files in the array are absolute if the path of this file is 784 * absolute, they are relative otherwise. 785 * 786 * @return an array of files or {@code null}. 787 */ 788 public File[] listFiles() { 789 return filenamesToFiles(list()); 790 } 791 792 /** 793 * Gets a list of the files in the directory represented by this file. This 794 * list is then filtered through a FilenameFilter and files with matching 795 * names are returned as an array of files. Returns {@code null} if this 796 * file is not a directory. If {@code filter} is {@code null} then all 797 * filenames match. 798 * <p> 799 * The entries {@code .} and {@code ..} representing the current and parent 800 * directories are not returned as part of the list. 801 * 802 * @param filter 803 * the filter to match names against, may be {@code null}. 804 * @return an array of files or {@code null}. 805 */ 806 public File[] listFiles(FilenameFilter filter) { 807 return filenamesToFiles(list(filter)); 808 } 809 810 /** 811 * Gets a list of the files in the directory represented by this file. This 812 * list is then filtered through a FileFilter and matching files are 813 * returned as an array of files. Returns {@code null} if this file is not a 814 * directory. If {@code filter} is {@code null} then all files match. 815 * <p> 816 * The entries {@code .} and {@code ..} representing the current and parent 817 * directories are not returned as part of the list. 818 * 819 * @param filter 820 * the filter to match names against, may be {@code null}. 821 * @return an array of files or {@code null}. 822 */ 823 public File[] listFiles(FileFilter filter) { 824 File[] files = listFiles(); 825 if (filter == null || files == null) { 826 return files; 827 } 828 List<File> result = new ArrayList<File>(files.length); 829 for (File file : files) { 830 if (filter.accept(file)) { 831 result.add(file); 832 } 833 } 834 return result.toArray(new File[result.size()]); 835 } 836 837 /** 838 * Converts a String[] containing filenames to a File[]. 839 * Note that the filenames must not contain slashes. 840 * This method is to remove duplication in the implementation 841 * of File.list's overloads. 842 */ 843 private File[] filenamesToFiles(String[] filenames) { 844 if (filenames == null) { 845 return null; 846 } 847 int count = filenames.length; 848 File[] result = new File[count]; 849 for (int i = 0; i < count; ++i) { 850 result[i] = new File(this, filenames[i]); 851 } 852 return result; 853 } 854 855 /** 856 * Creates the directory named by this file, assuming its parents exist. 857 * Use {@link #mkdirs} if you also want to create missing parents. 858 * 859 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 860 * Callers must check the return value. Note also that this method returns 861 * false if the directory already existed. If you want to know whether the 862 * directory exists on return, either use {@code (f.mkdir() || f.isDirectory())} 863 * or simply ignore the return value from this method and simply call {@link #isDirectory}. 864 * 865 * @return {@code true} if the directory was created, 866 * {@code false} on failure or if the directory already existed. 867 */ 868 public boolean mkdir() { 869 try { 870 mkdirErrno(); 871 return true; 872 } catch (ErrnoException errnoException) { 873 return false; 874 } 875 } 876 877 private void mkdirErrno() throws ErrnoException { 878 // On Android, we don't want default permissions to allow global access. 879 Libcore.os.mkdir(path, S_IRWXU); 880 } 881 882 /** 883 * Creates the directory named by this file, creating missing parent 884 * directories if necessary. 885 * Use {@link #mkdir} if you don't want to create missing parents. 886 * 887 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 888 * Callers must check the return value. Note also that this method returns 889 * false if the directory already existed. If you want to know whether the 890 * directory exists on return, either use {@code (f.mkdirs() || f.isDirectory())} 891 * or simply ignore the return value from this method and simply call {@link #isDirectory}. 892 * 893 * @return {@code true} if the directory was created, 894 * {@code false} on failure or if the directory already existed. 895 */ 896 public boolean mkdirs() { 897 return mkdirs(false); 898 } 899 900 private boolean mkdirs(boolean resultIfExists) { 901 try { 902 // Try to create the directory directly. 903 mkdirErrno(); 904 return true; 905 } catch (ErrnoException errnoException) { 906 if (errnoException.errno == ENOENT) { 907 // If the parent was missing, try to create it and then try again. 908 File parent = getParentFile(); 909 return parent != null && parent.mkdirs(true) && mkdir(); 910 } else if (errnoException.errno == EEXIST) { 911 return resultIfExists; 912 } 913 return false; 914 } 915 } 916 917 /** 918 * Creates a new, empty file on the file system according to the path 919 * information stored in this file. This method returns true if it creates 920 * a file, false if the file already existed. Note that it returns false 921 * even if the file is not a file (because it's a directory, say). 922 * 923 * <p>This method is not generally useful. For creating temporary files, 924 * use {@link #createTempFile} instead. For reading/writing files, use {@link FileInputStream}, 925 * {@link FileOutputStream}, or {@link RandomAccessFile}, all of which can create files. 926 * 927 * <p>Note that this method does <i>not</i> throw {@code IOException} if the file 928 * already exists, even if it's not a regular file. Callers should always check the 929 * return value, and may additionally want to call {@link #isFile}. 930 * 931 * @return true if the file has been created, false if it 932 * already exists. 933 * @throws IOException if it's not possible to create the file. 934 */ 935 public boolean createNewFile() throws IOException { 936 FileDescriptor fd = null; 937 try { 938 // On Android, we don't want default permissions to allow global access. 939 fd = Libcore.os.open(path, O_RDWR | O_CREAT | O_EXCL, 0600); 940 return true; 941 } catch (ErrnoException errnoException) { 942 if (errnoException.errno == EEXIST) { 943 // The file already exists. 944 return false; 945 } 946 throw errnoException.rethrowAsIOException(); 947 } finally { 948 IoUtils.close(fd); // TODO: should we suppress IOExceptions thrown here? 949 } 950 } 951 952 /** 953 * Creates an empty temporary file using the given prefix and suffix as part 954 * of the file name. If {@code suffix} is null, {@code .tmp} is used. This 955 * method is a convenience method that calls 956 * {@link #createTempFile(String, String, File)} with the third argument 957 * being {@code null}. 958 * 959 * @param prefix 960 * the prefix to the temp file name. 961 * @param suffix 962 * the suffix to the temp file name. 963 * @return the temporary file. 964 * @throws IOException 965 * if an error occurs when writing the file. 966 */ 967 public static File createTempFile(String prefix, String suffix) throws IOException { 968 return createTempFile(prefix, suffix, null); 969 } 970 971 /** 972 * Creates an empty temporary file in the given directory using the given 973 * prefix and suffix as part of the file name. If {@code suffix} is null, {@code .tmp} is used. 974 * 975 * <p>Note that this method does <i>not</i> call {@link #deleteOnExit}, but see the 976 * documentation for that method before you call it manually. 977 * 978 * @param prefix 979 * the prefix to the temp file name. 980 * @param suffix 981 * the suffix to the temp file name. 982 * @param directory 983 * the location to which the temp file is to be written, or 984 * {@code null} for the default location for temporary files, 985 * which is taken from the "java.io.tmpdir" system property. It 986 * may be necessary to set this property to an existing, writable 987 * directory for this method to work properly. 988 * @return the temporary file. 989 * @throws IllegalArgumentException 990 * if the length of {@code prefix} is less than 3. 991 * @throws IOException 992 * if an error occurs when writing the file. 993 */ 994 public static File createTempFile(String prefix, String suffix, File directory) 995 throws IOException { 996 // Force a prefix null check first 997 if (prefix.length() < 3) { 998 throw new IllegalArgumentException("prefix must be at least 3 characters"); 999 } 1000 if (suffix == null) { 1001 suffix = ".tmp"; 1002 } 1003 File tmpDirFile = directory; 1004 if (tmpDirFile == null) { 1005 String tmpDir = System.getProperty("java.io.tmpdir", "."); 1006 tmpDirFile = new File(tmpDir); 1007 } 1008 File result; 1009 do { 1010 result = new File(tmpDirFile, prefix + tempFileRandom.nextInt() + suffix); 1011 } while (!result.createNewFile()); 1012 return result; 1013 } 1014 1015 /** 1016 * Renames this file to {@code newPath}. This operation is supported for both 1017 * files and directories. 1018 * 1019 * <p>Many failures are possible. Some of the more likely failures include: 1020 * <ul> 1021 * <li>Write permission is required on the directories containing both the source and 1022 * destination paths. 1023 * <li>Search permission is required for all parents of both paths. 1024 * <li>Both paths be on the same mount point. On Android, applications are most likely to hit 1025 * this restriction when attempting to copy between internal storage and an SD card. 1026 * </ul> 1027 * 1028 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 1029 * Callers must check the return value. 1030 * 1031 * @param newPath the new path. 1032 * @return true on success. 1033 */ 1034 public boolean renameTo(File newPath) { 1035 try { 1036 Libcore.os.rename(path, newPath.path); 1037 return true; 1038 } catch (ErrnoException errnoException) { 1039 return false; 1040 } 1041 } 1042 1043 /** 1044 * Returns a string containing a concise, human-readable description of this 1045 * file. 1046 * 1047 * @return a printable representation of this file. 1048 */ 1049 @Override 1050 public String toString() { 1051 return path; 1052 } 1053 1054 /** 1055 * Returns a Uniform Resource Identifier for this file. The URI is system 1056 * dependent and may not be transferable between different operating / file 1057 * systems. 1058 * 1059 * @return an URI for this file. 1060 */ 1061 public URI toURI() { 1062 String name = getAbsoluteName(); 1063 try { 1064 if (!name.startsWith("/")) { 1065 // start with sep. 1066 return new URI("file", null, "/" + name, null, null); 1067 } else if (name.startsWith("//")) { 1068 return new URI("file", "", name, null); // UNC path 1069 } 1070 return new URI("file", null, name, null, null); 1071 } catch (URISyntaxException e) { 1072 // this should never happen 1073 return null; 1074 } 1075 } 1076 1077 /** 1078 * Returns a Uniform Resource Locator for this file. The URL is system 1079 * dependent and may not be transferable between different operating / file 1080 * systems. 1081 * 1082 * @return a URL for this file. 1083 * @throws java.net.MalformedURLException 1084 * if the path cannot be transformed into a URL. 1085 * @deprecated Use {@link #toURI} and {@link java.net.URI#toURL} to 1086 * correctly escape illegal characters. 1087 */ 1088 @Deprecated 1089 public URL toURL() throws java.net.MalformedURLException { 1090 String name = getAbsoluteName(); 1091 if (!name.startsWith("/")) { 1092 // start with sep. 1093 return new URL("file", "", -1, "/" + name, null); 1094 } else if (name.startsWith("//")) { 1095 return new URL("file:" + name); // UNC path 1096 } 1097 return new URL("file", "", -1, name, null); 1098 } 1099 1100 // TODO: is this really necessary, or can it be replaced with getAbsolutePath? 1101 private String getAbsoluteName() { 1102 File f = getAbsoluteFile(); 1103 String name = f.getPath(); 1104 if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) { 1105 // Directories must end with a slash 1106 name = name + "/"; 1107 } 1108 if (separatorChar != '/') { // Must convert slashes. 1109 name = name.replace(separatorChar, '/'); 1110 } 1111 return name; 1112 } 1113 1114 private void writeObject(ObjectOutputStream stream) throws IOException { 1115 stream.defaultWriteObject(); 1116 stream.writeChar(separatorChar); 1117 } 1118 1119 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 1120 stream.defaultReadObject(); 1121 char inSeparator = stream.readChar(); 1122 this.path = fixSlashes(path.replace(inSeparator, separatorChar)); 1123 } 1124 1125 /** 1126 * Returns the total size in bytes of the partition containing this path. 1127 * Returns 0 if this path does not exist. 1128 * 1129 * @since 1.6 1130 */ 1131 public long getTotalSpace() { 1132 try { 1133 StructStatVfs sb = Libcore.os.statvfs(path); 1134 return sb.f_blocks * sb.f_bsize; // total block count * block size in bytes. 1135 } catch (ErrnoException errnoException) { 1136 return 0; 1137 } 1138 } 1139 1140 /** 1141 * Returns the number of usable free bytes on the partition containing this path. 1142 * Returns 0 if this path does not exist. 1143 * 1144 * <p>Note that this is likely to be an optimistic over-estimate and should not 1145 * be taken as a guarantee your application can actually write this many bytes. 1146 * On Android (and other Unix-based systems), this method returns the number of free bytes 1147 * available to non-root users, regardless of whether you're actually running as root, 1148 * and regardless of any quota or other restrictions that might apply to the user. 1149 * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.) 1150 * 1151 * @since 1.6 1152 */ 1153 public long getUsableSpace() { 1154 try { 1155 StructStatVfs sb = Libcore.os.statvfs(path); 1156 return sb.f_bavail * sb.f_bsize; // non-root free block count * block size in bytes. 1157 } catch (ErrnoException errnoException) { 1158 return 0; 1159 } 1160 } 1161 1162 /** 1163 * Returns the number of free bytes on the partition containing this path. 1164 * Returns 0 if this path does not exist. 1165 * 1166 * <p>Note that this is likely to be an optimistic over-estimate and should not 1167 * be taken as a guarantee your application can actually write this many bytes. 1168 * 1169 * @since 1.6 1170 */ 1171 public long getFreeSpace() { 1172 try { 1173 StructStatVfs sb = Libcore.os.statvfs(path); 1174 return sb.f_bfree * sb.f_bsize; // free block count * block size in bytes. 1175 } catch (ErrnoException errnoException) { 1176 return 0; 1177 } 1178 } 1179} 1180