Diferență între revizuiri ale paginii „Input/Output Streams”
(Nu s-au afișat 9 versiuni intermediare efectuate de același utilizator) | |||
Linia 9: | Linia 9: | ||
== Console Streams == | == Console Streams == | ||
+ | The Java language provides three types of standard streams for communicating with the console: | ||
+ | * standard input stream - type InputStream, used to read data; | ||
+ | * standard output stream - type PrintStream, used to display data; | ||
+ | * standard error stream - type PrintStream, used to display errors. | ||
− | + | In Java, all standard streams are accessible through class [http://docs.oracle.com/javase/7/docs/api/java/lang/System.html java.lang.System]. So, for standard input, there is [http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#in System.in], for standard output there is [http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#out System.out] and for standard error, there is [http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#err System.err]. The three members '''in''', '''out''' and '''err''' of class '''System''' are static. | |
− | |||
− | |||
− | |||
− | + | Classes that implement IO operations are placed in package [http://docs.oracle.com/javase/7/docs/api/java/io/package-summary.html java.io]. This package contains two categories of streams: bytes streams and character streams. Byte streams have been introduced from JDK version 1.0.2 and character streams are available since JDK 1.1. The latter ones do not replace, but complete stream functionality by being able to directly read and write characters (which in Java have 2 bytes each). | |
− | + | == Byte Input/Output Streams == | |
− | + | Bytes streams (as character streams) are split in two categories: input streams and output streams. | |
− | + | === Bytes Input Streams | |
− | + | [[Fișier:inputstream.png|Graphical representation of a generic InputStream and a FileInputStream]] | |
− | + | Classes implementing byte input streams are extended from [http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html java.io.InputStream], an | |
− | + | [[Java Syntax; A Program's Lexical Structure#Abstract Modifier|abstract]] class which offers generic read methods. The definition of the class is: | |
− | |||
<syntaxhighlight lang="Java"> | <syntaxhighlight lang="Java"> | ||
Linia 43: | Linia 43: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Method ''read()'', with no arguments, reads the next byte from the stream and return it as an '''int''' with values between 0 and 255. If the end of stream has been reached, it returns -1. | |
− | |||
− | |||
− | + | Methods ''read()'', having as arguments an array of bytes, read a number of ''len'' or the length of the array ''b'' (whichever is smaller) of bytes from the stream and write them in array ''b'' at index ''off'', if this is specified. They return the number of bytes read from the stream (and subsequently written in ''b'') or -1 if the end of stream has been reached. | |
− | + | Method ''skip()'' is used to discard a number of bytes from the input stream, specified in argument ''n''. | |
− | + | Methods ''mark()'' and ''reset()'' are used together, so that portions of the stream that have been already read can be read again. Through method ''mark()'', the current position in the stream is memorized, specifying the maximum size of the buffer that will store the following data through the argument ''readLimit'' that can be written before calling ''reset()''. The ''reset()'' method re-position the read index to the position where it was when the ''mark()'' method was called. These two methods are only valid if the stream supports marking. Checking for this is done by calling method ''markSupported()''. | |
− | + | Method ''available()'' returns the number of bytes available to be read from the stream without blocking execution. Be aware that some classes (like file streams) only return an estimate value when calling ''available()''. Check the documentation. | |
− | + | Method ''close()'' is used to close a stream. Once work with a stream is done, it needs to be closed in order to free the associated resources. Normally, JVM will automatically close all streams then the program ends, but a programmer should not count on this feature and clean up after him/herself. | |
− | |||
− | |||
− | |||
− | |||
+ | In order to use class '''InputStream''' in applications, it needs to be extended by classes that are connected to real data sources, existing in the system. Some of these classes, defined in Java, are: | ||
+ | * [http://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html ByteArrayInputStream] can read data from an array of bytes, acting as an input stream; | ||
+ | * [http://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html FileInputStream] oferă can read bytes coming from a file on the file system; | ||
+ | * [http://docs.oracle.com/javase/7/docs/api/java/io/SequenceInputStream.html SequenceInputStream] can combine multiple input streams in a single stream; | ||
+ | * [http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/AudioInputStream.html AudioInputStream] can read from an audio source. | ||
− | + | Another category of classes derived from '''InputStream''', this time though not directly, are filter classes, derived from [http://docs.oracle.com/javase/7/docs/api/java/io/FilterInputStream.html FilterInputStream] which is, in its turn, derived from '''InputStream'''. These types of classes do not offer support for any additional data sources but instead they work as a wrapper over exiting input streams, providing additional functionality. Examples of such classes are: | |
− | * [http://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html DataInputStream] | + | * [http://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html DataInputStream] is one of the most used filter classes. In contains several methods that can read primitive data types ('''int''', '''float''', etc.), in a system independent way. |
− | * [http://docs.oracle.com/javase/7/docs/api/java/io/PushbackInputStream.html PushbackInputStream] | + | * [http://docs.oracle.com/javase/7/docs/api/java/io/PushbackInputStream.html PushbackInputStream] offers the possibility of rewind and read data that has already been read. |
− | + | Next, an example of using class '''ByteArrayInputStream''': | |
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
byte _buffer[] = new byte[10]; | byte _buffer[] = new byte[10]; | ||
Linia 81: | Linia 80: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | By using class '''ByteArrayInputStream''', you can read data from an array using stream reading methods, without having to manually manage the current read index in the array. The connection is easily done by giving the existing array as an argument to the stream constructor. The example above creates a 10 bytes array, filling it with value from 0 to 9 and then creating a ByteArrayInputStream and using it to sequentially read the data, byte by byte and displaying it on the screen. You can also see that the reading is only done until the ''read()'' method returns -1, signaling the end of the stream, thus the end of the array. | |
+ | |||
+ | === Byte Output Streams === | ||
− | + | [[Fișier:outputstream.png|Graphical representation of a generic OutputStream and a FileOutputStream]] | |
− | [ | + | For writing data using streams, a class hierarchy is used, derived from class [http://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html java.io.OutputStream]]. Just like '''InputStream''', class '''OutputStream''' is abstract, offering an interface for declaring generic write methods. The class has the following definition: |
− | |||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
public abstract class OutputStream{ | public abstract class OutputStream{ | ||
Linia 98: | Linia 98: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Method ''write()'' writes the lest significant bytes of the argument, which is of type '''int''' to the stream. The other methods write the contents of a byte array ''b'' or a section of it, starting from position ''off'' and having a length of ''len''. | |
− | + | Method ''flush()'' forces writing data to the stream, and it is useful when a write buffer is used. | |
− | + | Method ''close()'' closes the stream and frees and resource associated with it. | |
− | + | Just like ''InputStream'', classes derived from ''OutputStream'' can be split in two categories: data streams ([http://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayOutputStream.html ByteArrayOutputStream], [http://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html FileOutputStream], etc.) which connect to a destination, and filter streams (derived from [http://docs.oracle.com/javase/7/docs/api/java/io/FilterOutputStream.html FilterOutputStream]) which are wrappers over the first ones, enhancing their functionality. | |
− | + | Standard output stream ('''System.out''') and standard error streams ('''System.err''') are static fields of class '''System''', of type [http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html PrintStream], which extends class '''FilterOutputStream'''. These are connected to the display and by conventions are used in two distinct situations: first to display messages for the program user, and the second, to display error messages (usually for debugging purposes). | |
− | + | Next, let's see an example of using a '''ByteArrayOutputStream''', used to display all 8-bits values: | |
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
ByteArrayOutputStream _buffer = new ByteArrayOutputStream(256); | ByteArrayOutputStream _buffer = new ByteArrayOutputStream(256); | ||
Linia 122: | Linia 122: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Class '''ByteArrayOutputStream''' corresponds to '''ByteArrayInputStream''' and allows the connection of a stream to a buffer (a byte array). The buffer is created when an object of type '''ByteArrayOutputStream''' is instantiated by using one of the two constructors. This class offers a method of storing data in memory before processing or sending them somewhere else. In order to transmit data, method ''writeTo()'' is used. | |
+ | In the example above, the buffer is written to the ''out'' stream, passed as a parameter. Opposite to class '''ByteArrayInputStream''', where the buffer was passed as an argument to the constructor, in the case of | ||
+ | '''ByteArrayOutputStream''', in order to obtain a reference to the buffer, a call to ''toByteArray()'' is required. This method returns a copy of the buffer. | ||
+ | |||
+ | == Character Input/Output Streams == | ||
− | + | Classes for character streams are extended from class [http://docs.oracle.com/javase/7/docs/api/java/io/Reader.html java.io.Reader] for reading data and http://docs.oracle.com/javase/7/docs/api/java/io/Writer.html java.io.Writer] for writing data. Most of these classes overlap with byte stream classes, having the same functionality. The difference between them is that '''InputStream/OutputStream''' classes work (read/ write) with bytes (8 bits), as '''Reader/Writer''' work with characters represented in the [http://en.wikipedia.org/wiki/Unicode Unicode] standard, on 16 bits. | |
− | + | The corespondence between bytes streams and character streams are as follow: | |
− | + | In case of input streams: | |
− | |||
* '''InputStream''' - [http://docs.oracle.com/javase/7/docs/api/java/io/Reader.html Reader] | * '''InputStream''' - [http://docs.oracle.com/javase/7/docs/api/java/io/Reader.html Reader] | ||
* '''ByteArrayInputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/CharArrayReader.html CharArrayReader] | * '''ByteArrayInputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/CharArrayReader.html CharArrayReader] | ||
* '''StringBufferInputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/StringReader.html StringReader] | * '''StringBufferInputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/StringReader.html StringReader] | ||
* '''FileInputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/FileReader.html FileReader] | * '''FileInputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/FileReader.html FileReader] | ||
− | * | + | * There are classes, like '''SequenceInputStream''' and '''DataInputStream''' that don't have a '''Reader''' version. |
− | + | In case of output streams: | |
* '''OutputStream''' - [http://docs.oracle.com/javase/7/docs/api/java/io/Writer.html Writer] | * '''OutputStream''' - [http://docs.oracle.com/javase/7/docs/api/java/io/Writer.html Writer] | ||
* '''ByteArrayOutputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/CharArrayWriter.html CharArrayWriter] | * '''ByteArrayOutputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/CharArrayWriter.html CharArrayWriter] | ||
* '''FileOutputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/FileWriter.html FileWriter] | * '''FileOutputStream''' – [http://docs.oracle.com/javase/7/docs/api/java/io/FileWriter.html FileWriter] |
Versiunea curentă din 15 decembrie 2013 11:59
A computer communicates with the exterior world through one or more communication interfaces, also called input-output (IO) ports. E.g.: serial port, parallel port, video port, audio port, etc. By using these interfaces, the computer is able to transmit and receive information to and from the outside world through different peripheral devices (monitor, printer, keyboard, mouse, modem, Ethernet card, etc.).
Input/Output Streams
Considering the large number of peripheral types, the constant development of new ones and also the fact that existing peripherals are being constantly upgraded, direct communication between them and the software programs would be difficult to achieve if it were to only use the processor instructions (in/out). Furthermore, the complexity of the communication with the peripheral devices gets even higher with different types of communication: sequential/ random, binary/ character/ line by line, etc. In order to help with these problems, device drivers were developed, which are software modules used to control the peripherals and provide a simpler communication interface, however, they don't completely solve the compatibility issues of the IO operations. As a result, the operating system also introduces a layer of abstraction, offering a more uniform way of transferring data to and from the peripheral devices. However, programming languages, like Java, are created so that can be used in several operating systems and so additional standard functions are required, defined in the programming language libraries, to communicate with devices, independently of the operating system.
In order to treat communication uniformly, Java uses the concept of stream. The notion has been invented by Dennis Ritchie, who implemented the first IO system based on streams, in the Unix operating system, in year 1984. A stream implies the creation of a communication channel, generally valid, between two entities, either software or hardware, with the condition that one entity is a source, and the other is a destination. So, the source will transmit (write) information in the stream, and the destination will receive (read) from the stream. This way, the stream allows treating any communication channel between any entities in the system in the same way. Defining a stream is done by defining its two ends (source and destination). Because there are two communication directions, we can separate streams into two categories: input streams and output streams. Input streams are streams that connect to devices that provides data (like keyboards) and output streams connect to devices that receive data (like the monitor). Both source and destination can be either a peripheral device or software component.
Console Streams
The Java language provides three types of standard streams for communicating with the console:
- standard input stream - type InputStream, used to read data;
- standard output stream - type PrintStream, used to display data;
- standard error stream - type PrintStream, used to display errors.
In Java, all standard streams are accessible through class java.lang.System. So, for standard input, there is System.in, for standard output there is System.out and for standard error, there is System.err. The three members in, out and err of class System are static.
Classes that implement IO operations are placed in package java.io. This package contains two categories of streams: bytes streams and character streams. Byte streams have been introduced from JDK version 1.0.2 and character streams are available since JDK 1.1. The latter ones do not replace, but complete stream functionality by being able to directly read and write characters (which in Java have 2 bytes each).
Byte Input/Output Streams
Bytes streams (as character streams) are split in two categories: input streams and output streams.
=== Bytes Input Streams
Classes implementing byte input streams are extended from java.io.InputStream, an abstract class which offers generic read methods. The definition of the class is:
public abstract class InputStream{
public abstract int read() throws IOException;
public int read(byte b[]) throws IOException;
public int read(byte b[], int off, int len) throws IOException;
public long skip(long n) throws IOException;
public int available() throws IOException;
public void close() throws IOException;
public synchronized void mark(int readlimit);
public synchronized void reset() throws IOException;
public boolean markSupported();
}
Method read(), with no arguments, reads the next byte from the stream and return it as an int with values between 0 and 255. If the end of stream has been reached, it returns -1.
Methods read(), having as arguments an array of bytes, read a number of len or the length of the array b (whichever is smaller) of bytes from the stream and write them in array b at index off, if this is specified. They return the number of bytes read from the stream (and subsequently written in b) or -1 if the end of stream has been reached.
Method skip() is used to discard a number of bytes from the input stream, specified in argument n.
Methods mark() and reset() are used together, so that portions of the stream that have been already read can be read again. Through method mark(), the current position in the stream is memorized, specifying the maximum size of the buffer that will store the following data through the argument readLimit that can be written before calling reset(). The reset() method re-position the read index to the position where it was when the mark() method was called. These two methods are only valid if the stream supports marking. Checking for this is done by calling method markSupported().
Method available() returns the number of bytes available to be read from the stream without blocking execution. Be aware that some classes (like file streams) only return an estimate value when calling available(). Check the documentation.
Method close() is used to close a stream. Once work with a stream is done, it needs to be closed in order to free the associated resources. Normally, JVM will automatically close all streams then the program ends, but a programmer should not count on this feature and clean up after him/herself.
In order to use class InputStream in applications, it needs to be extended by classes that are connected to real data sources, existing in the system. Some of these classes, defined in Java, are:
- ByteArrayInputStream can read data from an array of bytes, acting as an input stream;
- FileInputStream oferă can read bytes coming from a file on the file system;
- SequenceInputStream can combine multiple input streams in a single stream;
- AudioInputStream can read from an audio source.
Another category of classes derived from InputStream, this time though not directly, are filter classes, derived from FilterInputStream which is, in its turn, derived from InputStream. These types of classes do not offer support for any additional data sources but instead they work as a wrapper over exiting input streams, providing additional functionality. Examples of such classes are:
- DataInputStream is one of the most used filter classes. In contains several methods that can read primitive data types (int, float, etc.), in a system independent way.
- PushbackInputStream offers the possibility of rewind and read data that has already been read.
Next, an example of using class ByteArrayInputStream:
byte _buffer[] = new byte[10];
for(byte i = 0; i < _buffer.length; i++){
_buffer[i] = i;
}
ByteArrayInputStream _bufferStream = new ByteArrayInputStream(_buffer);
int _byteRead;
while((_byteRead = _bufferStream.read()) != -1){
System.out.print(” ” + _byteRead);
}
System.out.println();
By using class ByteArrayInputStream, you can read data from an array using stream reading methods, without having to manually manage the current read index in the array. The connection is easily done by giving the existing array as an argument to the stream constructor. The example above creates a 10 bytes array, filling it with value from 0 to 9 and then creating a ByteArrayInputStream and using it to sequentially read the data, byte by byte and displaying it on the screen. You can also see that the reading is only done until the read() method returns -1, signaling the end of the stream, thus the end of the array.
Byte Output Streams
For writing data using streams, a class hierarchy is used, derived from class java.io.OutputStream]. Just like InputStream, class OutputStream is abstract, offering an interface for declaring generic write methods. The class has the following definition:
public abstract class OutputStream{
public abstract void write(int i) throws IOException;
public void write (byte b[]) throws IOException;
public void write (byte b[], int off, int len) throws IOException;
public long flush() throws IOException;
public void close() throws IOException;
}
Method write() writes the lest significant bytes of the argument, which is of type int to the stream. The other methods write the contents of a byte array b or a section of it, starting from position off and having a length of len.
Method flush() forces writing data to the stream, and it is useful when a write buffer is used.
Method close() closes the stream and frees and resource associated with it.
Just like InputStream, classes derived from OutputStream can be split in two categories: data streams (ByteArrayOutputStream, FileOutputStream, etc.) which connect to a destination, and filter streams (derived from FilterOutputStream) which are wrappers over the first ones, enhancing their functionality.
Standard output stream (System.out) and standard error streams (System.err) are static fields of class System, of type PrintStream, which extends class FilterOutputStream. These are connected to the display and by conventions are used in two distinct situations: first to display messages for the program user, and the second, to display error messages (usually for debugging purposes).
Next, let's see an example of using a ByteArrayOutputStream, used to display all 8-bits values:
ByteArrayOutputStream _buffer = new ByteArrayOutputStream(256);
try{
for(int i=0;i<256;i++) {
_buffer.write(i);
}
_buffer.writeTo(System.out);
byte[] _tablou = _buffer.toByteArray();
}catch(IOException _e){
System.out.println("Eroare "+ _e.getMessage());
}
Class ByteArrayOutputStream corresponds to ByteArrayInputStream and allows the connection of a stream to a buffer (a byte array). The buffer is created when an object of type ByteArrayOutputStream is instantiated by using one of the two constructors. This class offers a method of storing data in memory before processing or sending them somewhere else. In order to transmit data, method writeTo() is used. In the example above, the buffer is written to the out stream, passed as a parameter. Opposite to class ByteArrayInputStream, where the buffer was passed as an argument to the constructor, in the case of ByteArrayOutputStream, in order to obtain a reference to the buffer, a call to toByteArray() is required. This method returns a copy of the buffer.
Character Input/Output Streams
Classes for character streams are extended from class java.io.Reader for reading data and http://docs.oracle.com/javase/7/docs/api/java/io/Writer.html java.io.Writer] for writing data. Most of these classes overlap with byte stream classes, having the same functionality. The difference between them is that InputStream/OutputStream classes work (read/ write) with bytes (8 bits), as Reader/Writer work with characters represented in the Unicode standard, on 16 bits.
The corespondence between bytes streams and character streams are as follow:
In case of input streams:
- InputStream - Reader
- ByteArrayInputStream – CharArrayReader
- StringBufferInputStream – StringReader
- FileInputStream – FileReader
- There are classes, like SequenceInputStream and DataInputStream that don't have a Reader version.
In case of output streams:
- OutputStream - Writer
- ByteArrayOutputStream – CharArrayWriter
- FileOutputStream – FileWriter