Reading Files

java.io.FileInputStream is a concrete subclass of java.io.InputStream. It provides an input stream connected to a particular file. FileInputStream has all the usual methods of input streams, such as read( ), available( ), skip( ), and close( ), which are used exactly as they are for any other input stream. FileInputStream( ) has three constructors, which differ only in how the file to be read is specified:

public FileInputStream(String fileName) throws IOException
public FileInputStream(File file) throws FileNotFoundException
public FileInputStream(FileDescriptor fdObj)

The first constructor uses a string containing the name of the file. The second constructor uses a java.io.File object. The third constructor uses a java.io.FileDescriptor object.

To read a file, just pass the name of the file into the FileInputStream( ) constructor. Then use the read( ) method as normal. For example, the following code fragment reads the file README.TXT, then prints it on System.out:

try {
 FileInputStream fis = new FileInputStream("README.TXT");
 for (int n = fis.read(); n != -1; n = fis.read( )) {
 System.out.write(n);
 }
}
catch (IOException ex) {
 System.err.println(ex);
}
System.out.println( );

Java looks for files in the current working directory . Generally, this is the directory you were in when you typed javaprogram_name to start running the program. You can open a file in a different directory by passing a full or relative path to the file from the current working directory. For example, to read the file /etc/hosts no matter which directory is current, you can do this:

FileInputStream fis = new FileInputStream("/etc/hosts");

Filenames are platform-dependent, so hardcoded filenames should be avoided wherever possible. This example depends on a Unix-style pathname. It is not guaranteed to work on other platforms such as Windows or Mac OS 9, though it might. Using a filename to create a FileInputStream violates Sun's rules for "100% Pure Java." Some runtime environments such as Apple's Macintosh Runtime for Java include extra code to translate from Unix-style filenames to the native style. However, for maximum cross-platform awareness, you should use File objects instead. These can be created directly from filenames as described in Chapter 17, supplied by the user through a GUI such as a Swing JFileChooser, or returned by various methods scattered throughout the API and class libraries. Much of the time, code that uses a File object adapts more easily to unexpected filesystem conventions. One particularly important trick is to create multisegment paths by successively appending new File objects for each directory like so:

File root = new File("/");
File dir = new File(root, "etc");
File child = new File(dir, "hosts");
FileInputStream fis = new FileInputStream(child);

However, this still assumes that the root of the filesystem is named "/", which isn't likely to be a true on a non-Unix system. It's better to use the File.listRoots( ) method:

File[] roots = File.listRoots( )
File dir = new File(roots[0], "etc");
File child = new File(dir, "hosts");
FileInputStream fis = new FileInputStream(child);

However, although this code is more platform independent, it still assumes a particular file layout structure. This can vary not just from platform to platform, but from one PC to the next, even those running the same operating system. For more robustness, you'll want to get at least a directory, if not a complete file, by invoking a method that adapts to the local system. Possibilities include:

  • Ask the user to choose a file with a Swing JFileChooser.
  • Ask the user to choose a file with an AWT FileDialog.
  • Ask a third-party library such as MRJ Adapter's SpecialFolder for a known location such as the preferences folder or the desktop folder.
  • Create a temporary file with the File.createTempFile( ) method.
  • Find the user's home directory with System.getProperty("user.home").
  • Find the current working directory with System.getProperty("user.dir").

This list is not exhaustive; there are other approaches. Which one is appropriate depends on the use case. Details of these approaches are addressed in future chapters.

If the file you're trying to read does not exist when the FileInputStream object is constructed, the constructor throws a FileNotFoundException (a subclass of java.io.IOException). If for some other reason a file cannot be readfor example, the current process does not have read permission for the filesome other kind of IOException is thrown.

Example 4-1reads a filename from the command line, then copies the named file to System.out. The StreamCopier.copy( ) method from Example 3-3 in the previous chapter does the actual reading and writing. Notice that that method does not care whether the input is coming from a file or going to the console. It works regardless of the type of the input and output streams it's copying. It will work equally well for other streams still to be introduced, including ones that did not even exist when StreamCopier was created.

Example 4-1. The FileDumper program

import java.io.*;
import com.elharo.io.*;
public class FileTyper {
 public static void main(String[] args) throws IOException {
 if (args.length != 1) {
 System.err.println("Usage: java FileTyper filename");
 return;
 }
 typeFile(args[0]);
 }
 public static void typeFile(String filename) throws IOException {
 FileInputStream fin = new FileInputStream(filename);
 try {
 StreamCopier.copy(fin, System.out);
 }
 finally {
 fin.close( );
 }
 }
}

Untrusted code is not usually allowed to read or write files. If an applet tries to create a FileInputStream, the constructor will throw a SecurityException.

The FileInputStream class has one method that's not declared in the InputStream superclass: getFD( ).

public final FileDescriptor getFD( ) throws IOException

This method returns the java.io.FileDescriptor object associated with this stream. FileDescriptor objects are discussed inChapter 17. For now, all you can do with this object is use it to create another file stream.

It is possible to open multiple input streams to the same file at the same time, though it's rarely necessary to do so. Each stream maintains a separate pointer that points to the current position in the file. Reading from the file does not change the file in any way. Writing to the file is a different story, as you'll see in the next section.

Basic I/O

Introducing I/O

Output Streams

Input Streams

Data Sources

File Streams

Network Streams

Filter Streams

Filter Streams

Print Streams

Data Streams

Streams in Memory

Compressing Streams

JAR Archives

Cryptographic Streams

Object Serialization

New I/O

Buffers

Channels

Nonblocking I/O

The File System

Working with Files

File Dialogs and Choosers

Text

Character Sets and Unicode

Readers and Writers

Formatted I/O with java.text

Devices

The Java Communications API

USB

The J2ME Generic Connection Framework

Bluetooth

Character Sets



Java I/O
Java I/O
ISBN: 0596527500
EAN: 2147483647
Year: 2004
Pages: 244

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net