Without even opening the file, File lets you find out about a file or directory, and
lets you rename or delete it.
Because java.io.File can represent a file, wildcard, or directory node, this class
has many more uses than its name would suggest. File is a misnomer, because
File does not represent a file at all, but rather the name of a file or directory that
may or may not actually exist.
Using new File( name )
File myFile = new File( "C:\\temp\\abc.txt" );
File myDir = new File( "/home/fundir" );
Using new File( dir, name )
constructor builds file name out of two pieces. The first directory parameter may optionally a String or a File object. The second filename parameter must be a
String. This is not nearly as clever as you might imagine. All does is glue the two
pieces together with a / between. So you can’t do things like this:
new File ( ".", "C:/fileInRoot.txt" )
if new File ( "myDir", "/otherDir" )
File( "myDir/OtherDir" )
not File( "/OtherDir" );
In other words, the file parameter has to be truly relative to the directory parameter. However, embedded /s like
this new File ( "species", "clan/individual.txt" )
and new File ( "species/clan/individual.txt" );
Under the hood, File is surprisingly lightweight. It is just a String and an int to record the prefix length. The prefix is the drive specifier, or the lead /. There is no OS (Operating System)
file handle of any
kind. Since the current directory cannot change throughout the execution of a program, the File constructor does not need to embed it in each File object.
You might think you could do:
File base = new File ( "mydir/myfile.txt" );
File f2 = new File( base, "myfile2.txt" );
to create a file
mydir/myfile2.txt. This does not work. You will get
mydir/myfile.txt/myfile2.txt instead.
Filename not URL (Uniform Resource Locator)
gets you access to a file. You feed it a filename or directory name
suitable for the native platform, not an URL. On windows, you can use / and
\ interchangeably. \ has to be doubled
File dir1 = new File ( "E:\\mindprod" );
File dir2 = new File ( "E:\\mindprod\\" );
File dir3 = new File ( "E:/mindprod" );
File dir4 = new File ( "E:/mindprod/" );
If you need an URL or URI (Uniform Resource Indicator), you can use
File.toURL
or File. toURI.
Sample Code
Here is how you use most of the File methods. The listing comments also tell you what
to expect from each of the methods, especially the many different ways you can get a file’s name.
Methods For Manipulating Filenames and Files
I have ordered these with the ones you are most likely to use near the top.
File.createNewFile |
Atomically creates a new, empty file named if and only if a file with this name does not yet exist.
Normally you don’t explicitly create the file. It is created as a side effect of writing to an
OutputStream or Writer. |
File.exists |
does a file or directory of this name exist?. Beware of code like this:
String f = null;
if ( new File( f + ".ext" ) .exists() ) ...
will return true, because null.ext is considered to exist as the null device.
In a similar way com1.txt is considered to exist as the com1: port even when there is no such file. Avoid filenames of the form com?.* and lpt?.*. |
File.delete |
erase, remove, kill, destroy, unlink, and nuke a file. The File object is
completely unaffected by deleting the file on disk, whether you do it with
File.delete() or by any
independent means. See also File.deleteOnExit. Can also be used to delete empty
directories.
- Reasons for failure to delete include:
- The file/directory did not exist/was already deleted.
- The file has the system attribute.
- The file is owned by some other user than the one currently logged on.
- The file is still in use by this program. You must close all references/streams using it
first.
- The file is in use by some other program, Java or non Java.
- Sometimes delete fails because of an indexing-local search program
getting in too quickly to index the file about to be deleted. If the file is in-use, you
can’t delete it. I turn off my Copernic indexing program any time I am running Java batch
jobs.
- delete() returns true if the file was
successfully deleted, false if it did not exist, was already deleted or
could not be deleted because it was in use or lack of sufficient privilege. Normally that is not the
status you want. You want to know if the file is now gone. To do that you need code like this:
|
File.renameTo |
renaming (or moving) a file. Note, it does not change the name inside the File
object, just the name of the corresponding file on disk. You can’t use the File object to access the renamed file. You need a fresh one with the new name.
renameTo could fail if:
- the file is open
- the file in open by someone else
- the new name is invalid
- the new name is on another drive
- the new name already exists
- the file is read-only
|
File.length |
how many bytes are in this file. Coded as File.length
() not File. length as you would with an array. |
File.canRead |
does this file exist and do you have permission to read it? |
File.canWrite |
does this file exist and do you have permission to write it? Returns false if the file
does not exist, even though you probably could write such a file. Note that if it does not exist, you can
write it, but canWrite will return false. setReadOnly lets you make a file read-only, but there is no way to undo the read-only
status, other than by copying it or using exec. |
File.lastModified |
get last modified timestamp. setLastModified lets you change the lastModified
date
If you don’t have proper access permission, you will get -1 results. With
Java version 1.4 you can now set the date as well with File.setLastModified( long timestamp ). Windows keeps file
timestamps accurate to 100 nanoseconds with 10,000 times as much precision
as Java’s 1 ms. This means if you copy a file in Java, the new file might not have the exact same
timestamp as the old. When you reconstitute a zipped file, its timestamp will be reconstituted accurate
only to the even 2 seconds.
|
File.isFile |
is there a file by this name? Is this file a true file rather than a directory? |
RandomAccessFile.setLength |
chop/grow this file to n bytes long.Java version 1.2 or later only. You can’t use this directly on the
File. You must create a RandomAccessFile object first
with new RandomAccessFile( file, rw ); |
File.setReadOnly |
Lets you make a file read-only. There is no way to undo this in Java. |
File.setlastModified |
set last modified timestamp. This happens anyway automatically when you modify and close a file. You
cannot read or access the last access date or the create
date without using the FileTimes class,
JNI (Java Native Interface) or exec.
|
Manipulating Directories
The file methods work on directories. These methods are primarily for working on directories. File is used to
represent both a directory and a file.
File.list |
String[] fileNames = file.list();
get list of files in this directory. Wildcards won’t work. Note it returns an array of Strings, not including the directory, not File objects. Files
are not in any particular order. They include the subdirectories, but not the .
or .. entries. The lists include all files and directories, hidden or revealed.
It is as if Java ignores the hidden attribute.
If the directory is empty, you will get an empty list new
String[0]. However, if the file you give it is not a directory or does not
exist, you will get null. So whenever you use File.list() check for filenames
== null before you do for ( String filename : filenames)
Often used with a FilenameFilter to select some of the files.
String[] fileNames = file.list( someFilter );
Your FilenameFilter needs at a minimum to filter with File.isDirectory().
|
File.isDirectory |
is there a directory by this name. Is this file a directory rather than in individual file? |
File.listRoots |
a list of available drives,Java version 1.2 or later only. Note it returns you an array of
File objects, not Strings. If you print them, on Windows, they will have the form A:\. On Linux, there is only one root //, so it is not useful to
get you a list of mount points. |
javax.swing.
filechooser.
FileSystemView.
getFileSystemView().
getRoots() |
alternate way to get a list of available drives. |
File.mkdirs |
final boolean success = new File( "C:/temp/wombats" ).mkdirs();
final File dirs = new File( "C:/temp/wombats" );
final boolean success = dirs.mkdirs();
(It violates Sun’s naming conventions, but it is mkdirs, not mkDirs), make a directory and any necessary parent directories. mkdir is similar, but does not create parent directories. This is an instance method of
File. You define the directory first with new
File then create the tree. Returns true if all
directory nodes were successfully created. Returns false if it can’t
complete the job, or if directories were already existing. It may have created some but not all of the
directories when it fails. If it succeeds you are certain they are all there.
- Windows takes a short while after you make a successful mkdirs request
to actually post the addition to the directory structure. So if you do an File. exists immediately afterward, it can sometimes fail.
So close your eyes and trust the result of mkdirs. The directories will be
there by the time you create and close a file.
- The way mkdirs works is illogical. In my opinion it should have
returned true if the directories already exist. What is important is are
the directories ready to go, not how they got created. It is too late to fix now. To use mkdirs, you need to do an exists first, and avoid calling
mkdirs if the dir already exists.
- mkdirs will not work on a file to create its parent dirs. You must give it just the dir part.
|
File.getUsableSpace |
Java version 1.6 or later, How much free space is on a drive/partition that is free for you to use. |
File.getFreeSpace |
Java version 1.6 or later, How much free space is on a drive/partition. You might not necessarily be
allowed to write to all or any of it. |
File.getTotalSpace |
Java version 1.6 or later, How much free space is on a drive/partition combined used/unused. |
Taking Apart A Filename:
There are strange filenames like C:, .., /sub, C:. Make sure you test that your code
works with them as well. I have ordered this list with the ones you will use most often near the top. What you
get depends on what you put in. Look at the sample code to see the fine
points. Here I am presuming you put in minimal relative filenames.
File.toString |
partially qualified directory + name + extension. If you do a System. out. println ( someFile ) you will get the toString version. |
File.getAbsolutePath |
fully qualified drive + directory + name + extension. It won’t give you the
precise case of the file! It will echo back to you the case you used. |
File.getName |
just the name + extension. |
File.getPath |
partially qualified directory + name + extension. |
File.getParent |
partially qualified directory.
Uses \ instead of / for the separator in Windows. Only works to give you the absolute parent if you provide
fully qualified filenames. If you feed it an unqualified one, you will just get a null result. I suggest
you experiment to see what it is giving you in any case. The important thing to understand is you get everything to the left of the filename,
not just the rightmost directory leg. |
File.getCanonicalPath |
drive + fully qualified directory + name + extension.
Uses \ instead of / for the separator in W95/W98/Me/NT/W2K/XP/W2003/Vista/W2008/W7-32/W7-64. Gets you the precise
case. May throw an IOException. To avoid that use the cruder getAbsolutePath. In canonical form on Windows, drive letters are upper case. |
File.getCanonicalFile |
drive + fully qualified directory + name + extension packaged up in a new File Object.
Uses \ instead of / for the separator in W95/W98/Me/NT/W2K/XP/W2003/Vista/W2008/W7-32/W7-64. Gets you the precise
case. In canonical form on Windows, drive letters are upper case. |
File.isAbsolute |
true if the file name is absolute, false if
relative to the current directory. |
Combining Parts of A Filename:
Permanent Files
Finding a suitable spot to place permanent files is much more difficult than it should be. Here are some
approaches.
- Use Java Web Start. It has a mechanism to allocate you a
unique directory to place persistent files.
- For small amounts of data, use the Preferences mechanism that
stores the data in the Windows registry.
- Ask the end user via JFileChooser (good for files or
directories, new or existing) for the name of a suitable director. It is best to offer a sensible default drive
and directory since most users have no clue what a drive or directory is.
- Sniff about the drives using File.listRoots
and File. getFreeSpace looking for a partition that has
lots of free space and is writable, and just create a unique directory. Techies will be alarmed if you use
this approach.
- Look at system properties such as java.io.tmpdir, os.name, user.dir, user.home and
user.name to concoct a suitable directory name. E.g. on Windows, C:\Program Files\MyCompany\MyProduct is a good bet.
Temporary Files
Here are the methods useful for manipulating temporary files.
File.createTempFile |
Create a temporary file whose name is guaranteed to be unique. You specify a prefix, suffix and directory
to use. Always name your temporary files with a prefix temp and a suffix
.tmp so that they can easily be scavenged and deleted after a crash by generic
junk cleaning utilities. To put the temporary in the same directory as another file, use getParent to find the directory. The file will not be automatically
deleted on exit, unless you use deleteOnExit.
|
File.deleteOnExit |
Arrange for this temporary file to be automatically deleted on exit if we forget to. This is more
efficient than setting up a Runtime. getRuntime().addShutdownHook( new Thread(). There is no equivalent closeOnExit for various
file |
File.delete |
Delete the temporary file now. |
Hints
- There are no tools to test or change file attributes such as hidden, system or archive,
except for setReadOnly and setLastModified. The
java.io.FilePermission class can’t be used for changing permissions of
operating system files. It is used for specifying the permissions of files within a Java program. Java does not
support the hidden attribute because not all platforms have it. Unix and Linux use a convention of hiding files
whose names begin with a ..
- new File does not actually create a file. The file does not get created until you
open some sort of stream or reader. You can create one explicitly with File.createNewFile(). If the file already exists it does nothing. It does not empty the
file.
- Java does not let you change the current directory, though you
can discover it with new File(.).getCanonicalPath(). The concept of current does not really
make sense in a multithreaded environment. You can keep track of your own simulated current directory string
(possibly on a per thread or per Object basis), and use new File(dir, filename) to
construct a fully qualified filename. The constructor is not very bright. It basically just glues the filename
onto the end of the dir name with a file separator. It does not cleverly merge the directory name and the
filename the way a command processor would merge the current directory name and a partly qualified filename to
get a fully qualified name. You can’t, for example, provide the constructor with a fully qualified
filename as the file and have it completely override the dir. The best way to understand its limitations is to
experiment and dump your results with File.getCanonicalPath. Writing a smart merge
would have to consider the naming conventions of each platform. Another option is to write your own
JNI
CD (Compact Disk)
native method that uses the C chdir or _chdir function and
GetStringUTFChars. You could also use exec to
spawn a cd command.
- There are no tools to look for an extension. You have to do that yourself with
code like this: File offers no built-in way to get the extension or the filename
without
- File also handles directories. You can use it to delete, rename and test
directories. File.list will give you a list of files in this directory as an array of
Strings. However, File cannot handle wildcards. You have to use FilenameFilter.
- File is not final. You can extend it with your own
features, e.g. methods to decompose the filename into its composite pieces.
File and Record Locking
Java has no features for file or record locking. You can kludge them by creating a
dummy file whenever you are using the main file, and deleting it when you are done. If all threads and processes
using the file do likewise, and sleep while the dummy semaphore file is present, waking periodically to see if it
has disappeared, you can arrange exclusive access. Other than that, you would have to use
JNI to
hook into the OS ’s native file locking scheme.
The easiest way to deal with this is to use an SQL database manager
which can deal with concurrent updates.
Platform Specific Filenames
Every platform uses a different filename format. Your Java apps will deal directly with those filenames. You have
only
For WORA (Write Once, Run Anywhere), it is best to use very conservative file
naming conventions:
- lower case only.
- no punctuation.
- no spaces.
- no accented letters.
- no control characters.
Anything else is bound to confuse some OS somewhere.
Real World Platforms
|
Windows |
Linux |
Apple iMac |
Groupe Bull GCOS 8
(JDK (Java Development Kit) 1.1.6) |
| lineSeparator |
\r\n |
\n |
\r |
\n |
| separatorChar |
'\\' |
'/' |
':' |
'/' |
| pathSeparatorChar |
';' |
':' |
N/A |
':' |
| absolute |
C:\\myDir\\myFile.txt |
/usr/local/my.Dir/my.File.txt |
::myVolume:myDir:file.txt |
gcosuser/catalog/file.txt |
| relative |
myDir\\myFile.txt |
my.Dir/my.File.txt |
myDir:file.txt |
/catalog/file.txt
(subordinate to the current GCOS 8 userid) |
| root |
C:\\. |
/. |
::myVolume: |
N/A |
| parent |
..\\. |
../. |
File.getParent() |
N/A |
| case sensitive |
no |
yes |
no |
no |
| charset |
A-Z a-z 0-9 accented - _ ~ ! @ # $ |
A-Z a-z 0-9 accented - _ ~ ! @ # $ |
Almost anything, Full Unicode, even control chars |
a-z 0-9 - _ . |
| avoid |
. : ; * @ % ^ & ( ) [ ] { } " ' < > ? + = / | |
: ; * @ % ^ & ( ) [ ] { } " ' < > ? + = / | |
: (. at beginning) ; * @ % ^ ( ) " ' < > ? + = / | |
: ; * @ % ^ & ( ) [ ] { } " ' < > ? + = / | ~ ! @ # $ accented |
| zip and jar files |
|
|
|
These files types are treated as a container database for a collection of Java class files
and other resources. The pathnames stored within these files are not case sensitive and can be
arbitrarily long.
GCOS 8 supports read-access to these files. |
| restrictions |
|
|
|
- Each directory or file component must be less than or equal to 12 characters.
- Both . and .. can be valid file names.
- The construct . does not refer to the current directory.
- The construct .. does not refer to the parent directory.
|
|---|
GCOS is a mainframe JVM (Java Virtual Machine) implementation without GUI (Graphic User Interface). It runs on mainframes that use 36-bit words with
non-IEEE floating point hardware. It has its roots in GE’s GECOS, was later taken over by Honeywell, and
had been run by the French Company, Groupe Bull since 1989. It is included mainly to
show you just how different a platform can be and still run Java apps unmodified.
Console I/O
The console I/O methods are in System, e.g.
| System.in.read(); |
read a byte |
| System.err.print() |
print a value |
| System.err.println(); |
print a value followed by a newline |
| System.out.print(); |
print a value |
| System.out.println(); |
print a value followed by a newline. |
| System.setIn(); |
redirect stdin to a file |
| System.setErr(); |
redirect stderr to a file |
| System.setOut(); |
redirect stdout to a file |
Applets
Unsigned Applets cannot read files on the local hard disk. The java.io.File class
won’t let you read or write files on some other remote machine, e.g. Applets can’t
read or write files on the server, even if they are signed.
Learning More
Oracle’s Javadoc on
File class : available:
Oracle’s Javadoc on
File.canRead : available:
Oracle’s Javadoc on
File.canWrite : available:
Oracle’s Javadoc on
File.exists : available:
Oracle’s Javadoc on
File.getAbsolutePath : available:
Oracle’s Javadoc on
File.getCanonicalPath : available:
Oracle’s Javadoc on
File.getTotalSpace : available:
Oracle’s Javadoc on
File.getUsableSpace : available:
Oracle’s Javadoc on
File.isDirectory : available:
Oracle’s Javadoc on
File.lastModified : available:
Oracle’s Javadoc on
File.length : available:
Oracle’s Javadoc on
File.listFiles : available:
Oracle’s Javadoc on
File.mkDir : available:
Oracle’s Javadoc on
File.renameTo : available:
Oracle’s Javadoc on
Files.setPosixFilePermissions : available:
Oracle’s Javadoc on
Files.setOwner : available:
FileSystemView gives you more platform specific information about files. I have a RFE (Request For Enhancement) in asking for it to give more information e.g.
isDisk, isSSD, isDVD, isCD, isUSB,
isRemote…
Oracle’s Javadoc on
FileSystemView class : available: