/* * @(#)FileIO.java 1.12 05/03/12 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package sun.io; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; import java.io.Serializable; /** * Instances of this class represent the name of a file or directory * on the host file system. A file is specified by a pathname, which * can either be an absolute pathname or a pathname relative to the * current working directory. The pathname must follow the naming * conventions of the host platform. * <p> * The <code>File</code> class is intended to provide an abstraction * that deals with most of the machine dependent complexities of * files and pathnames in a machine-independent fashion. * <p> * Note that whenever a filename or path is used it is * assumed that the host's file naming conventions are used. * * @version 1.10, 02/08/19 * @author Saul Wold * @since JDK1.0 */ public abstract class FileIO implements Serializable { /** * The path of the file. The host's file separator is used. */ protected String path; /** * The system-dependent path separator character. This field is * initialized to contain the value of <code>File.separator</code>. * * @see java.io.File#separator(java.lang.String) * @since JDK1.0 */ // Fix for 6292536 and 6292996. public static final String separator = java.io.File.separator; /** * The system-dependent path separator string. This field is * initialized to contain the first character of the value of * <code>File.separator</code>. This character * separates the directory and file components in a filename. * * @see java.io.File#separator(java.lang.String) * @since JDK1.0 */ public static final char separatorChar = separator.charAt(0); /** * The system-dependent path separator string. This field is * initialized to contain the value of <code>File.pathSeparator</code>. * * @see java.io.File#pathSeparator(java.lang.String) * @since JDK1.0 */ // Fix for 6292536 and 6292996. public static final String pathSeparator = java.io.File.pathSeparator; /** * The system-dependent path separator character. This field is * initialized to contain the first character of * <code>File.pathSeparator</code>. This character is * often used to separate filenames in a sequence of files given as a * "path list". * * @see java.io.File#pathSeparator(java.lang.String) * @since JDK1.0 */ public static final char pathSeparatorChar = pathSeparator.charAt(0); public FileIO() {} /** * Creates a <code>File</code> instance that represents the file * whose pathname is the given path argument. * * @param path the file pathname. * @exception NullPointerException if the file path is equal to * <code>null</code>. * @see java.io.File#getPath() * @since JDK1.0 */ protected FileIO(String path) { if (path == null) { throw new NullPointerException(); } this.path = path; } /** * Creates a <code>File</code> instance whose pathname is the * pathname of the specified directory, followed by the separator * character, followed by the <code>name</code> argument. * * @param path the directory pathname. * @param name the file pathname. * @see java.io.File#getPath() * @see java.io.File#separator * @since JDK1.0 */ protected FileIO(String path, String name) { if (name == null) { /* raise exception, per Java Language Spec * 22.24.6 & 22.24.7 */ throw new NullPointerException(); } if (path != null) { if (path.endsWith(separator)) { this.path = path + name; } else { this.path = path + separator + name; } } else { this.path = name; } } /** * Creates a <code>File</code> instance that represents the file * with the specified name in the specified directory. * <p> * If the directory argument is <code>null</code>, the resulting * <code>File</code> instance represents a file in the * (system-dependent) current directory whose pathname is the * <code>name</code> argument. Otherwise, the <code>File</code> * instance represents a file whose pathname is the pathname of the * directory, followed by the separator character, followed by the * <code>name</code> argument. * * @param dir the directory. * @param name the file pathname. * @see java.io.File#getPath() * @see java.io.File#separator * @since JDK1.0 */ protected FileIO(FileIO dir, String name) { this(dir.getPath(), name); } public abstract InputStream getInputStream() throws IOException; public abstract OutputStream getOutputStream() throws IOException; /** * Returns the name of the file represented by this object. The name * is everything in the pathame after the last occurrence of the * separator character. * * @return the name of the file (without any directory components) * represented by this <code>File</code> object. * @see java.io.File#getPath() * @see java.io.File#separator * @since JDK1.0 */ public String getName() { int index = path.lastIndexOf(separatorChar); return (index < 0) ? path : path.substring(index + 1); } /** * Returns the pathname of the file represented by this object. * * @return the pathname represented by this <code>File</code> object. * @since JDK1.0 */ public String getPath() { return path; } /** * Returns the absolute pathname of the file represented by this object. * If this object represents an absolute pathname, then return the * pathname. Otherwise, return a pathname that is a concatenation of * the current user directory, the separator character, and the * pathname of this file object. * <p> * The system property <code>user.dir</code> contains the current * user directory. * * @return a system-dependent absolute pathname for this <code>File</code>. * @see java.io.File#getPath() * @see java.io.File#isAbsolute() * @see java.lang.System#getProperty(java.lang.String) * @since JDK1.0 */ public String getAbsolutePath() { if (isAbsolute()) return path; SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPropertyAccess("user.dir"); } return System.getProperty("user.dir") + separator + path; } /** * Returns the canonical form of this <code>File</code> object's pathname. * The precise definition of canonical form is system-dependent, but it * usually specifies an absolute pathname in which all relative references * and references to the current user directory have been completely * resolved. The canonical form of a pathname of a nonexistent file may * not be defined. * * @exception IOException If an I/O error occurs, which is possible because * the construction of the canonical path may require filesystem queries. * * @since JDK1.1 */ public String getCanonicalPath() throws IOException { if (isAbsolute()) return canonPath(path); SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPropertyAccess("user.dir"); } return canonPath(System.getProperty("user.dir") + separator + path); } /** * Returns the parent part of the pathname of this <code>File</code> * object, or <code>null</code> if the name has no parent part. The parent * part is generally everything leading up to the last occurrence of the * separator character, although the precise definition is system * dependent. On UNIX, for example, the parent part of * <code>"/usr/lib"</code> is <code>"/usr"</code>, whose parent part is * <code>"/"</code>, which in turn has no parent. On Windows platforms, * the parent part of <code>"c:\java"</code> is <code>"c:\"</code>, which * in turn has no parent. * * @see java.io.File#getPath() * @see java.io.File#getCanonicalPath() * @see java.io.File#separator * @since JDK1.0 */ public String getParent() { /* This is correct for Unix and Win32; other platforms may require a different algorithm */ int index = path.lastIndexOf(separatorChar); if (index < 0) return null; if (!isAbsolute() || (path.indexOf(separatorChar) != index)) return path.substring(0, index); if (index < path.length() - 1) return path.substring(0, index + 1); return null; } abstract String canonPath(String path) throws IOException; /** * Tests if this <code>File</code> exists. * * @return <code>true</code> if the file specified by this object * exists; <code>false</code> otherwise. * @exception SecurityException if a security manager exists, its * <code>checkRead</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed read access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkRead(java.lang.String) * @since JDK1.0 */ public abstract boolean exists(); /** * Tests if the application can write to this file. * * @return <code>true</code> if the application is allowed to write to * a file whose name is specified by this object; * <code>false</code> otherwise. * @exception SecurityException if a security manager exists, its * <code>checkWrite</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed write access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkWrite(java.lang.String) * @since JDK1.0 */ public abstract boolean canWrite(); /** * Tests if the application can read from the specified file. * * @return <code>true</code> if the file specified by this object exists * and the application can read the file; * <code>false</code> otherwise. * @exception SecurityException if a security manager exists, its * <code>checkRead</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed read access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkRead(java.lang.String) * @since JDK1.0 */ public abstract boolean canRead(); /** * Tests if the file represented by this <code>File</code> * object is a "normal" file. * <p> * A file is "normal" if it is not a directory and, in * addition, satisfies other system-dependent criteria. Any * non-directory file created by a Java application is guaranteed to * be a normal file. * * @return <code>true</code> if the file specified by this object * exists and is a "normal" file; <code>false</code> otherwise. * @exception SecurityException If a security manager exists, its * <code>checkRead</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed read access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkRead(java.lang.String) * @since JDK1.0 */ public abstract boolean isFile(); /** * Tests if the file represented by this <code>File</code> * object is a directory. * * @return <code>true</code> if this <code>File</code> exists and is a * directory; <code>false</code> otherwise. * @exception SecurityException if a security manager exists, its * <code>checkRead</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed read access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkRead(java.lang.String) * @since JDK1.0 */ public abstract boolean isDirectory(); /** * Tests if the file represented by this <code>File</code> object is an * absolute pathname. The definition of an absolute pathname is system * dependent. For example, on UNIX, a pathname is absolute if its * first character is the separator character. On Windows platforms, * a pathname is absolute if its first character is an ASCII '\' or * '/', or if it begins with a letter followed by a colon. * * @return <code>true</code> if the pathname indicated by the * <code>File</code> object is an absolute pathname; * <code>false</code> otherwise. * @see java.io.File#getPath() * @see java.io.File#separator * @since JDK1.0 */ public abstract boolean isAbsolute(); /** * Returns the time that the file represented by this * <code>File</code> object was last modified. * <p> * The return value is system dependent and should only be used to * compare with other values returned by last modified. It should not * be interpreted as an absolute time. * * @return the time the file specified by this object was last modified, * or <code>0L</code> if the specified file does not exist. * @exception SecurityException if a security manager exists, its * <code>checkRead</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed read access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkRead(java.lang.String) * @since JDK1.0 */ public abstract long lastModified(); /** * Returns the length of the file represented by this * <code>File</code> object. * * @return the length, in bytes, of the file specified by this object, * or <code>0L</code> if the specified file does not exist. * @exception SecurityException if a security manager exists, its * <code>checkRead</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed read access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkRead(java.lang.String) * @since JDK1.0 */ public abstract long length(); /** * Creates a directory whose pathname is specified by this * <code>File</code> object. * * @return <code>true</code> if the directory could be created; * <code>false</code> otherwise. * @exception SecurityException if a security manager exists, its * <code>checkWrite</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed write access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkWrite(java.lang.String) * @since JDK1.0 */ public abstract boolean mkdir(); /** * Creates a directory whose pathname is specified by this * <code>File</code> object, including any necessary parent directories. * * @return <code>true</code> if the directory (or directories) could be * created; <code>false</code> otherwise. * @exception SecurityException if a security manager exists, its * <code>checkWrite</code> method is called with the pathname * of each of the directories that is to be created, before * any of the directories are created. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkWrite(java.lang.String) * @since JDK1.0 */ public boolean mkdirs() { if (exists()) { return false; } if (mkdir()) { return true; } String parent = getParent(); return (parent != null) && (FileIOFactory.newInstance(parent).mkdirs() && mkdir()); } /** * Renames the file specified by this <code>File</code> object to * have the pathname given by the <code>File</code> argument. * * @param dest the new filename. * @return <code>true</code> if the renaming succeeds; * <code>false</code> otherwise. * @exception SecurityException if a security manager exists, its * <code>checkWrite</code> method is called both with the * pathname of this file object and with the pathname of the * destination target object to see if the application is * allowed to write to both files. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkWrite(java.lang.String) * @since JDK1.0 abstract boolean renameTo(FileIO dest); */ /** * Returns a list of the files in the directory specified by this * <code>File</code> object. * * @return an array of file names in the specified directory. * This list does not include the current directory or the * parent directory ("<code>.</code>" and "<code>..</code>" * on Unix systems). * @exception SecurityException If a security manager exists, its * <code>checkRead</code> method is called with the pathname * of this <code>File</code> to see if the application is * allowed read access to the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkRead(java.lang.String) * @since JDK1.0 */ public abstract String[] list(); /** * Deletes the file specified by this object. If the target * file to be deleted is a directory, it must be empty for deletion * to succeed. * * @return <code>true</code> if the file is successfully deleted; * <code>false</code> otherwise. * @exception SecurityException if a security manager exists, its * <code>checkDelete</code> method is called with the * pathname of this <code>File</code> to see if the * application is allowed to delete the file. * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkDelete(java.lang.String) * @since JDK1.0 */ abstract boolean delete(); /** * Computes a hashcode for the file. * * @return a hash code value for this <code>File</code> object. * @since JDK1.0 */ public int hashCode() { return path.hashCode() ^ 1234321; } /** * Compares this object against the specified object. * Returns <code>true</code> if and only if the argument is * not <code>null</code> and is a <code>File</code> object whose * pathname is equal to the pathname of this object. * * @param obj the object to compare with. * @return <code>true</code> if the objects are the same; * <code>false</code> otherwise. * @since JDK1.0 */ public boolean equals(Object obj) { if ((obj != null) && (obj instanceof FileIO)) { return path.equals(((FileIO) obj).path); } return false; } /** * Returns a string representation of this object. * * @return a string giving the pathname of this object. * @see java.io.File#getPath() * @since JDK1.0 */ public String toString() { return getPath(); } /** * WriteObject is called to save this filename. * The separator character is saved also so it can be replaced * in case the path is reconstituted on a different host type. */ private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeChar(separatorChar); // Add the separator character } /** * readObject is called to restore this filename. * The original separator character is read. If it is different * than the separator character on this system. The old seperator * is replaced by the current separator. */ private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); char sep = s.readChar(); // read the previous seperator char if (sep != separatorChar) path = path.replace(sep, separatorChar); } }