1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.io; 28 29 import java.net.URI; 30 import java.net.URL; 31 import java.net.MalformedURLException; 32 import java.net.URISyntaxException; 33 import java.util.List; 34 import java.util.ArrayList; 35 36 /** 37 * An abstract representation of file and directory pathnames. 38 * 39 * <p> User interfaces and operating systems use system-dependent <em>pathname 40 * strings</em> to name files and directories. This class presents an 41 * abstract, system-independent view of hierarchical pathnames. An 42 * <em>abstract pathname</em> has two components: 43 * 44 * <ol> 45 * <li> An optional system-dependent <em>prefix</em> string, 46 * such as a disk-drive specifier, <code>"/"</code> for the UNIX root 47 * directory, or <code>"\\\\"</code> for a Microsoft Windows UNC pathname, and 48 * <li> A sequence of zero or more string <em>names</em>. 49 * </ol> 50 * 51 * The first name in an abstract pathname may be a directory name or, in the 52 * case of Microsoft Windows UNC pathnames, a hostname. Each subsequent name 53 * in an abstract pathname denotes a directory; the last name may denote 54 * either a directory or a file. The <em>empty</em> abstract pathname has no 55 * prefix and an empty name sequence. 56 * 57 * <p> The conversion of a pathname string to or from an abstract pathname is 58 * inherently system-dependent. When an abstract pathname is converted into a 59 * pathname string, each name is separated from the next by a single copy of 60 * the default <em>separator character</em>. The default name-separator 61 * character is defined by the system property <code>file.separator</code>, and 62 * is made available in the public static fields <code>{@link 63 * #separator}</code> and <code>{@link #separatorChar}</code> of this class. 64 * When a pathname string is converted into an abstract pathname, the names 65 * within it may be separated by the default name-separator character or by any 66 * other name-separator character that is supported by the underlying system. 67 * 68 * <p> A pathname, whether abstract or in string form, may be either 69 * <em>absolute</em> or <em>relative</em>. An absolute pathname is complete in 70 * that no other information is required in order to locate the file that it 71 * denotes. A relative pathname, in contrast, must be interpreted in terms of 72 * information taken from some other pathname. By default the classes in the 73 * <code>java.io</code> package always resolve relative pathnames against the 74 * current user directory. This directory is named by the system property 75 * <code>user.dir</code>, and is typically the directory in which the Java 76 * virtual machine was invoked. 77 * 78 * <p> The <em>parent</em> of an abstract pathname may be obtained by invoking 79 * the {@link #getParent} method of this class and consists of the pathname's 80 * prefix and each name in the pathname's name sequence except for the last. 81 * Each directory's absolute pathname is an ancestor of any <tt>File</tt> 82 * object with an absolute abstract pathname which begins with the directory's 83 * absolute pathname. For example, the directory denoted by the abstract 84 * pathname <tt>"/usr"</tt> is an ancestor of the directory denoted by the 85 * pathname <tt>"/usr/local/bin"</tt>. 86 * 87 * <p> The prefix concept is used to handle root directories on UNIX platforms, 88 * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms, 89 * as follows: 90 * 91 * <ul> 92 * 93 * <li> For UNIX platforms, the prefix of an absolute pathname is always 94 * <code>"/"</code>. Relative pathnames have no prefix. The abstract pathname 95 * denoting the root directory has the prefix <code>"/"</code> and an empty 96 * name sequence. 97 * 98 * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive 99 * specifier consists of the drive letter followed by <code>":"</code> and 100 * possibly followed by <code>"\\"</code> if the pathname is absolute. The 101 * prefix of a UNC pathname is <code>"\\\\"</code>; the hostname and the share 102 * name are the first two names in the name sequence. A relative pathname that 103 * does not specify a drive has no prefix. 104 * 105 * </ul> 106 * 107 * <p> Instances of this class may or may not denote an actual file-system 108 * object such as a file or a directory. If it does denote such an object 109 * then that object resides in a <i>partition</i>. A partition is an 110 * operating system-specific portion of storage for a file system. A single 111 * storage device (e.g. a physical disk-drive, flash memory, CD-ROM) may 112 * contain multiple partitions. The object, if any, will reside on the 113 * partition <a name="partName">named</a> by some ancestor of the absolute 114 * form of this pathname. 115 * 116 * <p> A file system may implement restrictions to certain operations on the 117 * actual file-system object, such as reading, writing, and executing. These 118 * restrictions are collectively known as <i>access permissions</i>. The file 119 * system may have multiple sets of access permissions on a single object. 120 * For example, one set may apply to the object's <i>owner</i>, and another 121 * may apply to all other users. The access permissions on an object may 122 * cause some methods in this class to fail. 123 * 124 * <p> Instances of the <code>File</code> class are immutable; that is, once 125 * created, the abstract pathname represented by a <code>File</code> object 126 * will never change. 127 * 128 * <p>On Android, the underlying filesystem encoding for filenames is always UTF-8. 129 * 130 * @author unascribed 131 * @since JDK1.0 132 */ 133 134 public class File 135 implements Serializable, Comparable<File> 136 { 137 138 /** 139 * The FileSystem object representing the platform's local file system. 140 */ 141 static private final FileSystem fs = FileSystem.getFileSystem(); 142 143 /** 144 * This abstract pathname's normalized pathname string. A normalized 145 * pathname string uses the default name-separator character and does not 146 * contain any duplicate or redundant separators. 147 * 148 * @serial 149 */ 150 private String path; 151 152 /** 153 * Enum type that indicates the status of a file path. 154 */ 155 private static enum PathStatus { INVALID, CHECKED }; 156 157 /** 158 * The flag indicating whether the file path is invalid. 159 */ 160 private transient PathStatus status = null; 161 162 /** 163 * Check if the file has an invalid path. Currently, the inspection of 164 * a file path is very limited, and it only covers Nul character check. 165 * Returning true means the path is definitely invalid/garbage. But 166 * returning false does not guarantee that the path is valid. 167 * 168 * @return true if the file path is invalid. 169 */ isInvalid()170 final boolean isInvalid() { 171 if (status == null) { 172 status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED 173 : PathStatus.INVALID; 174 } 175 return status == PathStatus.INVALID; 176 } 177 178 /** 179 * The length of this abstract pathname's prefix, or zero if it has no 180 * prefix. 181 */ 182 private transient int prefixLength; 183 184 /** 185 * Returns the length of this abstract pathname's prefix. 186 * For use by FileSystem classes. 187 */ getPrefixLength()188 int getPrefixLength() { 189 return prefixLength; 190 } 191 192 /** 193 * The system-dependent default name-separator character. This field is 194 * initialized to contain the first character of the value of the system 195 * property <code>file.separator</code>. On UNIX systems the value of this 196 * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\\'</code>. 197 * 198 * @see java.lang.System#getProperty(java.lang.String) 199 */ 200 public static final char separatorChar = fs.getSeparator(); 201 202 /** 203 * The system-dependent default name-separator character, represented as a 204 * string for convenience. This string contains a single character, namely 205 * <code>{@link #separatorChar}</code>. 206 */ 207 public static final String separator = "" + separatorChar; 208 209 /** 210 * The system-dependent path-separator character. This field is 211 * initialized to contain the first character of the value of the system 212 * property <code>path.separator</code>. This character is used to 213 * separate filenames in a sequence of files given as a <em>path list</em>. 214 * On UNIX systems, this character is <code>':'</code>; on Microsoft Windows systems it 215 * is <code>';'</code>. 216 * 217 * @see java.lang.System#getProperty(java.lang.String) 218 */ 219 public static final char pathSeparatorChar = fs.getPathSeparator(); 220 221 /** 222 * The system-dependent path-separator character, represented as a string 223 * for convenience. This string contains a single character, namely 224 * <code>{@link #pathSeparatorChar}</code>. 225 */ 226 public static final String pathSeparator = "" + pathSeparatorChar; 227 228 229 /* -- Constructors -- */ 230 231 /** 232 * Internal constructor for already-normalized pathname strings. 233 */ File(String pathname, int prefixLength)234 private File(String pathname, int prefixLength) { 235 this.path = pathname; 236 this.prefixLength = prefixLength; 237 } 238 239 /** 240 * Internal constructor for already-normalized pathname strings. 241 * The parameter order is used to disambiguate this method from the 242 * public(File, String) constructor. 243 */ File(String child, File parent)244 private File(String child, File parent) { 245 assert parent.path != null; 246 assert (!parent.path.equals("")); 247 this.path = fs.resolve(parent.path, child); 248 this.prefixLength = parent.prefixLength; 249 } 250 251 /** 252 * Creates a new <code>File</code> instance by converting the given 253 * pathname string into an abstract pathname. If the given string is 254 * the empty string, then the result is the empty abstract pathname. 255 * 256 * @param pathname A pathname string 257 * @throws NullPointerException 258 * If the <code>pathname</code> argument is <code>null</code> 259 */ File(String pathname)260 public File(String pathname) { 261 if (pathname == null) { 262 throw new NullPointerException(); 263 } 264 this.path = fs.normalize(pathname); 265 this.prefixLength = fs.prefixLength(this.path); 266 } 267 268 /* Note: The two-argument File constructors do not interpret an empty 269 parent abstract pathname as the current user directory. An empty parent 270 instead causes the child to be resolved against the system-dependent 271 directory defined by the FileSystem.getDefaultParent method. On Unix 272 this default is "/", while on Microsoft Windows it is "\\". This is required for 273 compatibility with the original behavior of this class. */ 274 275 /** 276 * Creates a new <code>File</code> instance from a parent pathname string 277 * and a child pathname string. 278 * 279 * <p> If <code>parent</code> is <code>null</code> then the new 280 * <code>File</code> instance is created as if by invoking the 281 * single-argument <code>File</code> constructor on the given 282 * <code>child</code> pathname string. 283 * 284 * <p> Otherwise the <code>parent</code> pathname string is taken to denote 285 * a directory, and the <code>child</code> pathname string is taken to 286 * denote either a directory or a file. If the <code>child</code> pathname 287 * string is absolute then it is converted into a relative pathname in a 288 * system-dependent way. If <code>parent</code> is the empty string then 289 * the new <code>File</code> instance is created by converting 290 * <code>child</code> into an abstract pathname and resolving the result 291 * against a system-dependent default directory. Otherwise each pathname 292 * string is converted into an abstract pathname and the child abstract 293 * pathname is resolved against the parent. 294 * 295 * @param parent The parent pathname string 296 * @param child The child pathname string 297 * @throws NullPointerException 298 * If <code>child</code> is <code>null</code> 299 */ File(String parent, String child)300 public File(String parent, String child) { 301 if (child == null) { 302 throw new NullPointerException(); 303 } 304 if (parent != null && !parent.isEmpty()) { 305 this.path = fs.resolve(fs.normalize(parent), 306 fs.normalize(child)); 307 } else { 308 this.path = fs.normalize(child); 309 } 310 this.prefixLength = fs.prefixLength(this.path); 311 } 312 313 /** 314 * Creates a new <code>File</code> instance from a parent abstract 315 * pathname and a child pathname string. 316 * 317 * <p> If <code>parent</code> is <code>null</code> then the new 318 * <code>File</code> instance is created as if by invoking the 319 * single-argument <code>File</code> constructor on the given 320 * <code>child</code> pathname string. 321 * 322 * <p> Otherwise the <code>parent</code> abstract pathname is taken to 323 * denote a directory, and the <code>child</code> pathname string is taken 324 * to denote either a directory or a file. If the <code>child</code> 325 * pathname string is absolute then it is converted into a relative 326 * pathname in a system-dependent way. If <code>parent</code> is the empty 327 * abstract pathname then the new <code>File</code> instance is created by 328 * converting <code>child</code> into an abstract pathname and resolving 329 * the result against a system-dependent default directory. Otherwise each 330 * pathname string is converted into an abstract pathname and the child 331 * abstract pathname is resolved against the parent. 332 * 333 * @param parent The parent abstract pathname 334 * @param child The child pathname string 335 * @throws NullPointerException 336 * If <code>child</code> is <code>null</code> 337 */ File(File parent, String child)338 public File(File parent, String child) { 339 if (child == null) { 340 throw new NullPointerException(); 341 } 342 if (parent != null) { 343 if (parent.path.equals("")) { 344 this.path = fs.resolve(fs.getDefaultParent(), 345 fs.normalize(child)); 346 } else { 347 this.path = fs.resolve(parent.path, 348 fs.normalize(child)); 349 } 350 } else { 351 this.path = fs.normalize(child); 352 } 353 this.prefixLength = fs.prefixLength(this.path); 354 } 355 356 /** 357 * Creates a new <tt>File</tt> instance by converting the given 358 * <tt>file:</tt> URI into an abstract pathname. 359 * 360 * <p> The exact form of a <tt>file:</tt> URI is system-dependent, hence 361 * the transformation performed by this constructor is also 362 * system-dependent. 363 * 364 * <p> For a given abstract pathname <i>f</i> it is guaranteed that 365 * 366 * <blockquote><tt> 367 * new File(</tt><i> f</i><tt>.{@link #toURI() toURI}()).equals(</tt><i> f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}()) 368 * </tt></blockquote> 369 * 370 * so long as the original abstract pathname, the URI, and the new abstract 371 * pathname are all created in (possibly different invocations of) the same 372 * Java virtual machine. This relationship typically does not hold, 373 * however, when a <tt>file:</tt> URI that is created in a virtual machine 374 * on one operating system is converted into an abstract pathname in a 375 * virtual machine on a different operating system. 376 * 377 * @param uri 378 * An absolute, hierarchical URI with a scheme equal to 379 * <tt>"file"</tt>, a non-empty path component, and undefined 380 * authority, query, and fragment components 381 * 382 * @throws NullPointerException 383 * If <tt>uri</tt> is <tt>null</tt> 384 * 385 * @throws IllegalArgumentException 386 * If the preconditions on the parameter do not hold 387 * 388 * @see #toURI() 389 * @see java.net.URI 390 * @since 1.4 391 */ File(URI uri)392 public File(URI uri) { 393 394 // Check our many preconditions 395 if (!uri.isAbsolute()) 396 throw new IllegalArgumentException("URI is not absolute"); 397 if (uri.isOpaque()) 398 throw new IllegalArgumentException("URI is not hierarchical"); 399 String scheme = uri.getScheme(); 400 if ((scheme == null) || !scheme.equalsIgnoreCase("file")) 401 throw new IllegalArgumentException("URI scheme is not \"file\""); 402 if (uri.getAuthority() != null) 403 throw new IllegalArgumentException("URI has an authority component"); 404 if (uri.getFragment() != null) 405 throw new IllegalArgumentException("URI has a fragment component"); 406 if (uri.getQuery() != null) 407 throw new IllegalArgumentException("URI has a query component"); 408 String p = uri.getPath(); 409 if (p.equals("")) 410 throw new IllegalArgumentException("URI path component is empty"); 411 412 // Okay, now initialize 413 p = fs.fromURIPath(p); 414 if (File.separatorChar != '/') 415 p = p.replace('/', File.separatorChar); 416 this.path = fs.normalize(p); 417 this.prefixLength = fs.prefixLength(this.path); 418 } 419 420 421 /* -- Path-component accessors -- */ 422 423 /** 424 * Returns the name of the file or directory denoted by this abstract 425 * pathname. This is just the last name in the pathname's name 426 * sequence. If the pathname's name sequence is empty, then the empty 427 * string is returned. 428 * 429 * @return The name of the file or directory denoted by this abstract 430 * pathname, or the empty string if this pathname's name sequence 431 * is empty 432 */ getName()433 public String getName() { 434 int index = path.lastIndexOf(separatorChar); 435 if (index < prefixLength) return path.substring(prefixLength); 436 return path.substring(index + 1); 437 } 438 439 /** 440 * Returns the pathname string of this abstract pathname's parent, or 441 * <code>null</code> if this pathname does not name a parent directory. 442 * 443 * <p> The <em>parent</em> of an abstract pathname consists of the 444 * pathname's prefix, if any, and each name in the pathname's name 445 * sequence except for the last. If the name sequence is empty then 446 * the pathname does not name a parent directory. 447 * 448 * @return The pathname string of the parent directory named by this 449 * abstract pathname, or <code>null</code> if this pathname 450 * does not name a parent 451 */ getParent()452 public String getParent() { 453 int index = path.lastIndexOf(separatorChar); 454 if (index < prefixLength) { 455 if ((prefixLength > 0) && (path.length() > prefixLength)) 456 return path.substring(0, prefixLength); 457 return null; 458 } 459 return path.substring(0, index); 460 } 461 462 /** 463 * Returns the abstract pathname of this abstract pathname's parent, 464 * or <code>null</code> if this pathname does not name a parent 465 * directory. 466 * 467 * <p> The <em>parent</em> of an abstract pathname consists of the 468 * pathname's prefix, if any, and each name in the pathname's name 469 * sequence except for the last. If the name sequence is empty then 470 * the pathname does not name a parent directory. 471 * 472 * @return The abstract pathname of the parent directory named by this 473 * abstract pathname, or <code>null</code> if this pathname 474 * does not name a parent 475 * 476 * @since 1.2 477 */ getParentFile()478 public File getParentFile() { 479 String p = this.getParent(); 480 if (p == null) return null; 481 return new File(p, this.prefixLength); 482 } 483 484 /** 485 * Converts this abstract pathname into a pathname string. The resulting 486 * string uses the {@link #separator default name-separator character} to 487 * separate the names in the name sequence. 488 * 489 * @return The string form of this abstract pathname 490 */ getPath()491 public String getPath() { 492 return path; 493 } 494 495 496 /* -- Path operations -- */ 497 498 /** 499 * Tests whether this abstract pathname is absolute. The definition of 500 * absolute pathname is system dependent. On Android, absolute paths start with 501 * the character '/'. 502 * 503 * @return <code>true</code> if this abstract pathname is absolute, 504 * <code>false</code> otherwise 505 */ isAbsolute()506 public boolean isAbsolute() { 507 return fs.isAbsolute(this); 508 } 509 510 /** 511 * Returns the absolute path of this file. An absolute path is a path that starts at a root 512 * of the file system. On Android, there is only one root: {@code /}. 513 * 514 * <p>A common use for absolute paths is when passing paths to a {@code Process} as 515 * command-line arguments, to remove the requirement implied by relative paths, that the 516 * child must have the same working directory as its parent. 517 * 518 * @return The absolute pathname string denoting the same file or 519 * directory as this abstract pathname 520 * 521 * @see java.io.File#isAbsolute() 522 */ getAbsolutePath()523 public String getAbsolutePath() { 524 return fs.resolve(this); 525 } 526 527 /** 528 * Returns the absolute form of this abstract pathname. Equivalent to 529 * <code>new File(this.{@link #getAbsolutePath})</code>. 530 * 531 * @return The absolute abstract pathname denoting the same file or 532 * directory as this abstract pathname 533 * 534 * @throws SecurityException 535 * If a required system property value cannot be accessed. 536 * 537 * @since 1.2 538 */ getAbsoluteFile()539 public File getAbsoluteFile() { 540 String absPath = getAbsolutePath(); 541 return new File(absPath, fs.prefixLength(absPath)); 542 } 543 544 /** 545 * Returns the canonical pathname string of this abstract pathname. 546 * 547 * <p> A canonical pathname is both absolute and unique. The precise 548 * definition of canonical form is system-dependent. This method first 549 * converts this pathname to absolute form if necessary, as if by invoking the 550 * {@link #getAbsolutePath} method, and then maps it to its unique form in a 551 * system-dependent way. This typically involves removing redundant names 552 * such as <tt>"."</tt> and <tt>".."</tt> from the pathname, resolving 553 * symbolic links (on UNIX platforms), and converting drive letters to a 554 * standard case (on Microsoft Windows platforms). 555 * 556 * <p> Every pathname that denotes an existing file or directory has a 557 * unique canonical form. Every pathname that denotes a nonexistent file 558 * or directory also has a unique canonical form. The canonical form of 559 * the pathname of a nonexistent file or directory may be different from 560 * the canonical form of the same pathname after the file or directory is 561 * created. Similarly, the canonical form of the pathname of an existing 562 * file or directory may be different from the canonical form of the same 563 * pathname after the file or directory is deleted. 564 * 565 * @return The canonical pathname string denoting the same file or 566 * directory as this abstract pathname 567 * 568 * @throws IOException 569 * If an I/O error occurs, which is possible because the 570 * construction of the canonical pathname may require 571 * filesystem queries 572 * 573 * @throws SecurityException 574 * If a required system property value cannot be accessed, or 575 * if a security manager exists and its <code>{@link 576 * java.lang.SecurityManager#checkRead}</code> method denies 577 * read access to the file 578 * 579 * @since JDK1.1 580 * @see Path#toRealPath 581 */ getCanonicalPath()582 public String getCanonicalPath() throws IOException { 583 if (isInvalid()) { 584 throw new IOException("Invalid file path"); 585 } 586 return fs.canonicalize(fs.resolve(this)); 587 } 588 589 /** 590 * Returns the canonical form of this abstract pathname. Equivalent to 591 * <code>new File(this.{@link #getCanonicalPath})</code>. 592 * 593 * @return The canonical pathname string denoting the same file or 594 * directory as this abstract pathname 595 * 596 * @throws IOException 597 * If an I/O error occurs, which is possible because the 598 * construction of the canonical pathname may require 599 * filesystem queries 600 * 601 * @throws SecurityException 602 * If a required system property value cannot be accessed, or 603 * if a security manager exists and its <code>{@link 604 * java.lang.SecurityManager#checkRead}</code> method denies 605 * read access to the file 606 * 607 * @since 1.2 608 * @see Path#toRealPath 609 */ getCanonicalFile()610 public File getCanonicalFile() throws IOException { 611 String canonPath = getCanonicalPath(); 612 return new File(canonPath, fs.prefixLength(canonPath)); 613 } 614 slashify(String path, boolean isDirectory)615 private static String slashify(String path, boolean isDirectory) { 616 String p = path; 617 if (File.separatorChar != '/') 618 p = p.replace(File.separatorChar, '/'); 619 if (!p.startsWith("/")) 620 p = "/" + p; 621 if (!p.endsWith("/") && isDirectory) 622 p = p + "/"; 623 return p; 624 } 625 626 /** 627 * Converts this abstract pathname into a <code>file:</code> URL. The 628 * exact form of the URL is system-dependent. If it can be determined that 629 * the file denoted by this abstract pathname is a directory, then the 630 * resulting URL will end with a slash. 631 * 632 * @return A URL object representing the equivalent file URL 633 * 634 * @throws MalformedURLException 635 * If the path cannot be parsed as a URL 636 * 637 * @see #toURI() 638 * @see java.net.URI 639 * @see java.net.URI#toURL() 640 * @see java.net.URL 641 * @since 1.2 642 * 643 * @deprecated This method does not automatically escape characters that 644 * are illegal in URLs. It is recommended that new code convert an 645 * abstract pathname into a URL by first converting it into a URI, via the 646 * {@link #toURI() toURI} method, and then converting the URI into a URL 647 * via the {@link java.net.URI#toURL() URI.toURL} method. 648 */ 649 @Deprecated toURL()650 public URL toURL() throws MalformedURLException { 651 if (isInvalid()) { 652 throw new MalformedURLException("Invalid file path"); 653 } 654 return new URL("file", "", slashify(getAbsolutePath(), 655 getAbsoluteFile().isDirectory())); 656 } 657 658 /** 659 * Constructs a <tt>file:</tt> URI that represents this abstract pathname. 660 * 661 * <p> The exact form of the URI is system-dependent. If it can be 662 * determined that the file denoted by this abstract pathname is a 663 * directory, then the resulting URI will end with a slash. 664 * 665 * <p> For a given abstract pathname <i>f</i>, it is guaranteed that 666 * 667 * <blockquote><tt> 668 * new {@link #File(java.net.URI) File}(</tt><i> f</i><tt>.toURI()).equals(</tt><i> f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}()) 669 * </tt></blockquote> 670 * 671 * so long as the original abstract pathname, the URI, and the new abstract 672 * pathname are all created in (possibly different invocations of) the same 673 * Java virtual machine. Due to the system-dependent nature of abstract 674 * pathnames, however, this relationship typically does not hold when a 675 * <tt>file:</tt> URI that is created in a virtual machine on one operating 676 * system is converted into an abstract pathname in a virtual machine on a 677 * different operating system. 678 * 679 * <p> Note that when this abstract pathname represents a UNC pathname then 680 * all components of the UNC (including the server name component) are encoded 681 * in the {@code URI} path. The authority component is undefined, meaning 682 * that it is represented as {@code null}. 683 * 684 * @return An absolute, hierarchical URI with a scheme equal to 685 * <tt>"file"</tt>, a path representing this abstract pathname, 686 * and undefined authority, query, and fragment components 687 * @throws SecurityException If a required system property value cannot 688 * be accessed. 689 * 690 * @see #File(java.net.URI) 691 * @see java.net.URI 692 * @see java.net.URI#toURL() 693 * @since 1.4 694 */ toURI()695 public URI toURI() { 696 try { 697 File f = getAbsoluteFile(); 698 String sp = slashify(f.getPath(), f.isDirectory()); 699 if (sp.startsWith("//")) 700 sp = "//" + sp; 701 return new URI("file", null, sp, null); 702 } catch (URISyntaxException x) { 703 throw new Error(x); // Can't happen 704 } 705 } 706 707 708 /* -- Attribute accessors -- */ 709 710 /** 711 * Tests whether the application can read the file denoted by this 712 * abstract pathname. 713 * 714 * @return <code>true</code> if and only if the file specified by this 715 * abstract pathname exists <em>and</em> can be read by the 716 * application; <code>false</code> otherwise 717 * 718 * @throws SecurityException 719 * If a security manager exists and its <code>{@link 720 * java.lang.SecurityManager#checkRead(java.lang.String)}</code> 721 * method denies read access to the file 722 */ canRead()723 public boolean canRead() { 724 SecurityManager security = System.getSecurityManager(); 725 if (security != null) { 726 security.checkRead(path); 727 } 728 if (isInvalid()) { 729 return false; 730 } 731 return fs.checkAccess(this, FileSystem.ACCESS_READ); 732 } 733 734 /** 735 * Tests whether the application can modify the file denoted by this 736 * abstract pathname. 737 * 738 * @return <code>true</code> if and only if the file system actually 739 * contains a file denoted by this abstract pathname <em>and</em> 740 * the application is allowed to write to the file; 741 * <code>false</code> otherwise. 742 * 743 * @throws SecurityException 744 * If a security manager exists and its <code>{@link 745 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 746 * method denies write access to the file 747 */ canWrite()748 public boolean canWrite() { 749 SecurityManager security = System.getSecurityManager(); 750 if (security != null) { 751 security.checkWrite(path); 752 } 753 if (isInvalid()) { 754 return false; 755 } 756 return fs.checkAccess(this, FileSystem.ACCESS_WRITE); 757 } 758 759 /** 760 * Tests whether the file or directory denoted by this abstract pathname 761 * exists. 762 * 763 * @return <code>true</code> if and only if the file or directory denoted 764 * by this abstract pathname exists; <code>false</code> otherwise 765 * 766 * @throws SecurityException 767 * If a security manager exists and its <code>{@link 768 * java.lang.SecurityManager#checkRead(java.lang.String)}</code> 769 * method denies read access to the file or directory 770 */ exists()771 public boolean exists() { 772 SecurityManager security = System.getSecurityManager(); 773 if (security != null) { 774 security.checkRead(path); 775 } 776 if (isInvalid()) { 777 return false; 778 } 779 780 return fs.checkAccess(this, FileSystem.ACCESS_OK); 781 } 782 783 /** 784 * Tests whether the file denoted by this abstract pathname is a 785 * directory. 786 * 787 * @return <code>true</code> if and only if the file denoted by this 788 * abstract pathname exists <em>and</em> is a directory; 789 * <code>false</code> otherwise 790 * 791 * @throws SecurityException 792 * If a security manager exists and its <code>{@link 793 * java.lang.SecurityManager#checkRead(java.lang.String)}</code> 794 * method denies read access to the file 795 */ isDirectory()796 public boolean isDirectory() { 797 SecurityManager security = System.getSecurityManager(); 798 if (security != null) { 799 security.checkRead(path); 800 } 801 if (isInvalid()) { 802 return false; 803 } 804 return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY) 805 != 0); 806 } 807 808 /** 809 * Tests whether the file denoted by this abstract pathname is a normal 810 * file. A file is <em>normal</em> if it is not a directory and, in 811 * addition, satisfies other system-dependent criteria. Any non-directory 812 * file created by a Java application is guaranteed to be a normal file. 813 * 814 * @return <code>true</code> if and only if the file denoted by this 815 * abstract pathname exists <em>and</em> is a normal file; 816 * <code>false</code> otherwise 817 * 818 * @throws SecurityException 819 * If a security manager exists and its <code>{@link 820 * java.lang.SecurityManager#checkRead(java.lang.String)}</code> 821 * method denies read access to the file 822 */ isFile()823 public boolean isFile() { 824 SecurityManager security = System.getSecurityManager(); 825 if (security != null) { 826 security.checkRead(path); 827 } 828 if (isInvalid()) { 829 return false; 830 } 831 return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0); 832 } 833 834 /** 835 * Tests whether the file named by this abstract pathname is a hidden 836 * file. The exact definition of <em>hidden</em> is system-dependent. On 837 * UNIX systems, a file is considered to be hidden if its name begins with 838 * a period character (<code>'.'</code>). On Microsoft Windows systems, a file is 839 * considered to be hidden if it has been marked as such in the filesystem. 840 * 841 * @return <code>true</code> if and only if the file denoted by this 842 * abstract pathname is hidden according to the conventions of the 843 * underlying platform 844 * 845 * @throws SecurityException 846 * If a security manager exists and its <code>{@link 847 * java.lang.SecurityManager#checkRead(java.lang.String)}</code> 848 * method denies read access to the file 849 * 850 * @since 1.2 851 */ isHidden()852 public boolean isHidden() { 853 SecurityManager security = System.getSecurityManager(); 854 if (security != null) { 855 security.checkRead(path); 856 } 857 if (isInvalid()) { 858 return false; 859 } 860 return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0); 861 } 862 863 /** 864 * Returns the time that the file denoted by this abstract pathname was 865 * last modified. 866 * 867 * @return A <code>long</code> value representing the time the file was 868 * last modified, measured in milliseconds since the epoch 869 * (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the 870 * file does not exist or if an I/O error occurs 871 * 872 * @throws SecurityException 873 * If a security manager exists and its <code>{@link 874 * java.lang.SecurityManager#checkRead(java.lang.String)}</code> 875 * method denies read access to the file 876 */ lastModified()877 public long lastModified() { 878 SecurityManager security = System.getSecurityManager(); 879 if (security != null) { 880 security.checkRead(path); 881 } 882 if (isInvalid()) { 883 return 0L; 884 } 885 return fs.getLastModifiedTime(this); 886 } 887 888 /** 889 * Returns the length of the file denoted by this abstract pathname. 890 * The return value is unspecified if this pathname denotes a directory. 891 * 892 * @return The length, in bytes, of the file denoted by this abstract 893 * pathname, or <code>0L</code> if the file does not exist. Some 894 * operating systems may return <code>0L</code> for pathnames 895 * denoting system-dependent entities such as devices or pipes. 896 * 897 * @throws SecurityException 898 * If a security manager exists and its <code>{@link 899 * java.lang.SecurityManager#checkRead(java.lang.String)}</code> 900 * method denies read access to the file 901 */ length()902 public long length() { 903 SecurityManager security = System.getSecurityManager(); 904 if (security != null) { 905 security.checkRead(path); 906 } 907 if (isInvalid()) { 908 return 0L; 909 } 910 return fs.getLength(this); 911 } 912 913 914 /* -- File operations -- */ 915 916 /** 917 * Atomically creates a new, empty file named by this abstract pathname if 918 * and only if a file with this name does not yet exist. The check for the 919 * existence of the file and the creation of the file if it does not exist 920 * are a single operation that is atomic with respect to all other 921 * filesystem activities that might affect the file. 922 * <P> 923 * Note: this method should <i>not</i> be used for file-locking, as 924 * the resulting protocol cannot be made to work reliably. The 925 * {@link java.nio.channels.FileLock FileLock} 926 * facility should be used instead. 927 * 928 * @return <code>true</code> if the named file does not exist and was 929 * successfully created; <code>false</code> if the named file 930 * already exists 931 * 932 * @throws IOException 933 * If an I/O error occurred 934 * 935 * @throws SecurityException 936 * If a security manager exists and its <code>{@link 937 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 938 * method denies write access to the file 939 * 940 * @since 1.2 941 */ createNewFile()942 public boolean createNewFile() throws IOException { 943 SecurityManager security = System.getSecurityManager(); 944 if (security != null) security.checkWrite(path); 945 if (isInvalid()) { 946 throw new IOException("Invalid file path"); 947 } 948 return fs.createFileExclusively(path); 949 } 950 951 /** 952 * Deletes the file or directory denoted by this abstract pathname. If 953 * this pathname denotes a directory, then the directory must be empty in 954 * order to be deleted. 955 * 956 * @return <code>true</code> if and only if the file or directory is 957 * successfully deleted; <code>false</code> otherwise 958 * 959 * @throws SecurityException 960 * If a security manager exists and its <code>{@link 961 * java.lang.SecurityManager#checkDelete}</code> method denies 962 * delete access to the file 963 */ delete()964 public boolean delete() { 965 SecurityManager security = System.getSecurityManager(); 966 if (security != null) { 967 security.checkDelete(path); 968 } 969 if (isInvalid()) { 970 return false; 971 } 972 return fs.delete(this); 973 } 974 975 /** 976 * Requests that the file or directory denoted by this abstract 977 * pathname be deleted when the virtual machine terminates. 978 * Files (or directories) are deleted in the reverse order that 979 * they are registered. Invoking this method to delete a file or 980 * directory that is already registered for deletion has no effect. 981 * Deletion will be attempted only for normal termination of the 982 * virtual machine, as defined by the Java Language Specification. 983 * 984 * <p> Once deletion has been requested, it is not possible to cancel the 985 * request. This method should therefore be used with care. 986 * 987 * <P> 988 * Note: this method should <i>not</i> be used for file-locking, as 989 * the resulting protocol cannot be made to work reliably. The 990 * {@link java.nio.channels.FileLock FileLock} 991 * facility should be used instead. 992 * 993 * <p><i>Note that on Android, the application lifecycle does not include VM termination, 994 * so calling this method will not ensure that files are deleted</i>. Instead, you should 995 * use the most appropriate out of: 996 * <ul> 997 * <li>Use a {@code finally} clause to manually invoke {@link #delete}. 998 * <li>Maintain your own set of files to delete, and process it at an appropriate point 999 * in your application's lifecycle. 1000 * <li>Use the Unix trick of deleting the file as soon as all readers and writers have 1001 * opened it. No new readers/writers will be able to access the file, but all existing 1002 * ones will still have access until the last one closes the file. 1003 * </ul> 1004 * 1005 * @throws SecurityException 1006 * If a security manager exists and its <code>{@link 1007 * java.lang.SecurityManager#checkDelete}</code> method denies 1008 * delete access to the file 1009 * 1010 * @see #delete 1011 * 1012 * @since 1.2 1013 */ deleteOnExit()1014 public void deleteOnExit() { 1015 SecurityManager security = System.getSecurityManager(); 1016 if (security != null) { 1017 security.checkDelete(path); 1018 } 1019 if (isInvalid()) { 1020 return; 1021 } 1022 DeleteOnExitHook.add(path); 1023 } 1024 1025 /** 1026 * Returns an array of strings naming the files and directories in the 1027 * directory denoted by this abstract pathname. 1028 * 1029 * <p> If this abstract pathname does not denote a directory, then this 1030 * method returns {@code null}. Otherwise an array of strings is 1031 * returned, one for each file or directory in the directory. Names 1032 * denoting the directory itself and the directory's parent directory are 1033 * not included in the result. Each string is a file name rather than a 1034 * complete path. 1035 * 1036 * <p> There is no guarantee that the name strings in the resulting array 1037 * will appear in any specific order; they are not, in particular, 1038 * guaranteed to appear in alphabetical order. 1039 * 1040 * @return An array of strings naming the files and directories in the 1041 * directory denoted by this abstract pathname. The array will be 1042 * empty if the directory is empty. Returns {@code null} if 1043 * this abstract pathname does not denote a directory, or if an 1044 * I/O error occurs. 1045 * 1046 * @throws SecurityException 1047 * If a security manager exists and its {@link 1048 * SecurityManager#checkRead(String)} method denies read access to 1049 * the directory 1050 */ list()1051 public String[] list() { 1052 SecurityManager security = System.getSecurityManager(); 1053 if (security != null) { 1054 security.checkRead(path); 1055 } 1056 if (isInvalid()) { 1057 return null; 1058 } 1059 return fs.list(this); 1060 } 1061 1062 /** 1063 * Returns an array of strings naming the files and directories in the 1064 * directory denoted by this abstract pathname that satisfy the specified 1065 * filter. The behavior of this method is the same as that of the 1066 * {@link #list()} method, except that the strings in the returned array 1067 * must satisfy the filter. If the given {@code filter} is {@code null} 1068 * then all names are accepted. Otherwise, a name satisfies the filter if 1069 * and only if the value {@code true} results when the {@link 1070 * FilenameFilter#accept FilenameFilter.accept(File, String)} method 1071 * of the filter is invoked on this abstract pathname and the name of a 1072 * file or directory in the directory that it denotes. 1073 * 1074 * @param filter 1075 * A filename filter 1076 * 1077 * @return An array of strings naming the files and directories in the 1078 * directory denoted by this abstract pathname that were accepted 1079 * by the given {@code filter}. The array will be empty if the 1080 * directory is empty or if no names were accepted by the filter. 1081 * Returns {@code null} if this abstract pathname does not denote 1082 * a directory, or if an I/O error occurs. 1083 * 1084 * @throws SecurityException 1085 * If a security manager exists and its {@link 1086 * SecurityManager#checkRead(String)} method denies read access to 1087 * the directory 1088 * 1089 */ list(FilenameFilter filter)1090 public String[] list(FilenameFilter filter) { 1091 String names[] = list(); 1092 if ((names == null) || (filter == null)) { 1093 return names; 1094 } 1095 List<String> v = new ArrayList<>(); 1096 for (int i = 0 ; i < names.length ; i++) { 1097 if (filter.accept(this, names[i])) { 1098 v.add(names[i]); 1099 } 1100 } 1101 return v.toArray(new String[v.size()]); 1102 } 1103 1104 /** 1105 * Returns an array of abstract pathnames denoting the files in the 1106 * directory denoted by this abstract pathname. 1107 * 1108 * <p> If this abstract pathname does not denote a directory, then this 1109 * method returns {@code null}. Otherwise an array of {@code File} objects 1110 * is returned, one for each file or directory in the directory. Pathnames 1111 * denoting the directory itself and the directory's parent directory are 1112 * not included in the result. Each resulting abstract pathname is 1113 * constructed from this abstract pathname using the {@link #File(File, 1114 * String) File(File, String)} constructor. Therefore if this 1115 * pathname is absolute then each resulting pathname is absolute; if this 1116 * pathname is relative then each resulting pathname will be relative to 1117 * the same directory. 1118 * 1119 * <p> There is no guarantee that the name strings in the resulting array 1120 * will appear in any specific order; they are not, in particular, 1121 * guaranteed to appear in alphabetical order. 1122 * 1123 * @return An array of abstract pathnames denoting the files and 1124 * directories in the directory denoted by this abstract pathname. 1125 * The array will be empty if the directory is empty. Returns 1126 * {@code null} if this abstract pathname does not denote a 1127 * directory, or if an I/O error occurs. 1128 * 1129 * @throws SecurityException 1130 * If a security manager exists and its {@link 1131 * SecurityManager#checkRead(String)} method denies read access to 1132 * the directory 1133 * 1134 * @since 1.2 1135 */ listFiles()1136 public File[] listFiles() { 1137 String[] ss = list(); 1138 if (ss == null) return null; 1139 int n = ss.length; 1140 File[] fs = new File[n]; 1141 for (int i = 0; i < n; i++) { 1142 fs[i] = new File(ss[i], this); 1143 } 1144 return fs; 1145 } 1146 1147 /** 1148 * Returns an array of abstract pathnames denoting the files and 1149 * directories in the directory denoted by this abstract pathname that 1150 * satisfy the specified filter. The behavior of this method is the same 1151 * as that of the {@link #listFiles()} method, except that the pathnames in 1152 * the returned array must satisfy the filter. If the given {@code filter} 1153 * is {@code null} then all pathnames are accepted. Otherwise, a pathname 1154 * satisfies the filter if and only if the value {@code true} results when 1155 * the {@link FilenameFilter#accept 1156 * FilenameFilter.accept(File, String)} method of the filter is 1157 * invoked on this abstract pathname and the name of a file or directory in 1158 * the directory that it denotes. 1159 * 1160 * @param filter 1161 * A filename filter 1162 * 1163 * @return An array of abstract pathnames denoting the files and 1164 * directories in the directory denoted by this abstract pathname. 1165 * The array will be empty if the directory is empty. Returns 1166 * {@code null} if this abstract pathname does not denote a 1167 * directory, or if an I/O error occurs. 1168 * 1169 * @throws SecurityException 1170 * If a security manager exists and its {@link 1171 * SecurityManager#checkRead(String)} method denies read access to 1172 * the directory 1173 * 1174 * @since 1.2 1175 */ listFiles(FilenameFilter filter)1176 public File[] listFiles(FilenameFilter filter) { 1177 String ss[] = list(); 1178 if (ss == null) return null; 1179 ArrayList<File> files = new ArrayList<>(); 1180 for (String s : ss) 1181 if ((filter == null) || filter.accept(this, s)) 1182 files.add(new File(s, this)); 1183 return files.toArray(new File[files.size()]); 1184 } 1185 1186 /** 1187 * Returns an array of abstract pathnames denoting the files and 1188 * directories in the directory denoted by this abstract pathname that 1189 * satisfy the specified filter. The behavior of this method is the same 1190 * as that of the {@link #listFiles()} method, except that the pathnames in 1191 * the returned array must satisfy the filter. If the given {@code filter} 1192 * is {@code null} then all pathnames are accepted. Otherwise, a pathname 1193 * satisfies the filter if and only if the value {@code true} results when 1194 * the {@link FileFilter#accept FileFilter.accept(File)} method of the 1195 * filter is invoked on the pathname. 1196 * 1197 * @param filter 1198 * A file filter 1199 * 1200 * @return An array of abstract pathnames denoting the files and 1201 * directories in the directory denoted by this abstract pathname. 1202 * The array will be empty if the directory is empty. Returns 1203 * {@code null} if this abstract pathname does not denote a 1204 * directory, or if an I/O error occurs. 1205 * 1206 * @throws SecurityException 1207 * If a security manager exists and its {@link 1208 * SecurityManager#checkRead(String)} method denies read access to 1209 * the directory 1210 * 1211 * @since 1.2 1212 */ listFiles(FileFilter filter)1213 public File[] listFiles(FileFilter filter) { 1214 String ss[] = list(); 1215 if (ss == null) return null; 1216 ArrayList<File> files = new ArrayList<>(); 1217 for (String s : ss) { 1218 File f = new File(s, this); 1219 if ((filter == null) || filter.accept(f)) 1220 files.add(f); 1221 } 1222 return files.toArray(new File[files.size()]); 1223 } 1224 1225 /** 1226 * Creates the directory named by this abstract pathname. 1227 * 1228 * @return <code>true</code> if and only if the directory was 1229 * created; <code>false</code> otherwise 1230 * 1231 * @throws SecurityException 1232 * If a security manager exists and its <code>{@link 1233 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1234 * method does not permit the named directory to be created 1235 */ mkdir()1236 public boolean mkdir() { 1237 SecurityManager security = System.getSecurityManager(); 1238 if (security != null) { 1239 security.checkWrite(path); 1240 } 1241 if (isInvalid()) { 1242 return false; 1243 } 1244 return fs.createDirectory(this); 1245 } 1246 1247 /** 1248 * Creates the directory named by this abstract pathname, including any 1249 * necessary but nonexistent parent directories. Note that if this 1250 * operation fails it may have succeeded in creating some of the necessary 1251 * parent directories. 1252 * 1253 * @return <code>true</code> if and only if the directory was created, 1254 * along with all necessary parent directories; <code>false</code> 1255 * otherwise 1256 * 1257 * @throws SecurityException 1258 * If a security manager exists and its <code>{@link 1259 * java.lang.SecurityManager#checkRead(java.lang.String)}</code> 1260 * method does not permit verification of the existence of the 1261 * named directory and all necessary parent directories; or if 1262 * the <code>{@link 1263 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1264 * method does not permit the named directory and all necessary 1265 * parent directories to be created 1266 */ mkdirs()1267 public boolean mkdirs() { 1268 if (exists()) { 1269 return false; 1270 } 1271 if (mkdir()) { 1272 return true; 1273 } 1274 File canonFile = null; 1275 try { 1276 canonFile = getCanonicalFile(); 1277 } catch (IOException e) { 1278 return false; 1279 } 1280 1281 File parent = canonFile.getParentFile(); 1282 return (parent != null && (parent.mkdirs() || parent.exists()) && 1283 canonFile.mkdir()); 1284 } 1285 1286 /** 1287 * Renames the file denoted by this abstract pathname. 1288 * 1289 * <p>Many failures are possible. Some of the more likely failures include: 1290 * <ul> 1291 * <li>Write permission is required on the directories containing both the source and 1292 * destination paths. 1293 * <li>Search permission is required for all parents of both paths. 1294 * <li>Both paths be on the same mount point. On Android, applications are most likely to hit 1295 * this restriction when attempting to copy between internal storage and an SD card. 1296 * </ul> 1297 * 1298 * <p>The return value should always be checked to make sure 1299 * that the rename operation was successful. 1300 * 1301 * @param dest The new abstract pathname for the named file 1302 * 1303 * @return <code>true</code> if and only if the renaming succeeded; 1304 * <code>false</code> otherwise 1305 * 1306 * @throws SecurityException 1307 * If a security manager exists and its <code>{@link 1308 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1309 * method denies write access to either the old or new pathnames 1310 * 1311 * @throws NullPointerException 1312 * If parameter <code>dest</code> is <code>null</code> 1313 */ renameTo(File dest)1314 public boolean renameTo(File dest) { 1315 SecurityManager security = System.getSecurityManager(); 1316 if (security != null) { 1317 security.checkWrite(path); 1318 security.checkWrite(dest.path); 1319 } 1320 if (dest == null) { 1321 throw new NullPointerException(); 1322 } 1323 if (this.isInvalid() || dest.isInvalid()) { 1324 return false; 1325 } 1326 return fs.rename(this, dest); 1327 } 1328 1329 /** 1330 * Sets the last-modified time of the file or directory named by this 1331 * abstract pathname. 1332 * 1333 * <p> All platforms support file-modification times to the nearest second, 1334 * but some provide more precision. The argument will be truncated to fit 1335 * the supported precision. If the operation succeeds and no intervening 1336 * operations on the file take place, then the next invocation of the 1337 * <code>{@link #lastModified}</code> method will return the (possibly 1338 * truncated) <code>time</code> argument that was passed to this method. 1339 * 1340 * @param time The new last-modified time, measured in milliseconds since 1341 * the epoch (00:00:00 GMT, January 1, 1970) 1342 * 1343 * @return <code>true</code> if and only if the operation succeeded; 1344 * <code>false</code> otherwise 1345 * 1346 * @throws IllegalArgumentException If the argument is negative 1347 * 1348 * @throws SecurityException 1349 * If a security manager exists and its <code>{@link 1350 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1351 * method denies write access to the named file 1352 * 1353 * @since 1.2 1354 */ setLastModified(long time)1355 public boolean setLastModified(long time) { 1356 if (time < 0) throw new IllegalArgumentException("Negative time"); 1357 SecurityManager security = System.getSecurityManager(); 1358 if (security != null) { 1359 security.checkWrite(path); 1360 } 1361 if (isInvalid()) { 1362 return false; 1363 } 1364 return fs.setLastModifiedTime(this, time); 1365 } 1366 1367 /** 1368 * Marks the file or directory named by this abstract pathname so that 1369 * only read operations are allowed. After invoking this method the file 1370 * or directory is guaranteed not to change until it is either deleted or 1371 * marked to allow write access. Whether or not a read-only file or 1372 * directory may be deleted depends upon the underlying system. 1373 * 1374 * @return <code>true</code> if and only if the operation succeeded; 1375 * <code>false</code> otherwise 1376 * 1377 * @throws SecurityException 1378 * If a security manager exists and its <code>{@link 1379 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1380 * method denies write access to the named file 1381 * 1382 * @since 1.2 1383 */ setReadOnly()1384 public boolean setReadOnly() { 1385 SecurityManager security = System.getSecurityManager(); 1386 if (security != null) { 1387 security.checkWrite(path); 1388 } 1389 if (isInvalid()) { 1390 return false; 1391 } 1392 return fs.setReadOnly(this); 1393 } 1394 1395 /** 1396 * Sets the owner's or everybody's write permission for this abstract 1397 * pathname. 1398 * 1399 * @param writable 1400 * If <code>true</code>, sets the access permission to allow write 1401 * operations; if <code>false</code> to disallow write operations 1402 * 1403 * @param ownerOnly 1404 * If <code>true</code>, the write permission applies only to the 1405 * owner's write permission; otherwise, it applies to everybody. If 1406 * the underlying file system can not distinguish the owner's write 1407 * permission from that of others, then the permission will apply to 1408 * everybody, regardless of this value. 1409 * 1410 * @return <code>true</code> if and only if the operation succeeded. The 1411 * operation will fail if the user does not have permission to change 1412 * the access permissions of this abstract pathname. 1413 * 1414 * @throws SecurityException 1415 * If a security manager exists and its <code>{@link 1416 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1417 * method denies write access to the named file 1418 * 1419 * @since 1.6 1420 */ setWritable(boolean writable, boolean ownerOnly)1421 public boolean setWritable(boolean writable, boolean ownerOnly) { 1422 SecurityManager security = System.getSecurityManager(); 1423 if (security != null) { 1424 security.checkWrite(path); 1425 } 1426 if (isInvalid()) { 1427 return false; 1428 } 1429 return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly); 1430 } 1431 1432 /** 1433 * A convenience method to set the owner's write permission for this abstract 1434 * pathname. 1435 * 1436 * <p> An invocation of this method of the form <tt>file.setWritable(arg)</tt> 1437 * behaves in exactly the same way as the invocation 1438 * 1439 * <pre> 1440 * file.setWritable(arg, true) </pre> 1441 * 1442 * @param writable 1443 * If <code>true</code>, sets the access permission to allow write 1444 * operations; if <code>false</code> to disallow write operations 1445 * 1446 * @return <code>true</code> if and only if the operation succeeded. The 1447 * operation will fail if the user does not have permission to 1448 * change the access permissions of this abstract pathname. 1449 * 1450 * @throws SecurityException 1451 * If a security manager exists and its <code>{@link 1452 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1453 * method denies write access to the file 1454 * 1455 * @since 1.6 1456 */ setWritable(boolean writable)1457 public boolean setWritable(boolean writable) { 1458 return setWritable(writable, true); 1459 } 1460 1461 /** 1462 * Sets the owner's or everybody's read permission for this abstract 1463 * pathname. 1464 * 1465 * @param readable 1466 * If <code>true</code>, sets the access permission to allow read 1467 * operations; if <code>false</code> to disallow read operations 1468 * 1469 * @param ownerOnly 1470 * If <code>true</code>, the read permission applies only to the 1471 * owner's read permission; otherwise, it applies to everybody. If 1472 * the underlying file system can not distinguish the owner's read 1473 * permission from that of others, then the permission will apply to 1474 * everybody, regardless of this value. 1475 * 1476 * @return <code>true</code> if and only if the operation succeeded. The 1477 * operation will fail if the user does not have permission to 1478 * change the access permissions of this abstract pathname. If 1479 * <code>readable</code> is <code>false</code> and the underlying 1480 * file system does not implement a read permission, then the 1481 * operation will fail. 1482 * 1483 * @throws SecurityException 1484 * If a security manager exists and its <code>{@link 1485 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1486 * method denies write access to the file 1487 * 1488 * @since 1.6 1489 */ setReadable(boolean readable, boolean ownerOnly)1490 public boolean setReadable(boolean readable, boolean ownerOnly) { 1491 SecurityManager security = System.getSecurityManager(); 1492 if (security != null) { 1493 security.checkWrite(path); 1494 } 1495 if (isInvalid()) { 1496 return false; 1497 } 1498 return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly); 1499 } 1500 1501 /** 1502 * A convenience method to set the owner's read permission for this abstract 1503 * pathname. 1504 * 1505 * <p>An invocation of this method of the form <tt>file.setReadable(arg)</tt> 1506 * behaves in exactly the same way as the invocation 1507 * 1508 * <pre> 1509 * file.setReadable(arg, true) </pre> 1510 * 1511 * @param readable 1512 * If <code>true</code>, sets the access permission to allow read 1513 * operations; if <code>false</code> to disallow read operations 1514 * 1515 * @return <code>true</code> if and only if the operation succeeded. The 1516 * operation will fail if the user does not have permission to 1517 * change the access permissions of this abstract pathname. If 1518 * <code>readable</code> is <code>false</code> and the underlying 1519 * file system does not implement a read permission, then the 1520 * operation will fail. 1521 * 1522 * @throws SecurityException 1523 * If a security manager exists and its <code>{@link 1524 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1525 * method denies write access to the file 1526 * 1527 * @since 1.6 1528 */ setReadable(boolean readable)1529 public boolean setReadable(boolean readable) { 1530 return setReadable(readable, true); 1531 } 1532 1533 /** 1534 * Sets the owner's or everybody's execute permission for this abstract 1535 * pathname. 1536 * 1537 * @param executable 1538 * If <code>true</code>, sets the access permission to allow execute 1539 * operations; if <code>false</code> to disallow execute operations 1540 * 1541 * @param ownerOnly 1542 * If <code>true</code>, the execute permission applies only to the 1543 * owner's execute permission; otherwise, it applies to everybody. 1544 * If the underlying file system can not distinguish the owner's 1545 * execute permission from that of others, then the permission will 1546 * apply to everybody, regardless of this value. 1547 * 1548 * @return <code>true</code> if and only if the operation succeeded. The 1549 * operation will fail if the user does not have permission to 1550 * change the access permissions of this abstract pathname. If 1551 * <code>executable</code> is <code>false</code> and the underlying 1552 * file system does not implement an execute permission, then the 1553 * operation will fail. 1554 * 1555 * @throws SecurityException 1556 * If a security manager exists and its <code>{@link 1557 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1558 * method denies write access to the file 1559 * 1560 * @since 1.6 1561 */ setExecutable(boolean executable, boolean ownerOnly)1562 public boolean setExecutable(boolean executable, boolean ownerOnly) { 1563 SecurityManager security = System.getSecurityManager(); 1564 if (security != null) { 1565 security.checkWrite(path); 1566 } 1567 if (isInvalid()) { 1568 return false; 1569 } 1570 return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly); 1571 } 1572 1573 /** 1574 * A convenience method to set the owner's execute permission for this abstract 1575 * pathname. 1576 * 1577 * <p>An invocation of this method of the form <tt>file.setExcutable(arg)</tt> 1578 * behaves in exactly the same way as the invocation 1579 * 1580 * <pre> 1581 * file.setExecutable(arg, true) </pre> 1582 * 1583 * @param executable 1584 * If <code>true</code>, sets the access permission to allow execute 1585 * operations; if <code>false</code> to disallow execute operations 1586 * 1587 * @return <code>true</code> if and only if the operation succeeded. The 1588 * operation will fail if the user does not have permission to 1589 * change the access permissions of this abstract pathname. If 1590 * <code>executable</code> is <code>false</code> and the underlying 1591 * file system does not implement an excute permission, then the 1592 * operation will fail. 1593 * 1594 * @throws SecurityException 1595 * If a security manager exists and its <code>{@link 1596 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1597 * method denies write access to the file 1598 * 1599 * @since 1.6 1600 */ setExecutable(boolean executable)1601 public boolean setExecutable(boolean executable) { 1602 return setExecutable(executable, true); 1603 } 1604 1605 /** 1606 * Tests whether the application can execute the file denoted by this 1607 * abstract pathname. 1608 * 1609 * @return <code>true</code> if and only if the abstract pathname exists 1610 * <em>and</em> the application is allowed to execute the file 1611 * 1612 * @throws SecurityException 1613 * If a security manager exists and its <code>{@link 1614 * java.lang.SecurityManager#checkExec(java.lang.String)}</code> 1615 * method denies execute access to the file 1616 * 1617 * @since 1.6 1618 */ canExecute()1619 public boolean canExecute() { 1620 SecurityManager security = System.getSecurityManager(); 1621 if (security != null) { 1622 security.checkExec(path); 1623 } 1624 if (isInvalid()) { 1625 return false; 1626 } 1627 return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE); 1628 } 1629 1630 1631 /* -- Filesystem interface -- */ 1632 1633 1634 /** 1635 * Returns the file system roots. On Android and other Unix systems, there is 1636 * a single root, {@code /}. 1637 */ listRoots()1638 public static File[] listRoots() { 1639 return fs.listRoots(); 1640 } 1641 1642 1643 /* -- Disk usage -- */ 1644 1645 /** 1646 * Returns the size of the partition <a href="#partName">named</a> by this 1647 * abstract pathname. 1648 * 1649 * @return The size, in bytes, of the partition or <tt>0L</tt> if this 1650 * abstract pathname does not name a partition 1651 * 1652 * @throws SecurityException 1653 * If a security manager has been installed and it denies 1654 * {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt> 1655 * or its {@link SecurityManager#checkRead(String)} method denies 1656 * read access to the file named by this abstract pathname 1657 * 1658 * @since 1.6 1659 */ getTotalSpace()1660 public long getTotalSpace() { 1661 SecurityManager sm = System.getSecurityManager(); 1662 if (sm != null) { 1663 sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); 1664 sm.checkRead(path); 1665 } 1666 if (isInvalid()) { 1667 return 0L; 1668 } 1669 return fs.getSpace(this, FileSystem.SPACE_TOTAL); 1670 } 1671 1672 /** 1673 * Returns the number of unallocated bytes in the partition <a 1674 * href="#partName">named</a> by this abstract path name. 1675 * 1676 * <p> The returned number of unallocated bytes is a hint, but not 1677 * a guarantee, that it is possible to use most or any of these 1678 * bytes. The number of unallocated bytes is most likely to be 1679 * accurate immediately after this call. It is likely to be made 1680 * inaccurate by any external I/O operations including those made 1681 * on the system outside of this virtual machine. This method 1682 * makes no guarantee that write operations to this file system 1683 * will succeed. 1684 * 1685 * @return The number of unallocated bytes on the partition or <tt>0L</tt> 1686 * if the abstract pathname does not name a partition. This 1687 * value will be less than or equal to the total file system size 1688 * returned by {@link #getTotalSpace}. 1689 * 1690 * @throws SecurityException 1691 * If a security manager has been installed and it denies 1692 * {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt> 1693 * or its {@link SecurityManager#checkRead(String)} method denies 1694 * read access to the file named by this abstract pathname 1695 * 1696 * @since 1.6 1697 */ getFreeSpace()1698 public long getFreeSpace() { 1699 SecurityManager sm = System.getSecurityManager(); 1700 if (sm != null) { 1701 sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); 1702 sm.checkRead(path); 1703 } 1704 if (isInvalid()) { 1705 return 0L; 1706 } 1707 return fs.getSpace(this, FileSystem.SPACE_FREE); 1708 } 1709 1710 /** 1711 * Returns the number of bytes available to this virtual machine on the 1712 * partition <a href="#partName">named</a> by this abstract pathname. When 1713 * possible, this method checks for write permissions and other operating 1714 * system restrictions and will therefore usually provide a more accurate 1715 * estimate of how much new data can actually be written than {@link 1716 * #getFreeSpace}. 1717 * 1718 * <p> The returned number of available bytes is a hint, but not a 1719 * guarantee, that it is possible to use most or any of these bytes. The 1720 * number of unallocated bytes is most likely to be accurate immediately 1721 * after this call. It is likely to be made inaccurate by any external 1722 * I/O operations including those made on the system outside of this 1723 * virtual machine. This method makes no guarantee that write operations 1724 * to this file system will succeed. 1725 * 1726 * <p> On Android (and other Unix-based systems), this method returns the number of free bytes 1727 * available to non-root users, regardless of whether you're actually running as root, 1728 * and regardless of any quota or other restrictions that might apply to the user. 1729 * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.) 1730 * 1731 * @return The number of available bytes on the partition or <tt>0L</tt> 1732 * if the abstract pathname does not name a partition. On 1733 * systems where this information is not available, this method 1734 * will be equivalent to a call to {@link #getFreeSpace}. 1735 * 1736 * @throws SecurityException 1737 * If a security manager has been installed and it denies 1738 * {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt> 1739 * or its {@link SecurityManager#checkRead(String)} method denies 1740 * read access to the file named by this abstract pathname 1741 * 1742 * @since 1.6 1743 */ getUsableSpace()1744 public long getUsableSpace() { 1745 SecurityManager sm = System.getSecurityManager(); 1746 if (sm != null) { 1747 sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); 1748 sm.checkRead(path); 1749 } 1750 if (isInvalid()) { 1751 return 0L; 1752 } 1753 return fs.getSpace(this, FileSystem.SPACE_USABLE); 1754 } 1755 1756 /* -- Temporary files -- */ 1757 1758 // file name generation generateTempFile(String prefix, String suffix, File dir)1759 private static File generateTempFile(String prefix, String suffix, File dir) 1760 throws IOException 1761 { 1762 // Android-changed: Use Math.randomIntInternal. This (pseudo) random number 1763 // is initialized post-fork 1764 int n = Math.randomIntInternal(); 1765 if (n == Integer.MIN_VALUE) { 1766 n = 0; // corner case 1767 } else { 1768 n = Math.abs(n); 1769 } 1770 String name = prefix + Integer.toString(n) + suffix; 1771 File f = new File(dir, name); 1772 if (!name.equals(f.getName())) 1773 throw new IOException("Unable to create temporary file"); 1774 return f; 1775 } 1776 1777 /** 1778 * <p> Creates a new empty file in the specified directory, using the 1779 * given prefix and suffix strings to generate its name. If this method 1780 * returns successfully then it is guaranteed that: 1781 * 1782 * <ol> 1783 * <li> The file denoted by the returned abstract pathname did not exist 1784 * before this method was invoked, and 1785 * <li> Neither this method nor any of its variants will return the same 1786 * abstract pathname again in the current invocation of the virtual 1787 * machine. 1788 * </ol> 1789 * 1790 * This method provides only part of a temporary-file facility. To arrange 1791 * for a file created by this method to be deleted automatically, use the 1792 * <code>{@link #deleteOnExit}</code> method. 1793 * 1794 * <p> The <code>prefix</code> argument must be at least three characters 1795 * long. It is recommended that the prefix be a short, meaningful string 1796 * such as <code>"hjb"</code> or <code>"mail"</code>. The 1797 * <code>suffix</code> argument may be <code>null</code>, in which case the 1798 * suffix <code>".tmp"</code> will be used. 1799 * 1800 * <p> To create the new file, the prefix and the suffix may first be 1801 * adjusted to fit the limitations of the underlying platform. If the 1802 * prefix is too long then it will be truncated, but its first three 1803 * characters will always be preserved. If the suffix is too long then it 1804 * too will be truncated, but if it begins with a period character 1805 * (<code>'.'</code>) then the period and the first three characters 1806 * following it will always be preserved. Once these adjustments have been 1807 * made the name of the new file will be generated by concatenating the 1808 * prefix, five or more internally-generated characters, and the suffix. 1809 * 1810 * <p> If the <code>directory</code> argument is <code>null</code> then the 1811 * system-dependent default temporary-file directory will be used. The 1812 * default temporary-file directory is specified by the system property 1813 * <code>java.io.tmpdir</code>. On UNIX systems the default value of this 1814 * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on 1815 * Microsoft Windows systems it is typically <code>"C:\\WINNT\\TEMP"</code>. A different 1816 * value may be given to this system property when the Java virtual machine 1817 * is invoked, but programmatic changes to this property are not guaranteed 1818 * to have any effect upon the temporary directory used by this method. 1819 * 1820 * @param prefix The prefix string to be used in generating the file's 1821 * name; must be at least three characters long 1822 * 1823 * @param suffix The suffix string to be used in generating the file's 1824 * name; may be <code>null</code>, in which case the 1825 * suffix <code>".tmp"</code> will be used 1826 * 1827 * @param directory The directory in which the file is to be created, or 1828 * <code>null</code> if the default temporary-file 1829 * directory is to be used 1830 * 1831 * @return An abstract pathname denoting a newly-created empty file 1832 * 1833 * @throws IllegalArgumentException 1834 * If the <code>prefix</code> argument contains fewer than three 1835 * characters 1836 * 1837 * @throws IOException If a file could not be created 1838 * 1839 * @throws SecurityException 1840 * If a security manager exists and its <code>{@link 1841 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1842 * method does not allow a file to be created 1843 * 1844 * @since 1.2 1845 */ createTempFile(String prefix, String suffix, File directory)1846 public static File createTempFile(String prefix, String suffix, 1847 File directory) 1848 throws IOException 1849 { 1850 if (prefix.length() < 3) 1851 throw new IllegalArgumentException("Prefix string too short"); 1852 if (suffix == null) 1853 suffix = ".tmp"; 1854 1855 File tmpdir = (directory != null) ? directory 1856 : new File(System.getProperty("java.io.tmpdir", ".")); 1857 File f; 1858 try { 1859 do { 1860 f = generateTempFile(prefix, suffix, tmpdir); 1861 } while (f.exists()); 1862 if (!f.createNewFile()) 1863 throw new IOException("Unable to create temporary file"); 1864 } catch (SecurityException se) { 1865 // don't reveal temporary directory location 1866 if (directory == null) 1867 throw new SecurityException("Unable to create temporary file"); 1868 throw se; 1869 } 1870 return f; 1871 } 1872 1873 /** 1874 * Creates an empty file in the default temporary-file directory, using 1875 * the given prefix and suffix to generate its name. Invoking this method 1876 * is equivalent to invoking <code>{@link #createTempFile(java.lang.String, 1877 * java.lang.String, java.io.File) 1878 * createTempFile(prefix, suffix, null)}</code>. 1879 * 1880 * @param prefix The prefix string to be used in generating the file's 1881 * name; must be at least three characters long 1882 * 1883 * @param suffix The suffix string to be used in generating the file's 1884 * name; may be <code>null</code>, in which case the 1885 * suffix <code>".tmp"</code> will be used 1886 * 1887 * @return An abstract pathname denoting a newly-created empty file 1888 * 1889 * @throws IllegalArgumentException 1890 * If the <code>prefix</code> argument contains fewer than three 1891 * characters 1892 * 1893 * @throws IOException If a file could not be created 1894 * 1895 * @throws SecurityException 1896 * If a security manager exists and its <code>{@link 1897 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code> 1898 * method does not allow a file to be created 1899 * 1900 * @since 1.2 1901 */ createTempFile(String prefix, String suffix)1902 public static File createTempFile(String prefix, String suffix) 1903 throws IOException 1904 { 1905 return createTempFile(prefix, suffix, null); 1906 } 1907 1908 /* -- Basic infrastructure -- */ 1909 1910 /** 1911 * Compares two abstract pathnames lexicographically. The ordering 1912 * defined by this method depends upon the underlying system. On UNIX 1913 * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows 1914 * systems it is not. 1915 * 1916 * @param pathname The abstract pathname to be compared to this abstract 1917 * pathname 1918 * 1919 * @return Zero if the argument is equal to this abstract pathname, a 1920 * value less than zero if this abstract pathname is 1921 * lexicographically less than the argument, or a value greater 1922 * than zero if this abstract pathname is lexicographically 1923 * greater than the argument 1924 * 1925 * @since 1.2 1926 */ compareTo(File pathname)1927 public int compareTo(File pathname) { 1928 return fs.compare(this, pathname); 1929 } 1930 1931 /** 1932 * Tests this abstract pathname for equality with the given object. 1933 * Returns <code>true</code> if and only if the argument is not 1934 * <code>null</code> and is an abstract pathname that denotes the same file 1935 * or directory as this abstract pathname. Whether or not two abstract 1936 * pathnames are equal depends upon the underlying system. On UNIX 1937 * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows 1938 * systems it is not. 1939 * 1940 * @param obj The object to be compared with this abstract pathname 1941 * 1942 * @return <code>true</code> if and only if the objects are the same; 1943 * <code>false</code> otherwise 1944 */ equals(Object obj)1945 public boolean equals(Object obj) { 1946 if ((obj != null) && (obj instanceof File)) { 1947 return compareTo((File)obj) == 0; 1948 } 1949 return false; 1950 } 1951 1952 /** 1953 * Computes a hash code for this abstract pathname. Because equality of 1954 * abstract pathnames is inherently system-dependent, so is the computation 1955 * of their hash codes. On UNIX systems, the hash code of an abstract 1956 * pathname is equal to the exclusive <em>or</em> of the hash code 1957 * of its pathname string and the decimal value 1958 * <code>1234321</code>. On Microsoft Windows systems, the hash 1959 * code is equal to the exclusive <em>or</em> of the hash code of 1960 * its pathname string converted to lower case and the decimal 1961 * value <code>1234321</code>. Locale is not taken into account on 1962 * lowercasing the pathname string. 1963 * 1964 * @return A hash code for this abstract pathname 1965 */ hashCode()1966 public int hashCode() { 1967 return fs.hashCode(this); 1968 } 1969 1970 /** 1971 * Returns the pathname string of this abstract pathname. This is just the 1972 * string returned by the <code>{@link #getPath}</code> method. 1973 * 1974 * @return The string form of this abstract pathname 1975 */ toString()1976 public String toString() { 1977 return getPath(); 1978 } 1979 1980 /** 1981 * WriteObject is called to save this filename. 1982 * The separator character is saved also so it can be replaced 1983 * in case the path is reconstituted on a different host type. 1984 * <p> 1985 * @serialData Default fields followed by separator character. 1986 */ writeObject(java.io.ObjectOutputStream s)1987 private synchronized void writeObject(java.io.ObjectOutputStream s) 1988 throws IOException 1989 { 1990 s.defaultWriteObject(); 1991 s.writeChar(this.separatorChar); // Add the separator character 1992 } 1993 1994 /** 1995 * readObject is called to restore this filename. 1996 * The original separator character is read. If it is different 1997 * than the separator character on this system, then the old separator 1998 * is replaced by the local separator. 1999 */ readObject(java.io.ObjectInputStream s)2000 private synchronized void readObject(java.io.ObjectInputStream s) 2001 throws IOException, ClassNotFoundException 2002 { 2003 ObjectInputStream.GetField fields = s.readFields(); 2004 String pathField = (String)fields.get("path", null); 2005 char sep = s.readChar(); // read the previous separator char 2006 if (sep != separatorChar) 2007 pathField = pathField.replace(sep, separatorChar); 2008 this.path = fs.normalize(pathField); 2009 this.prefixLength = fs.prefixLength(this.path); 2010 } 2011 2012 /** use serialVersionUID from JDK 1.0.2 for interoperability */ 2013 private static final long serialVersionUID = 301077366599181567L; 2014 } 2015