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