Vous êtes sur la page 1sur 10

Java Input/Output Text and Binary Streams

Introduction to Data Streams


Often programs need to bring in information from an external source or send out information to an external
destination. The information can be anywhere: in a file, on disk, somewhere on the network, in memory, or in
another program. Also, it can be of any type: objects, characters, images, or sounds.
To bring in information, a program opens a stream on an information source (a file, memory, a socket and
reads the information serially, like this:
!imilarly, a program can send information to an external destination by opening a stream to a destination and
writing the information out serially, like this:
"o matter where the information is coming from or going to and no matter what type of data is being read or
written, the algorithms for reading and writing data is pretty much always the same.
#eading $riting
open a stream
while more information
read information
close the stream
open a stream
while more information
write information
close the stream
The java.io package contains a collection of stream classes that support these algorithms for reading and
writing. These classes are di%ided into two class hierarchies based on the data type (either characters or bytes
on which they operate.
&owe%er, it's often more con%enient to group the classes based on their purpose rather than on the data type
they read and write. Thus, we can cross(group the streams by whether they read from and write to data )sinks)
or process the information as its being read or written.
Overview of I/O Streams
Character Streams
Reader and Writer are the abstract superclasses for character streams in java.io. Reader pro%ides the A*+
and partial implementation for readers((streams that read ,-(bit characters((and Writer pro%ides the A*+ and
partial implementation for writers((streams that write ,-(bit characters.
!ubclasses of Reader and Writer implement speciali.ed streams and are di%ided into two categories: those that
read from or write to data sinks (shown in gray in the following figures and those that perform some sort of
processing (shown in white. The figure shows the class hierarchies for the Reader and Writer classes.
/ost programs should use readers and writers to read and write information. This is because they both can
handle any character in the 0nicode character set (while the byte streams are limited to +!O(1atin(, 2(bit
bytes.
Byte Streams (Binary Streams
*rograms should use the byte streams, descendants of InputStream and OutputStream, to read and write 2(bit
bytes. InputStream and OutputStream pro%ide the A*+ and some implementation for input streams (streams
that read 2(bit bytes and output streams (streams that write 2(bit bytes. These streams are typically used to
read and write binary data such as images and sounds.
As with Reader and Writer, subclasses of InputStream and OutputStream pro%ide speciali.ed +3O that falls
into two categories: data sink streams and processing streams. 4igure 5- shows the class hierarchies for the byte
streams.
As mentioned, two of the byte stream classes, ObjectInputStream and ObjectOutputStream, are used for
object seriali.ation.
!nderstandin" the I/O Superc#asses
Reader and InputStream define similar A*+s but for different data types. 4or example, Reader contains these
methods for reading characters and arrays of characters:
int read()
int read(char cbuf[])
int read(char cbuf[] int offset int len!th)
InputStream defines the same methods but for reading bytes and arrays of bytes:
int read()
int read(b"te cbuf[])
int read(b"te cbuf[] int offset int len!th)
Also, both Reader and InputStream pro%ide methods for marking a location in the stream, skipping input, and
resetting the current position.
Writer and OutputStream are similarly parallel. Writer defines these methods for writing characters and
arrays of characters:
void write(int c)
void write(char cbuf[])
void write(char cbuf[] int offset int len!th)
void write(Strin! s)
And OutputStream defines the same methods but for bytes:
void write(int c)
void write(b"te cbuf[])
void write(b"te cbuf[] int offset int len!th)
All of the streams((readers, writers, input streams, and output streams((are automatically opened when created.
6ou can close any stream explicitly by calling its close method. Or the garbage collector can implicitly close
it, which occurs when the object is no longer referenced.
$ow to !se %i#e Streams
4ile streams are perhaps the easiest streams to understand. !imply put, the file streams ( #ileReader,
#ileWriter, #ileInputStream, and #ileOutputStream ( each read or write from a file on the nati%e file
system. 6ou can create a file stream from a filename, a #ile object, or a #ile$escriptor object.
The following program uses #ileReader and #ileWriter to copy the contents of a file named input.txt into a
file called output.t%t :
import java.io.&'
public class (op" )
public static void main(Strin![] ar!s) throws IO*%ception )
#ile input#ile + new #ile(,input.t%t,)'
#ile output#ile + new #ile(,output.t%t,)'
#ileReader in + new #ileReader(input#ile)'
#ileWriter out + new #ileWriter(output#ile)'
int c'
while ((c + in.read()) -+ ./)
out.write(c)'
in.close()'
out.close()'
0
0
This program is %ery simple. +t opens a #ileReader on input.t%t and opens a #ileWriter on output.t%t.
The program reads characters from the reader as long as there's more input in the input file. $hen the input
runs out, the program closes both the reader and the writer.
"otice the code that the (op" program uses to create a #ileReader:
#ile input#ile + new #ile(,input.t%t,)'
#ileReader in + new #ileReader(input#ile)'
This code creates a #ile object that represents the named file on the nati%e file system. #ile is a utility class
pro%ided by java.io. This program uses this object only to construct a #ileReader on input.t%t. &owe%er,
it could use input#ile to get information about input.t%t, such as its full pathname.
1fter "ou2ve run the pro!ram "ou should find an e%act cop" of input.t%t in a file named
output.t%t in the same director".
#emember that #ileReader and #ileWriter read and write ,-(bit characters. &owe%er, most nati%e file
systems are based on 2(bit bytes. These streams encode the characters as they operate according to the default
character(encoding scheme. 6ou can find out the default character(encoding by using S"stem.!et3ropert"
(,file.encodin!,). To specify an encoding other than the default, you should construct an
OutputStreamWriter on a #ileOutputStream and specify it.
4or the curious, here is another %ersion of this program, (op"4"tes, which uses #ileInputStream and
#ileOutputStream in place of #ileReader and #ileWriter :
import java.io.&'
public class (op"4"tes )
public static void main(Strin![] ar!s) throws IO*%ception )
#ile input#ile + new #ile(,input.t%t,)'
#ile output#ile + new #ile(,output.t%t,)'
#ileInputStream in + new #ileInputStream(input#ile)'
#ileOutputStream out + new #ileOutputStream(output#ile)'
int c'
while ((c + in.read()) -+ ./)
out.write(c)'
in.close()'
out.close()'
0
0
$ow to !se &ine'um(er)eader
The 5ine6umberReader class is a subclass of 4ufferedReader. +ts read() methods contain additional logic to
count end(of(line characters and thereby maintain a line number. !ince different platforms use different
characters to represent the end of a line, 5ine6umberReader takes a flexible approach and recogni.es ,7n,,
,7r,, or ,7r7n, as the end of a line. #egardless of the end(of(line character it reads, 5ine6umberReader
returns only ,7n, from its read() methods.
6ou can create a 5ine6umberReader by passing its constructor a Reader. The following example prints out all
the lines of a file, with each line prefixed by its number. +f you try this example, you'll see that the line numbers
begin at 8 by default:
tr" )
#ileReader fileIn + new #ileReader(,te%t.t%t,)'
5ine6umberReader in + new 5ine6umberReader(fileIn)'
while ((line+in.read5ine()) -+ null) )
S"stem.out.println(in.!et5ine6umber() 9 ,. , 9 line)'
0
0 catch (IO*%ception ioe) )
ioe.printStac:;race()'
0
The 5ine6umberReader class has two methods pertaining to line numbers. The !et5ine6umber() method
returns the current line number. +f you want to change the current line number of a 5ine6umberReader, use
set5ine6umber(). This method does not affect the stream position7 it merely sets the %alue of the line number.
$ow to !se *rint+riter
The 3rintWriter class is a subclass of Writer that pro%ides a set of methods for printing string
representations of e%ery 8a%a data type. A 3rintWriter can be wrapped around an underlying Writer object or
an underlying OutputStream object. +n the case of wrapping an OutputStream, any characters written to the
3rintWriter are con%erted to bytes using the default encoding scheme.9:; Additional constructors allow you
to specify if the underlying stream should be flushed after e%ery line(separator character is written.
The 3rintWriter class pro%ides a print() and a println() method for e%ery primiti%e 8a%a data type. As
their names imply, the println() methods do the same thing as their print() counterparts, but also append a
line separator character.
The following example demonstrates how to wrap a 3rintWriter around an OutputStream:
boolean b + true'
char c + 2<2
double d + =.>/?@/
int i + ?A'
Strin! s + ,R + ,'
3rintWriter out + new 3rintWriter(S"stem.out true)'
out.print(s)'
out.print(d)'
out.println()'
out.println(b)'
out.println(c)'
out.println(i)'
This example produces the following output:
R + =.>/?@/
true
<
?A
3rintWriter objects are often used to report errors. 4or this reason, the methods of this class do not throw
exceptions. +nstead, the methods catch any exceptions thrown by any downstream OutputStream or Writer
objects and set an internal flag, so that the object can remember that a problem occurred. 6ou can <uery the
internal flag by calling the chec:*rror() method.
Although you can create a 3rintWriter that flushes the underlying stream e%ery time a line(separator
character is written, this may not always be exactly what you want. !uppose that you are writing a program that
has a character(based user interface, and that you want the program to output a prompt and then allow the user
to input a response on the same line. +n order to make this work with a 3rintWriter, you need to get the
3rintWriter to write the characters in its buffer without writing a line separator. 6ou can do this by calling the
flush() method.
$ow to !se DataInputStream and DataOutputStream
This page shows you how to use the java.io $ataInputStream and $ataOutputStream classes. +t features an
example, $ataIO;est, that reads and writes tabular data (in%oices for 8a%a merchandise :
import java.io.&'
public class $ataIO;est )
public static void main(Strin![] ar!s) throws IO*%ception )
BB write the data out
$ataOutputStream out + new $ataOutputStream(new
#ileOutputStream(,invoice/.t%t,))'
double[] prices + ) /C.CC C.CC /@.CC >.CC ?.CC 0'
int[] units + ) /A = /> AC @8 0'
Strin![] descs + ) ,Dava ;.shirt,
,Dava Eu!, ,$u:e Du!!lin! $olls,
,Dava 3in, ,Dava Fe" (hain, 0'

for (int i + 8' i G prices.len!th' i 99) )
out.write$ouble(prices[i])'
out.write(har(27t2)'
out.writeInt(units[i])'
out.write(har(27t2)'
out.write(hars(descs[i])'
out.write(har(27n2)'
0
out.close()'
BB read it in a!ain
$ataInputStream in + new $ataInputStream(new
#ileInputStream(,invoice/.t%t,))'
double price'
int unit'
Strin! desc'
double total + 8.8'
tr" )
while (true) )
price + in.read$ouble()'
in.read(har()' BB throws out the tab
unit + in.readInt()'
in.read(har()' BB throws out the tab
desc + in.read5ine()'
S"stem.out.println(,Hou2ve ordered , 9 unit 9 , units of , 9
desc 9 , at I, 9 price)'
total + total 9 unit & price'
0
0 catch (*O#*%ception e) )
0
S"stem.out.println(,#or a ;O;15 ofJ I, 9 total)'
in.close()'
0
0
The tabular data is formatted in columns, where each column is separated from the next by tabs. The columns
contain the sales price, the number of units ordered, and a description of the item, like this:
/C.CC /A Dava ;.shirt
C.CC = Dava Eu!
$ataOutputStream, like other filtered output streams, must be attached to some other OutputStream. +n this
case, it's attached to a #ileOutputStream that's set up to write to a file named invoice/.t%t.
$ataOutputStream dos + new $ataOutputStream(new #ileOutputStream(,invoice/.t%t,))'
"ext, $ataIO;est uses $ataOutputStream's speciali.ed writeXXX methods to write the in%oice data
(contained within arrays in the program according to the type of data being written:
for (int i + 8' i G prices.len!th' i 99) )
dos.write$ouble(prices[i])'
dos.write(har(27t2)'
dos.writeInt(units[i])'
dos.write(har(27t2)'
dos.write(hars(descs[i])'
dos.write(har(27n2)'
0
dos.close()'
"ote that this code snippet closes the output stream when it's finished.
"ext, $ataIO;est opens a $ataInputStream on the file just written:
$ataInputStream dis + new $ataInputStream(new #ileInputStream(,invoice/.t%t,))'
$ataInputStream also must be attached to some other InputStream7 in this case, a #ileInputStream set up
to read the file just written ( invoice/.t%t. $ataIO;est then just reads the data back in using
$ataInputStream's speciali.ed readXXX methods.
tr" )
while (true) )
price + dis.read$ouble()'
dis.read(har()' BB throws out the tab
unit + dis.readInt()'
dis.read(har()' BB throws out the tab
desc + dis.read5ine()'
S"stem.out.println(,Hou2ve ordered , 9 unit 9 , units of , 9 desc
9 , at I, 9 price)'
total + total 9 unit & price'
0
0
catch (*O#*%ception e) )
0
S"stem.out.println(,#or a ;O;15 ofJ I, 9 total)'
dis.close()'
$hen all of the data has been read, $ataIO;est displays a statement summari.ing the order and the total
amount owed, and closes the stream.
"ote the loop that $ataIO;est uses to read the data from the $ataInputStream. "ormally, when reading you
see loops like this:
while ((input + dis.read5ine()) -+ null)
)
. . .
0
The read5ine method returns a %alue, null, that indicates that the end of the file has been reached. /any of the
$ataInputStream readXXX methods can't do this because any %alue that could be returned to indicate end(of(
file may also be a legitimate %alue read from the stream. 4or example, suppose that you wanted to use (, to
indicate end(of(file= $ell, you can't because (, is a legitimate %alue that can be read from the input stream
using read$ouble, readInt, or one of the other read methods that reads numbers. !o $ataInputStream's
readXXX methods throw an *O#*%ception instead. $hen the *O#*%ception occurs the while (true)
terminates.
$hen you run the $ataIO;est program you should see the following output:
Hou2ve ordered /A units of Dava ;.shirt at I/C.CC
Hou2ve ordered = units of Dava Eu! at IC.CC
Hou2ve ordered /> units of $u:e Du!!lin! $olls at I/@.CC
Hou2ve ordered AC units of Dava 3in at I>.CC
Hou2ve ordered @8 units of Dava Fe" (hain at I?.CC
#or a ;O;15 ofJ I=CA.==
%i#e ,anipu#ation
$hile streams are used to handle most types of +3O in 8a%a, there are some nonstream(oriented classes in
java.io that are pro%ided for file manipulation. "amely, the #ile class represents a file on the local
filesystem, while the Random1ccess#ile class pro%ides nonse<uential access to data in a file. +n addition, the
#ilename#ilter interface can be used to filter a list of filenames.
%i#e
The #ile class represents a file on the local filesystem. 6ou can use an instance of the #ile class to identify a
file, obtain information about the file, and e%en change information about the file. The easiest way to create a
#ile is to pass a filename to the #ile constructor, like this:
new #ile(,readme.t%t,)
Although the methods that the #ile class pro%ides for manipulating file information are relati%ely platform
independent, filenames must follow the rules of the local filesystem. The #ile class does pro%ide some
information that can be helpful in interpreting filenames and path specifications. The %ariable separator(har
specifies the system(specific character used to separate the name of a directory from what follows. +n a
$indows en%ironment, this is a backslash (7, while in a 0"+> or /acintosh en%ironment it is a forward slash
(B. 4ile separator can be obtained as !ystem.get*roperty('file.separator', which is how the 4ile class gets it.
6ou can create a #ile object that refers to a file called readme.t%t in a directory called m"$ir as follows:
new #ile(,m"$ir, 9 #ile.separator(har 9 ,readme.t%t,)
The #ile class also pro%ides some constructors that make this task easier. 4or example, there is a #ile
constructor that takes two strings as arguments: the first string is the name of a directory and the second string
is the name of a file. The following example does the exact same thing as the pre%ious example:
new #ile(,m"$ir, ,readme.t%t,)
The #ile class has another constructor that allows you to specify the directory of a file using a #ile object
instead of a Strin!:
#ile dir + new #ile(,m"$ir,)'
#ile f + new #ile(dir ,readme.t%t,)'
!ometimes a program needs to process a list of files that ha%e been passed to it in a string. 4or example, such a
list of files is passed to the 8a%a en%ironment by the (51SS31;K en%ironment %ariable and can be accessed by
the expression:
S"stem.!et3ropert"(,java.class.path,)
This list contains one or more filenames separated by separator characters. +n a $indows or /acintosh
en%ironment, the separator character is a semicolon (', while in a 0"+> en%ironment, the separator character
is a colon (J. The system(specific separator character is specified by the pathSeparator(har %ariable. Thus,
to turn the %alue of (51SS31;K into a collection of #ile objects, we can write:
Strin!;o:eniLer s'
Mector v + new Mector()'
s + new Strin!;o:eniLer(S"stem.!et3ropert"(,java.class.path,) #ile.pathSeparator)'
while (s.hasEore;o:ens())
v.add*lement(new #ile(s.ne%t;o:en()))'
6ou can retrie%e the pathname of the file represented by a #ile object with !et3ath(), the filename without
any path information with !et6ame(), and the directory name with !et3arent().
The #ile class also defines methods that return information about the actual file represented by a #ile object.
0se e%ists() to check whether or not the file exists. is$irector"() and is#ile() tell whether the file is a
file or a directory. +f the file is a directory, you can use list() to get an array of filenames for the files in that
directory. The canRead() and canWrite() methods indicate whether or not a program is allowed to read from
or write to a file. 6ou can also retrie%e the length of a file with len!th() and its last modified date with
lastEodified().
A few #ile methods allow you to change the information about a file. 4or example, you can rename a file with
rename() and delete it with delete(). The m:dir() and m:dirs() methods pro%ide a way to create directories
within the filesystem.
/any of these methods can throw a Securit"*%ception if a program does not ha%e permission to access the
filesystem, or particular files within it. +f a Securit"Eana!er has been installed, the chec:Read() and
chec:Write() methods of the Securit"Eana!er %erify whether or not the program has permission to access
the filesystem.
%i#ename%i#ter
The purpose of the #ilename#ilter interface is to pro%ide a way for an object to decide which filenames
should be included in a list of filenames. A class that implements the #ilename#ilter interface must define a
method called accept(). This method is passed a #ile object that identifies a directory and a Strin! that
names a file. The accept() method is expected to return true if the specified file should be included in the list,
or false if the file should not be included. &ere is an example of a simple #ilename#ilter class that only
allows files with a specified suffix to be in a list:
import java.io.#ile'
import java.io.#ilename#ilter'
public class Suffi%#ilter implements #ilename#ilter )
private Strin! suffi%'
public Suffi%#ilter(Strin! suffi%) )
this.suffi% + ,., 9 suffi%'
0
public boolean accept(#ile dir Strin! name) )
return name.endsWith(suffi%)'
0
0
A #ilename#ilter object can be passed as a parameter to the list() method of #ile to filter the list that it
creates. 6ou can also use a #ilename#ilter to limit the choices shown in a #ile$ialo!.
)andom-ccess%i#e
The Random1ccess#ile class pro%ides a way to read from and write to a file in a nonse<uential manner. The
Random1ccess#ile class has two constructors that both take two arguments. The first argument specifies the
file to open, either as a Strin! or a #ile object. The second argument is a Strin! that must be either ,r, or
,rw,. +f the second argument is ,r,, the file is opened for reading only. +f the argument is ,rw,, howe%er, the
file is opened for both reading and writing. The close() method closes the file. ?oth constructors and all the
methods of the Random1ccess#ile class can throw an IO*%ception if they encounter an error.
The Random1ccess#ile class defines three different read() methods for reading bytes from a file. The
Random1ccess#ile class also implements the $ataInput interface, so it pro%ides additional methods for
reading from a file. /ost of these additional methods are related to reading 8a%a primiti%e types in a machine(
independent way. /ultibyte <uantities are read assuming the most significant byte is first and the least
significant byte is last. All of these methods handle an attempt to read past the end of file by throwing an
*O#*%ception.
The Random1ccess#ile class also defines three different write() methods for writing bytes of output. The
Random1ccess#ile class also implements the $ataOutput interface, so it pro%ides additional methods for
writing to a file. /ost of these additional methods are related to writing 8a%a primiti%e types in a machine(
independent way. Again, multibyte <uantities are written with the most significant byte first and the least
significant byte last.
The Random1ccess#ile class would not li%e up to its name if it did not pro%ide a way to access a file in a
nonse<uential manner. The !et#ile3ointer() method returns the current position in the file, while the
see:() method pro%ides a way to set the position. 4inally, the len!th() method returns the length of the file in
bytes.

Vous aimerez peut-être aussi