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 // BEGIN android-note 19 // We've dropped Windows support, except where it's exposed: we still support 20 // non-Unix separators in serialized File objects, for example, but we don't 21 // have any code for UNC paths or case-insensitivity. 22 // We've also changed the JNI interface to better match what the Java actually wants. 23 // (The JNI implementation is also much simpler.) 24 // Some methods have been rewritten to reduce unnecessary allocation. 25 // Some duplication has been factored out. 26 // END android-note 27 28 package java.io; 29 30 import java.net.URI; 31 import java.net.URISyntaxException; 32 import java.net.URL; 33 import java.security.AccessController; 34 import java.util.ArrayList; 35 import java.util.List; 36 import java.util.Random; 37 import org.apache.harmony.luni.util.DeleteOnExit; 38 import org.apache.harmony.luni.util.PriviAction; 39 40 /** 41 * An "abstract" representation of a file system entity identified by a 42 * pathname. The pathname may be absolute (relative to the root directory 43 * of the file system) or relative to the current directory in which the program 44 * is running. 45 * <p> 46 * The actual file referenced by a {@code File} may or may not exist. It may 47 * also, despite the name {@code File}, be a directory or other non-regular 48 * file. 49 * <p> 50 * This class provides limited functionality for getting/setting file 51 * permissions, file type, and last modified time. 52 * <p> 53 * Although Java doesn't specify a character encoding for filenames, on Android 54 * Java strings are converted to UTF-8 byte sequences when sending filenames to 55 * the operating system, and byte sequences returned by the operating system 56 * (from the various {@code list} methods) are converted to Java strings by 57 * decoding them as UTF-8 byte sequences. 58 * 59 * @see java.io.Serializable 60 * @see java.lang.Comparable 61 */ 62 public class File implements Serializable, Comparable<File> { 63 64 private static final long serialVersionUID = 301077366599181567L; 65 66 /** 67 * The system-dependent character used to separate components in filenames ('/'). 68 * Use of this (rather than hard-coding '/') helps portability to other operating systems. 69 * 70 * <p>This field is initialized from the system property "file.separator". 71 * Later changes to that property will have no effect on this field or this class. 72 */ 73 public static final char separatorChar; 74 75 /** 76 * The system-dependent string used to separate components in filenames ('/'). 77 * See {@link #separatorChar}. 78 */ 79 public static final String separator; 80 81 /** 82 * The system-dependent character used to separate components in search paths (':'). 83 * This is used to split such things as the PATH environment variable and classpath 84 * system properties into lists of directories to be searched. 85 * 86 * <p>This field is initialized from the system property "path.separator". 87 * Later changes to that property will have no effect on this field or this class. 88 */ 89 public static final char pathSeparatorChar; 90 91 /** 92 * The system-dependent string used to separate components in search paths (":"). 93 * See {@link #pathSeparatorChar}. 94 */ 95 public static final String pathSeparator; 96 97 /** 98 * The path we return from getPath. This is almost the path we were 99 * given, but without duplicate adjacent slashes and without trailing 100 * slashes (except for the special case of the root directory). This 101 * path may be the empty string. 102 */ 103 private String path; 104 105 /** 106 * The path we return from getAbsolutePath, and pass down to native code. 107 */ 108 private String absolutePath; 109 110 static { 111 // The default protection domain grants access to these properties. 112 separatorChar = System.getProperty("file.separator", "/").charAt(0); 113 pathSeparatorChar = System.getProperty("path.separator", ":").charAt(0); 114 separator = String.valueOf(separatorChar); 115 pathSeparator = String.valueOf(pathSeparatorChar); 116 } 117 118 /** 119 * Constructs a new file using the specified directory and name. 120 * 121 * @param dir 122 * the directory where the file is stored. 123 * @param name 124 * the file's name. 125 * @throws NullPointerException 126 * if {@code name} is {@code null}. 127 */ File(File dir, String name)128 public File(File dir, String name) { 129 this(dir == null ? null : dir.getPath(), name); 130 } 131 132 /** 133 * Constructs a new file using the specified path. 134 * 135 * @param path 136 * the path to be used for the file. 137 */ File(String path)138 public File(String path) { 139 init(path); 140 } 141 142 /** 143 * Constructs a new File using the specified directory path and file name, 144 * placing a path separator between the two. 145 * 146 * @param dirPath 147 * the path to the directory where the file is stored. 148 * @param name 149 * the file's name. 150 * @throws NullPointerException 151 * if {@code name} is {@code null}. 152 */ File(String dirPath, String name)153 public File(String dirPath, String name) { 154 if (name == null) { 155 throw new NullPointerException(); 156 } 157 if (dirPath == null || dirPath.isEmpty()) { 158 init(name); 159 } else if (name.isEmpty()) { 160 init(dirPath); 161 } else { 162 init(join(dirPath, name)); 163 } 164 } 165 166 /** 167 * Constructs a new File using the path of the specified URI. {@code uri} 168 * needs to be an absolute and hierarchical Unified Resource Identifier with 169 * file scheme and non-empty path component, but with undefined authority, 170 * query or fragment components. 171 * 172 * @param uri 173 * the Unified Resource Identifier that is used to construct this 174 * file. 175 * @throws IllegalArgumentException 176 * if {@code uri} does not comply with the conditions above. 177 * @see #toURI 178 * @see java.net.URI 179 */ File(URI uri)180 public File(URI uri) { 181 // check pre-conditions 182 checkURI(uri); 183 init(uri.getPath()); 184 } 185 init(String dirtyPath)186 private void init(String dirtyPath) { 187 // Cache the path and the absolute path. 188 // We can't call isAbsolute() here (http://b/2486943). 189 String cleanPath = fixSlashes(dirtyPath); 190 boolean isAbsolute = cleanPath.length() > 0 && cleanPath.charAt(0) == separatorChar; 191 if (isAbsolute) { 192 this.path = this.absolutePath = cleanPath; 193 } else { 194 String userDir = AccessController.doPrivileged(new PriviAction<String>("user.dir")); 195 this.absolutePath = cleanPath.isEmpty() ? userDir : join(userDir, cleanPath); 196 // We want path to be equal to cleanPath, but we'd like to reuse absolutePath's char[]. 197 this.path = absolutePath.substring(absolutePath.length() - cleanPath.length()); 198 } 199 } 200 201 // Removes duplicate adjacent slashes and any trailing slash. fixSlashes(String origPath)202 private String fixSlashes(String origPath) { 203 // Remove duplicate adjacent slashes. 204 boolean lastWasSlash = false; 205 char[] newPath = origPath.toCharArray(); 206 int length = newPath.length; 207 int newLength = 0; 208 for (int i = 0; i < length; ++i) { 209 char ch = newPath[i]; 210 if (ch == '/') { 211 if (!lastWasSlash) { 212 newPath[newLength++] = separatorChar; 213 lastWasSlash = true; 214 } 215 } else { 216 newPath[newLength++] = ch; 217 lastWasSlash = false; 218 } 219 } 220 // Remove any trailing slash (unless this is the root of the file system). 221 if (lastWasSlash && newLength > 1) { 222 newLength--; 223 } 224 // Reuse the original string if possible. 225 return (newLength != length) ? new String(newPath, 0, newLength) : origPath; 226 } 227 228 // Joins two path components, adding a separator only if necessary. join(String prefix, String suffix)229 private String join(String prefix, String suffix) { 230 int prefixLength = prefix.length(); 231 boolean haveSlash = (prefixLength > 0 && prefix.charAt(prefixLength - 1) == separatorChar); 232 if (!haveSlash) { 233 haveSlash = (suffix.length() > 0 && suffix.charAt(0) == separatorChar); 234 } 235 return haveSlash ? (prefix + suffix) : (prefix + separatorChar + suffix); 236 } 237 checkURI(URI uri)238 private void checkURI(URI uri) { 239 if (!uri.isAbsolute()) { 240 throw new IllegalArgumentException("URI is not absolute: " + uri); 241 } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) { 242 throw new IllegalArgumentException("URI is not hierarchical: " + uri); 243 } 244 if (!"file".equals(uri.getScheme())) { 245 throw new IllegalArgumentException("Expected file scheme in URI: " + uri); 246 } 247 String rawPath = uri.getRawPath(); 248 if (rawPath == null || rawPath.isEmpty()) { 249 throw new IllegalArgumentException("Expected non-empty path in URI: " + uri); 250 } 251 if (uri.getRawAuthority() != null) { 252 throw new IllegalArgumentException("Found authority in URI: " + uri); 253 } 254 if (uri.getRawQuery() != null) { 255 throw new IllegalArgumentException("Found query in URI: " + uri); 256 } 257 if (uri.getRawFragment() != null) { 258 throw new IllegalArgumentException("Found fragment in URI: " + uri); 259 } 260 } 261 262 /** 263 * Lists the file system roots. The Java platform may support zero or more 264 * file systems, each with its own platform-dependent root. Further, the 265 * canonical pathname of any file on the system will always begin with one 266 * of the returned file system roots. 267 * 268 * @return the array of file system roots. 269 */ listRoots()270 public static File[] listRoots() { 271 return new File[] { new File("/") }; 272 } 273 274 /** 275 * Tests whether or not this process is allowed to execute this file. 276 * Note that this is a best-effort result; the only way to be certain is 277 * to actually attempt the operation. 278 * 279 * @return {@code true} if this file can be executed, {@code false} otherwise. 280 * @throws SecurityException 281 * If a security manager exists and 282 * SecurityManager.checkExec(java.lang.String) disallows read 283 * permission to this file object 284 * @see java.lang.SecurityManager#checkExec(String) 285 * 286 * @since 1.6 287 */ canExecute()288 public boolean canExecute() { 289 if (path.isEmpty()) { 290 return false; 291 } 292 SecurityManager security = System.getSecurityManager(); 293 if (security != null) { 294 security.checkExec(path); // Seems bogus, but this is what the RI does. 295 } 296 return canExecuteImpl(absolutePath); 297 } canExecuteImpl(String path)298 private static native boolean canExecuteImpl(String path); 299 300 /** 301 * Indicates whether the current context is allowed to read from this file. 302 * 303 * @return {@code true} if this file can be read, {@code false} otherwise. 304 * @throws SecurityException 305 * if a {@code SecurityManager} is installed and it denies the 306 * read request. 307 */ canRead()308 public boolean canRead() { 309 if (path.isEmpty()) { 310 return false; 311 } 312 SecurityManager security = System.getSecurityManager(); 313 if (security != null) { 314 security.checkRead(path); 315 } 316 return canReadImpl(absolutePath); 317 } canReadImpl(String path)318 private static native boolean canReadImpl(String path); 319 320 /** 321 * Indicates whether the current context is allowed to write to this file. 322 * 323 * @return {@code true} if this file can be written, {@code false} 324 * otherwise. 325 * @throws SecurityException 326 * if a {@code SecurityManager} is installed and it denies the 327 * write request. 328 */ canWrite()329 public boolean canWrite() { 330 if (path.isEmpty()) { 331 return false; 332 } 333 SecurityManager security = System.getSecurityManager(); 334 if (security != null) { 335 security.checkWrite(path); 336 } 337 return canWriteImpl(absolutePath); 338 } canWriteImpl(String path)339 private static native boolean canWriteImpl(String path); 340 341 /** 342 * Returns the relative sort ordering of the paths for this file and the 343 * file {@code another}. The ordering is platform dependent. 344 * 345 * @param another 346 * a file to compare this file to 347 * @return an int determined by comparing the two paths. Possible values are 348 * described in the Comparable interface. 349 * @see Comparable 350 */ compareTo(File another)351 public int compareTo(File another) { 352 return this.getPath().compareTo(another.getPath()); 353 } 354 355 /** 356 * Deletes this file. Directories must be empty before they will be deleted. 357 * 358 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 359 * Callers must check the return value. 360 * 361 * @return {@code true} if this file was deleted, {@code false} otherwise. 362 * @throws SecurityException 363 * if a {@code SecurityManager} is installed and it denies the 364 * request. 365 * @see java.lang.SecurityManager#checkDelete 366 */ delete()367 public boolean delete() { 368 if (path.isEmpty()) { 369 return false; 370 } 371 SecurityManager security = System.getSecurityManager(); 372 if (security != null) { 373 security.checkDelete(path); 374 } 375 return deleteImpl(absolutePath); 376 } 377 deleteImpl(String path)378 private static native boolean deleteImpl(String path); 379 380 /** 381 * Schedules this file to be automatically deleted once the virtual machine 382 * terminates. This will only happen when the virtual machine terminates 383 * normally as described by the Java Language Specification section 12.9. 384 * 385 * @throws SecurityException 386 * if a {@code SecurityManager} is installed and it denies the 387 * request. 388 */ deleteOnExit()389 public void deleteOnExit() { 390 SecurityManager security = System.getSecurityManager(); 391 if (security != null) { 392 security.checkDelete(path); 393 } 394 DeleteOnExit.getInstance().addFile(getAbsoluteName()); 395 } 396 397 /** 398 * Compares {@code obj} to this file and returns {@code true} if they 399 * represent the <em>same</em> object using a path specific comparison. 400 * 401 * @param obj 402 * the object to compare this file with. 403 * @return {@code true} if {@code obj} is the same as this object, 404 * {@code false} otherwise. 405 */ 406 @Override equals(Object obj)407 public boolean equals(Object obj) { 408 if (!(obj instanceof File)) { 409 return false; 410 } 411 return path.equals(((File) obj).getPath()); 412 } 413 414 /** 415 * Returns a boolean indicating whether this file can be found on the 416 * underlying file system. 417 * 418 * @return {@code true} if this file exists, {@code false} otherwise. 419 * @throws SecurityException 420 * if a {@code SecurityManager} is installed and it denies read 421 * access to this file. 422 * @see #getPath 423 * @see java.lang.SecurityManager#checkRead(FileDescriptor) 424 */ exists()425 public boolean exists() { 426 if (path.isEmpty()) { 427 return false; 428 } 429 SecurityManager security = System.getSecurityManager(); 430 if (security != null) { 431 security.checkRead(path); 432 } 433 return existsImpl(absolutePath); 434 } 435 existsImpl(String path)436 private static native boolean existsImpl(String path); 437 438 /** 439 * Returns the absolute path of this file. 440 * 441 * @return the absolute file path. 442 */ getAbsolutePath()443 public String getAbsolutePath() { 444 return absolutePath; 445 } 446 447 /** 448 * Returns a new file constructed using the absolute path of this file. 449 * 450 * @return a new file from this file's absolute path. 451 * @see java.lang.SecurityManager#checkPropertyAccess 452 */ getAbsoluteFile()453 public File getAbsoluteFile() { 454 return new File(this.getAbsolutePath()); 455 } 456 457 /** 458 * Returns the absolute path of this file with all references resolved. An 459 * <em>absolute</em> path is one that begins at the root of the file 460 * system. The canonical path is one in which all references have been 461 * resolved. For the cases of '..' and '.', where the file system supports 462 * parent and working directory respectively, these are removed and replaced 463 * with a direct directory reference. If the file does not exist, 464 * getCanonicalPath() may not resolve any references and simply returns an 465 * absolute path name or throws an IOException. 466 * 467 * @return the canonical path of this file. 468 * @throws IOException 469 * if an I/O error occurs. 470 */ getCanonicalPath()471 public String getCanonicalPath() throws IOException { 472 // BEGIN android-removed 473 // Caching the canonical path is bogus. Users facing specific 474 // performance problems can perform their own caching, with 475 // eviction strategies that are appropriate for their application. 476 // A VM-wide cache with no mechanism to evict stale elements is a 477 // disservice to applications that need up-to-date data. 478 // String canonPath = FileCanonPathCache.get(absPath); 479 // if (canonPath != null) { 480 // return canonPath; 481 // } 482 // END android-removed 483 484 // TODO: rewrite getCanonicalPath, resolve, and resolveLink. 485 486 String result = absolutePath; 487 if (separatorChar == '/') { 488 // resolve the full path first 489 result = resolveLink(result, result.length(), false); 490 // resolve the parent directories 491 result = resolve(result); 492 } 493 int numSeparators = 1; 494 for (int i = 0; i < result.length(); ++i) { 495 if (result.charAt(i) == separatorChar) { 496 numSeparators++; 497 } 498 } 499 int[] sepLocations = new int[numSeparators]; 500 int rootLoc = 0; 501 if (separatorChar != '/') { 502 if (result.charAt(0) == '\\') { 503 rootLoc = (result.length() > 1 && result.charAt(1) == '\\') ? 1 : 0; 504 } else { 505 rootLoc = 2; // skip drive i.e. c: 506 } 507 } 508 509 char[] newResult = new char[result.length() + 1]; 510 int newLength = 0, lastSlash = 0, foundDots = 0; 511 sepLocations[lastSlash] = rootLoc; 512 for (int i = 0; i <= result.length(); ++i) { 513 if (i < rootLoc) { 514 newResult[newLength++] = result.charAt(i); 515 } else { 516 if (i == result.length() || result.charAt(i) == separatorChar) { 517 if (i == result.length() && foundDots == 0) { 518 break; 519 } 520 if (foundDots == 1) { 521 /* Don't write anything, just reset and continue */ 522 foundDots = 0; 523 continue; 524 } 525 if (foundDots > 1) { 526 /* Go back N levels */ 527 lastSlash = lastSlash > (foundDots - 1) ? lastSlash - (foundDots - 1) : 0; 528 newLength = sepLocations[lastSlash] + 1; 529 foundDots = 0; 530 continue; 531 } 532 sepLocations[++lastSlash] = newLength; 533 newResult[newLength++] = separatorChar; 534 continue; 535 } 536 if (result.charAt(i) == '.') { 537 foundDots++; 538 continue; 539 } 540 /* Found some dots within text, write them out */ 541 if (foundDots > 0) { 542 for (int j = 0; j < foundDots; j++) { 543 newResult[newLength++] = '.'; 544 } 545 } 546 newResult[newLength++] = result.charAt(i); 547 foundDots = 0; 548 } 549 } 550 // remove trailing slash 551 if (newLength > (rootLoc + 1) && newResult[newLength - 1] == separatorChar) { 552 newLength--; 553 } 554 return new String(newResult, 0, newLength); 555 } 556 557 /* 558 * Resolve symbolic links in the parent directories. 559 */ resolve(String path)560 private static String resolve(String path) throws IOException { 561 int last = 1; 562 String linkPath = path; 563 String bytes; 564 boolean done; 565 for (int i = 1; i <= path.length(); i++) { 566 if (i == path.length() || path.charAt(i) == separatorChar) { 567 done = i >= path.length() - 1; 568 // if there is only one segment, do nothing 569 if (done && linkPath.length() == 1) { 570 return path; 571 } 572 boolean inPlace = false; 573 if (linkPath.equals(path)) { 574 bytes = path; 575 // if there are no symbolic links, truncate the path instead of copying 576 if (!done) { 577 inPlace = true; 578 path = path.substring(0, i); 579 } 580 } else { 581 int nextSize = i - last + 1; 582 int linkSize = linkPath.length(); 583 if (linkPath.charAt(linkSize - 1) == separatorChar) { 584 linkSize--; 585 } 586 bytes = linkPath.substring(0, linkSize) + 587 path.substring(last - 1, last - 1 + nextSize); 588 // the full path has already been resolved 589 } 590 if (done) { 591 return bytes; 592 } 593 linkPath = resolveLink(bytes, inPlace ? i : bytes.length(), true); 594 if (inPlace) { 595 // path[i] = '/'; 596 path = path.substring(0, i) + '/' + (i + 1 < path.length() ? path.substring(i + 1) : ""); 597 } 598 last = i + 1; 599 } 600 } 601 throw new InternalError(); 602 } 603 604 /* 605 * Resolve a symbolic link. While the path resolves to an existing path, 606 * keep resolving. If an absolute link is found, resolve the parent 607 * directories if resolveAbsolute is true. 608 */ resolveLink(String path, int length, boolean resolveAbsolute)609 private static String resolveLink(String path, int length, boolean resolveAbsolute) throws IOException { 610 boolean restart = false; 611 do { 612 String fragment = path.substring(0, length); 613 String target = readlink(fragment); 614 if (target.equals(fragment)) { 615 break; 616 } 617 if (target.charAt(0) == separatorChar) { 618 // The link target was an absolute path, so we may need to start again. 619 restart = resolveAbsolute; 620 path = target + path.substring(length); 621 } else { 622 path = path.substring(0, path.lastIndexOf(separatorChar, length - 1) + 1) + target; 623 } 624 length = path.length(); 625 } while (existsImpl(path)); 626 // resolve the parent directories 627 if (restart) { 628 return resolve(path); 629 } 630 return path; 631 } 632 readlink(String filePath)633 private static native String readlink(String filePath); 634 635 /** 636 * Returns a new file created using the canonical path of this file. 637 * Equivalent to {@code new File(this.getCanonicalPath())}. 638 * 639 * @return the new file constructed from this file's canonical path. 640 * @throws IOException 641 * if an I/O error occurs. 642 * @see java.lang.SecurityManager#checkPropertyAccess 643 */ getCanonicalFile()644 public File getCanonicalFile() throws IOException { 645 return new File(getCanonicalPath()); 646 } 647 648 /** 649 * Returns the name of the file or directory represented by this file. 650 * 651 * @return this file's name or an empty string if there is no name part in 652 * the file's path. 653 */ getName()654 public String getName() { 655 int separatorIndex = path.lastIndexOf(separator); 656 return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length()); 657 } 658 659 /** 660 * Returns the pathname of the parent of this file. This is the path up to 661 * but not including the last name. {@code null} is returned if there is no 662 * parent. 663 * 664 * @return this file's parent pathname or {@code null}. 665 */ getParent()666 public String getParent() { 667 int length = path.length(), firstInPath = 0; 668 if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') { 669 firstInPath = 2; 670 } 671 int index = path.lastIndexOf(separatorChar); 672 if (index == -1 && firstInPath > 0) { 673 index = 2; 674 } 675 if (index == -1 || path.charAt(length - 1) == separatorChar) { 676 return null; 677 } 678 if (path.indexOf(separatorChar) == index 679 && path.charAt(firstInPath) == separatorChar) { 680 return path.substring(0, index + 1); 681 } 682 return path.substring(0, index); 683 } 684 685 /** 686 * Returns a new file made from the pathname of the parent of this file. 687 * This is the path up to but not including the last name. {@code null} is 688 * returned when there is no parent. 689 * 690 * @return a new file representing this file's parent or {@code null}. 691 */ getParentFile()692 public File getParentFile() { 693 String tempParent = getParent(); 694 if (tempParent == null) { 695 return null; 696 } 697 return new File(tempParent); 698 } 699 700 /** 701 * Returns the path of this file. 702 * 703 * @return this file's path. 704 */ getPath()705 public String getPath() { 706 return path; 707 } 708 709 /** 710 * Returns an integer hash code for the receiver. Any two objects for which 711 * {@code equals} returns {@code true} must return the same hash code. 712 * 713 * @return this files's hash value. 714 * @see #equals 715 */ 716 @Override hashCode()717 public int hashCode() { 718 return getPath().hashCode() ^ 1234321; 719 } 720 721 /** 722 * Indicates if this file's pathname is absolute. Whether a pathname is 723 * absolute is platform specific. On Android, absolute paths start with 724 * the character '/'. 725 * 726 * @return {@code true} if this file's pathname is absolute, {@code false} 727 * otherwise. 728 * @see #getPath 729 */ isAbsolute()730 public boolean isAbsolute() { 731 return path.length() > 0 && path.charAt(0) == separatorChar; 732 } 733 734 /** 735 * Indicates if this file represents a <em>directory</em> on the 736 * underlying file system. 737 * 738 * @return {@code true} if this file is a directory, {@code false} 739 * otherwise. 740 * @throws SecurityException 741 * if a {@code SecurityManager} is installed and it denies read 742 * access to this file. 743 */ isDirectory()744 public boolean isDirectory() { 745 if (path.isEmpty()) { 746 return false; 747 } 748 SecurityManager security = System.getSecurityManager(); 749 if (security != null) { 750 security.checkRead(path); 751 } 752 return isDirectoryImpl(absolutePath); 753 } 754 isDirectoryImpl(String path)755 private static native boolean isDirectoryImpl(String path); 756 757 /** 758 * Indicates if this file represents a <em>file</em> on the underlying 759 * file system. 760 * 761 * @return {@code true} if this file is a file, {@code false} otherwise. 762 * @throws SecurityException 763 * if a {@code SecurityManager} is installed and it denies read 764 * access to this file. 765 */ isFile()766 public boolean isFile() { 767 if (path.isEmpty()) { 768 return false; 769 } 770 SecurityManager security = System.getSecurityManager(); 771 if (security != null) { 772 security.checkRead(path); 773 } 774 return isFileImpl(absolutePath); 775 } 776 isFileImpl(String path)777 private static native boolean isFileImpl(String path); 778 779 /** 780 * Returns whether or not this file is a hidden file as defined by the 781 * operating system. The notion of "hidden" is system-dependent. For Unix 782 * systems a file is considered hidden if its name starts with a ".". For 783 * Windows systems there is an explicit flag in the file system for this 784 * purpose. 785 * 786 * @return {@code true} if the file is hidden, {@code false} otherwise. 787 * @throws SecurityException 788 * if a {@code SecurityManager} is installed and it denies read 789 * access to this file. 790 */ isHidden()791 public boolean isHidden() { 792 if (path.isEmpty()) { 793 return false; 794 } 795 SecurityManager security = System.getSecurityManager(); 796 if (security != null) { 797 security.checkRead(path); 798 } 799 return getName().startsWith("."); 800 } 801 802 /** 803 * Returns the time when this file was last modified, measured in 804 * milliseconds since January 1st, 1970, midnight. 805 * Returns 0 if the file does not exist. 806 * 807 * @return the time when this file was last modified. 808 * @throws SecurityException 809 * if a {@code SecurityManager} is installed and it denies read 810 * access to this file. 811 */ lastModified()812 public long lastModified() { 813 if (path.isEmpty()) { 814 return 0; 815 } 816 SecurityManager security = System.getSecurityManager(); 817 if (security != null) { 818 security.checkRead(path); 819 } 820 return lastModifiedImpl(absolutePath); 821 } 822 lastModifiedImpl(String path)823 private static native long lastModifiedImpl(String path); 824 825 /** 826 * Sets the time this file was last modified, measured in milliseconds since 827 * January 1st, 1970, midnight. 828 * 829 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 830 * Callers must check the return value. 831 * 832 * @param time 833 * the last modification time for this file. 834 * @return {@code true} if the operation is successful, {@code false} 835 * otherwise. 836 * @throws IllegalArgumentException 837 * if {@code time < 0}. 838 * @throws SecurityException 839 * if a {@code SecurityManager} is installed and it denies write 840 * access to this file. 841 */ setLastModified(long time)842 public boolean setLastModified(long time) { 843 if (path.isEmpty()) { 844 return false; 845 } 846 if (time < 0) { 847 throw new IllegalArgumentException("time < 0"); 848 } 849 SecurityManager security = System.getSecurityManager(); 850 if (security != null) { 851 security.checkWrite(path); 852 } 853 return setLastModifiedImpl(absolutePath, time); 854 } 855 setLastModifiedImpl(String path, long time)856 private static native boolean setLastModifiedImpl(String path, long time); 857 858 /** 859 * Equivalent to setWritable(false, false). 860 * 861 * @see #setWritable(boolean, boolean) 862 */ setReadOnly()863 public boolean setReadOnly() { 864 return setWritable(false, false); 865 } 866 867 /** 868 * Manipulates the execute permissions for the abstract path designated by 869 * this file. 870 * 871 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 872 * Callers must check the return value. 873 * 874 * @param executable 875 * To allow execute permission if true, otherwise disallow 876 * @param ownerOnly 877 * To manipulate execute permission only for owner if true, 878 * otherwise for everyone. The manipulation will apply to 879 * everyone regardless of this value if the underlying system 880 * does not distinguish owner and other users. 881 * @return true if and only if the operation succeeded. If the user does not 882 * have permission to change the access permissions of this abstract 883 * pathname the operation will fail. If the underlying file system 884 * does not support execute permission and the value of executable 885 * is false, this operation will fail. 886 * @throws SecurityException - 887 * If a security manager exists and 888 * SecurityManager.checkWrite(java.lang.String) disallows write 889 * permission to this file object 890 * @since 1.6 891 */ setExecutable(boolean executable, boolean ownerOnly)892 public boolean setExecutable(boolean executable, boolean ownerOnly) { 893 if (path.isEmpty()) { 894 return false; 895 } 896 SecurityManager security = System.getSecurityManager(); 897 if (security != null) { 898 security.checkWrite(path); 899 } 900 return setExecutableImpl(absolutePath, executable, ownerOnly); 901 } 902 903 /** 904 * Equivalent to setExecutable(executable, true). 905 * @see #setExecutable(boolean, boolean) 906 * @since 1.6 907 */ setExecutable(boolean executable)908 public boolean setExecutable(boolean executable) { 909 return setExecutable(executable, true); 910 } 911 setExecutableImpl(String path, boolean executable, boolean ownerOnly)912 private static native boolean setExecutableImpl(String path, boolean executable, boolean ownerOnly); 913 914 /** 915 * Manipulates the read permissions for the abstract path designated by this 916 * file. 917 * 918 * @param readable 919 * To allow read permission if true, otherwise disallow 920 * @param ownerOnly 921 * To manipulate read permission only for owner if true, 922 * otherwise for everyone. The manipulation will apply to 923 * everyone regardless of this value if the underlying system 924 * does not distinguish owner and other users. 925 * @return true if and only if the operation succeeded. If the user does not 926 * have permission to change the access permissions of this abstract 927 * pathname the operation will fail. If the underlying file system 928 * does not support read permission and the value of readable is 929 * false, this operation will fail. 930 * @throws SecurityException - 931 * If a security manager exists and 932 * SecurityManager.checkWrite(java.lang.String) disallows write 933 * permission to this file object 934 * @since 1.6 935 */ setReadable(boolean readable, boolean ownerOnly)936 public boolean setReadable(boolean readable, boolean ownerOnly) { 937 if (path.isEmpty()) { 938 return false; 939 } 940 SecurityManager security = System.getSecurityManager(); 941 if (security != null) { 942 security.checkWrite(path); 943 } 944 return setReadableImpl(absolutePath, readable, ownerOnly); 945 } 946 947 /** 948 * Equivalent to setReadable(readable, true). 949 * @see #setReadable(boolean, boolean) 950 * @since 1.6 951 */ setReadable(boolean readable)952 public boolean setReadable(boolean readable) { 953 return setReadable(readable, true); 954 } 955 setReadableImpl(String path, boolean readable, boolean ownerOnly)956 private static native boolean setReadableImpl(String path, boolean readable, boolean ownerOnly); 957 958 /** 959 * Manipulates the write permissions for the abstract path designated by this 960 * file. 961 * 962 * @param writable 963 * To allow write permission if true, otherwise disallow 964 * @param ownerOnly 965 * To manipulate write permission only for owner if true, 966 * otherwise for everyone. The manipulation will apply to 967 * everyone regardless of this value if the underlying system 968 * does not distinguish owner and other users. 969 * @return true if and only if the operation succeeded. If the user does not 970 * have permission to change the access permissions of this abstract 971 * pathname the operation will fail. 972 * @throws SecurityException - 973 * If a security manager exists and 974 * SecurityManager.checkWrite(java.lang.String) disallows write 975 * permission to this file object 976 * @since 1.6 977 */ setWritable(boolean writable, boolean ownerOnly)978 public boolean setWritable(boolean writable, boolean ownerOnly) { 979 if (path.isEmpty()) { 980 return false; 981 } 982 SecurityManager security = System.getSecurityManager(); 983 if (security != null) { 984 security.checkWrite(path); 985 } 986 return setWritableImpl(absolutePath, writable, ownerOnly); 987 } 988 989 /** 990 * Equivalent to setWritable(writable, true). 991 * @see #setWritable(boolean, boolean) 992 * @since 1.6 993 */ setWritable(boolean writable)994 public boolean setWritable(boolean writable) { 995 return setWritable(writable, true); 996 } 997 setWritableImpl(String path, boolean writable, boolean ownerOnly)998 private static native boolean setWritableImpl(String path, boolean writable, boolean ownerOnly); 999 1000 /** 1001 * Returns the length of this file in bytes. 1002 * Returns 0 if the file does not exist. 1003 * The result for a directory is not defined. 1004 * 1005 * @return the number of bytes in this file. 1006 * @throws SecurityException 1007 * if a {@code SecurityManager} is installed and it denies read 1008 * access to this file. 1009 */ length()1010 public long length() { 1011 SecurityManager security = System.getSecurityManager(); 1012 if (security != null) { 1013 security.checkRead(path); 1014 } 1015 return lengthImpl(absolutePath); 1016 } 1017 lengthImpl(String path)1018 private static native long lengthImpl(String path); 1019 1020 /** 1021 * Returns an array of strings with the file names in the directory 1022 * represented by this file. The result is {@code null} if this file is not 1023 * a directory. 1024 * <p> 1025 * The entries {@code .} and {@code ..} representing the current and parent 1026 * directory are not returned as part of the list. 1027 * 1028 * @return an array of strings with file names or {@code null}. 1029 * @throws SecurityException 1030 * if a {@code SecurityManager} is installed and it denies read 1031 * access to this file. 1032 * @see #isDirectory 1033 * @see java.lang.SecurityManager#checkRead(FileDescriptor) 1034 */ list()1035 public String[] list() { 1036 SecurityManager security = System.getSecurityManager(); 1037 if (security != null) { 1038 security.checkRead(path); 1039 } 1040 if (path.isEmpty()) { 1041 return null; 1042 } 1043 return listImpl(absolutePath); 1044 } 1045 listImpl(String path)1046 private static native String[] listImpl(String path); 1047 1048 /** 1049 * Gets a list of the files in the directory represented by this file. This 1050 * list is then filtered through a FilenameFilter and the names of files 1051 * with matching names are returned as an array of strings. Returns 1052 * {@code null} if this file is not a directory. If {@code filter} is 1053 * {@code null} then all filenames match. 1054 * <p> 1055 * The entries {@code .} and {@code ..} representing the current and parent 1056 * directories are not returned as part of the list. 1057 * 1058 * @param filter 1059 * the filter to match names against, may be {@code null}. 1060 * @return an array of files or {@code null}. 1061 * @throws SecurityException 1062 * if a {@code SecurityManager} is installed and it denies read 1063 * access to this file. 1064 * @see #getPath 1065 * @see #isDirectory 1066 * @see java.lang.SecurityManager#checkRead(FileDescriptor) 1067 */ list(FilenameFilter filter)1068 public String[] list(FilenameFilter filter) { 1069 String[] filenames = list(); 1070 if (filter == null || filenames == null) { 1071 return filenames; 1072 } 1073 List<String> result = new ArrayList<String>(filenames.length); 1074 for (String filename : filenames) { 1075 if (filter.accept(this, filename)) { 1076 result.add(filename); 1077 } 1078 } 1079 return result.toArray(new String[result.size()]); 1080 } 1081 1082 /** 1083 * Returns an array of files contained in the directory represented by this 1084 * file. The result is {@code null} if this file is not a directory. The 1085 * paths of the files in the array are absolute if the path of this file is 1086 * absolute, they are relative otherwise. 1087 * 1088 * @return an array of files or {@code null}. 1089 * @throws SecurityException 1090 * if a {@code SecurityManager} is installed and it denies read 1091 * access to this file. 1092 * @see #list 1093 * @see #isDirectory 1094 */ listFiles()1095 public File[] listFiles() { 1096 return filenamesToFiles(list()); 1097 } 1098 1099 /** 1100 * Gets a list of the files in the directory represented by this file. This 1101 * list is then filtered through a FilenameFilter and files with matching 1102 * names are returned as an array of files. Returns {@code null} if this 1103 * file is not a directory. If {@code filter} is {@code null} then all 1104 * filenames match. 1105 * <p> 1106 * The entries {@code .} and {@code ..} representing the current and parent 1107 * directories are not returned as part of the list. 1108 * 1109 * @param filter 1110 * the filter to match names against, may be {@code null}. 1111 * @return an array of files or {@code null}. 1112 * @throws SecurityException 1113 * if a {@code SecurityManager} is installed and it denies read 1114 * access to this file. 1115 * @see #list(FilenameFilter filter) 1116 * @see #getPath 1117 * @see #isDirectory 1118 * @see java.lang.SecurityManager#checkRead(FileDescriptor) 1119 */ listFiles(FilenameFilter filter)1120 public File[] listFiles(FilenameFilter filter) { 1121 return filenamesToFiles(list(filter)); 1122 } 1123 1124 /** 1125 * Gets a list of the files in the directory represented by this file. This 1126 * list is then filtered through a FileFilter and matching files are 1127 * returned as an array of files. Returns {@code null} if this file is not a 1128 * directory. If {@code filter} is {@code null} then all files match. 1129 * <p> 1130 * The entries {@code .} and {@code ..} representing the current and parent 1131 * directories are not returned as part of the list. 1132 * 1133 * @param filter 1134 * the filter to match names against, may be {@code null}. 1135 * @return an array of files or {@code null}. 1136 * @throws SecurityException 1137 * if a {@code SecurityManager} is installed and it denies read 1138 * access to this file. 1139 * @see #getPath 1140 * @see #isDirectory 1141 * @see java.lang.SecurityManager#checkRead(FileDescriptor) 1142 */ listFiles(FileFilter filter)1143 public File[] listFiles(FileFilter filter) { 1144 File[] files = listFiles(); 1145 if (filter == null || files == null) { 1146 return files; 1147 } 1148 List<File> result = new ArrayList<File>(files.length); 1149 for (File file : files) { 1150 if (filter.accept(file)) { 1151 result.add(file); 1152 } 1153 } 1154 return result.toArray(new File[result.size()]); 1155 } 1156 1157 /** 1158 * Converts a String[] containing filenames to a File[]. 1159 * Note that the filenames must not contain slashes. 1160 * This method is to remove duplication in the implementation 1161 * of File.list's overloads. 1162 */ filenamesToFiles(String[] filenames)1163 private File[] filenamesToFiles(String[] filenames) { 1164 if (filenames == null) { 1165 return null; 1166 } 1167 int count = filenames.length; 1168 File[] result = new File[count]; 1169 for (int i = 0; i < count; ++i) { 1170 result[i] = new File(this, filenames[i]); 1171 } 1172 return result; 1173 } 1174 1175 /** 1176 * Creates the directory named by the trailing filename of this file. Does 1177 * not create the complete path required to create this directory. 1178 * 1179 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 1180 * Callers must check the return value. 1181 * 1182 * @return {@code true} if the directory has been created, {@code false} 1183 * otherwise. 1184 * @throws SecurityException 1185 * if a {@code SecurityManager} is installed and it denies write 1186 * access for this file. 1187 * @see #mkdirs 1188 */ mkdir()1189 public boolean mkdir() { 1190 SecurityManager security = System.getSecurityManager(); 1191 if (security != null) { 1192 security.checkWrite(path); 1193 } 1194 return mkdirImpl(absolutePath); 1195 } 1196 mkdirImpl(String path)1197 private static native boolean mkdirImpl(String path); 1198 1199 /** 1200 * Creates the directory named by the trailing filename of this file, 1201 * including the complete directory path required to create this directory. 1202 * 1203 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 1204 * Callers must check the return value. 1205 * 1206 * @return {@code true} if the necessary directories have been created, 1207 * {@code false} if the target directory already exists or one of 1208 * the directories can not be created. 1209 * @throws SecurityException 1210 * if a {@code SecurityManager} is installed and it denies write 1211 * access for this file. 1212 * @see #mkdir 1213 */ mkdirs()1214 public boolean mkdirs() { 1215 /* If the terminal directory already exists, answer false */ 1216 if (exists()) { 1217 return false; 1218 } 1219 1220 /* If the receiver can be created, answer true */ 1221 if (mkdir()) { 1222 return true; 1223 } 1224 1225 String parentDir = getParent(); 1226 /* If there is no parent and we were not created, answer false */ 1227 if (parentDir == null) { 1228 return false; 1229 } 1230 1231 /* Otherwise, try to create a parent directory and then this directory */ 1232 return (new File(parentDir).mkdirs() && mkdir()); 1233 } 1234 1235 /** 1236 * Creates a new, empty file on the file system according to the path 1237 * information stored in this file. 1238 * 1239 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 1240 * Callers must check the return value. 1241 * 1242 * @return {@code true} if the file has been created, {@code false} if it 1243 * already exists. 1244 * @throws IOException if it's not possible to create the file. 1245 * @throws SecurityException 1246 * if a {@code SecurityManager} is installed and it denies write 1247 * access for this file. 1248 */ createNewFile()1249 public boolean createNewFile() throws IOException { 1250 SecurityManager security = System.getSecurityManager(); 1251 if (security != null) { 1252 security.checkWrite(path); 1253 } 1254 if (path.isEmpty()) { 1255 throw new IOException("No such file or directory"); 1256 } 1257 return createNewFileImpl(absolutePath); 1258 } 1259 createNewFileImpl(String path)1260 private static native boolean createNewFileImpl(String path); 1261 1262 /** 1263 * Creates an empty temporary file using the given prefix and suffix as part 1264 * of the file name. If {@code suffix} is null, {@code .tmp} is used. This 1265 * method is a convenience method that calls 1266 * {@link #createTempFile(String, String, File)} with the third argument 1267 * being {@code null}. 1268 * 1269 * @param prefix 1270 * the prefix to the temp file name. 1271 * @param suffix 1272 * the suffix to the temp file name. 1273 * @return the temporary file. 1274 * @throws IOException 1275 * if an error occurs when writing the file. 1276 */ createTempFile(String prefix, String suffix)1277 public static File createTempFile(String prefix, String suffix) throws IOException { 1278 return createTempFile(prefix, suffix, null); 1279 } 1280 1281 /** 1282 * Creates an empty temporary file in the given directory using the given 1283 * prefix and suffix as part of the file name. If {@code suffix} is null, {@code .tmp} is used. 1284 * 1285 * <p>Note that this method does <i>not</i> call {@link #deleteOnExit}. 1286 * 1287 * @param prefix 1288 * the prefix to the temp file name. 1289 * @param suffix 1290 * the suffix to the temp file name. 1291 * @param directory 1292 * the location to which the temp file is to be written, or 1293 * {@code null} for the default location for temporary files, 1294 * which is taken from the "java.io.tmpdir" system property. It 1295 * may be necessary to set this property to an existing, writable 1296 * directory for this method to work properly. 1297 * @return the temporary file. 1298 * @throws IllegalArgumentException 1299 * if the length of {@code prefix} is less than 3. 1300 * @throws IOException 1301 * if an error occurs when writing the file. 1302 */ 1303 @SuppressWarnings("nls") createTempFile(String prefix, String suffix, File directory)1304 public static File createTempFile(String prefix, String suffix, 1305 File directory) throws IOException { 1306 // Force a prefix null check first 1307 if (prefix.length() < 3) { 1308 throw new IllegalArgumentException("prefix must be at least 3 characters"); 1309 } 1310 if (suffix == null) { 1311 suffix = ".tmp"; 1312 } 1313 File tmpDirFile = directory; 1314 if (tmpDirFile == null) { 1315 String tmpDir = AccessController.doPrivileged( 1316 new PriviAction<String>("java.io.tmpdir", ".")); 1317 tmpDirFile = new File(tmpDir); 1318 } 1319 File result; 1320 do { 1321 result = new File(tmpDirFile, prefix + new Random().nextInt() + suffix); 1322 } while (!result.createNewFile()); 1323 return result; 1324 } 1325 1326 /** 1327 * Renames this file to {@code newPath}. This operation is supported for both 1328 * files and directories. 1329 * 1330 * <p>Many failures are possible. Some of the more likely failures include: 1331 * <ul> 1332 * <li>Write permission is required on the directories containing both the source and 1333 * destination paths. 1334 * <li>Search permission is required for all parents of both paths. 1335 * <li>Both paths be on the same mount point. On Android, applications are most likely to hit 1336 * this restriction when attempting to copy between internal storage and an SD card. 1337 * </ul> 1338 * 1339 * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 1340 * Callers must check the return value. 1341 * 1342 * @param newPath the new path. 1343 * @return true on success. 1344 * @throws SecurityException 1345 * if a {@code SecurityManager} is installed and it denies write 1346 * access for this file or {@code newPath}. 1347 */ renameTo(File newPath)1348 public boolean renameTo(File newPath) { 1349 if (path.isEmpty() || newPath.path.isEmpty()) { 1350 return false; 1351 } 1352 SecurityManager security = System.getSecurityManager(); 1353 if (security != null) { 1354 security.checkWrite(path); 1355 security.checkWrite(newPath.path); 1356 } 1357 return renameToImpl(absolutePath, newPath.absolutePath); 1358 } 1359 renameToImpl(String oldPath, String newPath)1360 private static native boolean renameToImpl(String oldPath, String newPath); 1361 1362 /** 1363 * Returns a string containing a concise, human-readable description of this 1364 * file. 1365 * 1366 * @return a printable representation of this file. 1367 */ 1368 @Override toString()1369 public String toString() { 1370 return path; 1371 } 1372 1373 /** 1374 * Returns a Uniform Resource Identifier for this file. The URI is system 1375 * dependent and may not be transferable between different operating / file 1376 * systems. 1377 * 1378 * @return an URI for this file. 1379 */ 1380 @SuppressWarnings("nls") toURI()1381 public URI toURI() { 1382 String name = getAbsoluteName(); 1383 try { 1384 if (!name.startsWith("/")) { 1385 // start with sep. 1386 return new URI("file", null, new StringBuilder( 1387 name.length() + 1).append('/').append(name).toString(), 1388 null, null); 1389 } else if (name.startsWith("//")) { 1390 return new URI("file", "", name, null); // UNC path 1391 } 1392 return new URI("file", null, name, null, null); 1393 } catch (URISyntaxException e) { 1394 // this should never happen 1395 return null; 1396 } 1397 } 1398 1399 /** 1400 * Returns a Uniform Resource Locator for this file. The URL is system 1401 * dependent and may not be transferable between different operating / file 1402 * systems. 1403 * 1404 * @return a URL for this file. 1405 * @throws java.net.MalformedURLException 1406 * if the path cannot be transformed into a URL. 1407 * @deprecated use {@link #toURI} and {@link java.net.URI#toURL} to get 1408 * correct escaping of illegal characters. 1409 */ 1410 @Deprecated 1411 @SuppressWarnings("nls") toURL()1412 public URL toURL() throws java.net.MalformedURLException { 1413 String name = getAbsoluteName(); 1414 if (!name.startsWith("/")) { 1415 // start with sep. 1416 return new URL("file", "", -1, 1417 new StringBuilder(name.length() + 1).append('/').append(name).toString(), null); 1418 } else if (name.startsWith("//")) { 1419 return new URL("file:" + name); // UNC path 1420 } 1421 return new URL("file", "", -1, name, null); 1422 } 1423 getAbsoluteName()1424 private String getAbsoluteName() { 1425 File f = getAbsoluteFile(); 1426 String name = f.getPath(); 1427 1428 if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) { 1429 // Directories must end with a slash 1430 name = new StringBuilder(name.length() + 1).append(name) 1431 .append('/').toString(); 1432 } 1433 if (separatorChar != '/') { // Must convert slashes. 1434 name = name.replace(separatorChar, '/'); 1435 } 1436 return name; 1437 } 1438 writeObject(ObjectOutputStream stream)1439 private void writeObject(ObjectOutputStream stream) throws IOException { 1440 stream.defaultWriteObject(); 1441 stream.writeChar(separatorChar); 1442 } 1443 readObject(ObjectInputStream stream)1444 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 1445 stream.defaultReadObject(); 1446 char inSeparator = stream.readChar(); 1447 init(path.replace(inSeparator, separatorChar)); 1448 } 1449 1450 /** 1451 * Returns the total size in bytes of the partition containing this path. 1452 * Returns 0 if this path does not exist. 1453 * 1454 * @since 1.6 1455 */ getTotalSpace()1456 public long getTotalSpace() { 1457 SecurityManager security = System.getSecurityManager(); 1458 if (security != null) { 1459 security.checkPermission(new RuntimePermission("getFileSystemAttributes")); 1460 } 1461 return getTotalSpaceImpl(absolutePath); 1462 } getTotalSpaceImpl(String path)1463 private static native long getTotalSpaceImpl(String path); 1464 1465 /** 1466 * Returns the number of usable free bytes on the partition containing this path. 1467 * Returns 0 if this path does not exist. 1468 * 1469 * <p>Note that this is likely to be an optimistic over-estimate and should not 1470 * be taken as a guarantee your application can actually write this many bytes. 1471 * On Android (and other Unix-based systems), this method returns the number of free bytes 1472 * available to non-root users, regardless of whether you're actually running as root, 1473 * and regardless of any quota or other restrictions that might apply to the user. 1474 * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.) 1475 * 1476 * @since 1.6 1477 */ getUsableSpace()1478 public long getUsableSpace() { 1479 SecurityManager security = System.getSecurityManager(); 1480 if (security != null) { 1481 security.checkPermission(new RuntimePermission("getFileSystemAttributes")); 1482 } 1483 return getUsableSpaceImpl(absolutePath); 1484 } getUsableSpaceImpl(String path)1485 private static native long getUsableSpaceImpl(String path); 1486 1487 /** 1488 * Returns the number of free bytes on the partition containing this path. 1489 * Returns 0 if this path does not exist. 1490 * 1491 * <p>Note that this is likely to be an optimistic over-estimate and should not 1492 * be taken as a guarantee your application can actually write this many bytes. 1493 * 1494 * @since 1.6 1495 */ getFreeSpace()1496 public long getFreeSpace() { 1497 SecurityManager security = System.getSecurityManager(); 1498 if (security != null) { 1499 security.checkPermission(new RuntimePermission("getFileSystemAttributes")); 1500 } 1501 return getFreeSpaceImpl(absolutePath); 1502 } getFreeSpaceImpl(String path)1503 private static native long getFreeSpaceImpl(String path); 1504 } 1505