Input and Output in Java
Byte- and Character-based I/O
File Objects
jonas.kvarnstrom@liu.se – 2015
Two forms of file access:
2
jonkv@ida
Introduction
A stream:
A sequence of elements
Made available one at a time
Sequential access
Used in most of Java's I/O classes
3
jonkv@ida
Streams 1: The Concept
4
Reading “raw” bytes
abstract class InputStream
Read a single byte or an array of bytes
InputStream is;
Reading from a file
is = new FileInputStream("java.dat");
Reading from an array in memory
is = new ByteArrayInputStream(…);
Reading from a network socket
is = socket.getInputStream();
…
Interfaces would have
been better – why?
Writing “raw” bytes
abstract class OutputStream
Write a single byte or an array of bytes
OutputStream is;
Writing to a file
is = new FileOutputStream("java.dat");
This is how you create an empty file!
Writing to an array in memory
is = new ByteArrayOutputStream(…);
Writing to a network socket
is = socket.getOutputStream();
…
One class for each source / destination
jonkv@ida
Streams 2: Binary I/O
A simple OutputStream example:
5
Declare an AutoCloseable
resource in try()… (Java 7+)
▪ public static void main(String[] args) {
try (OutputStream os = new FileOutputStream("java.dat")) {
This is
os.write(3);
Use it inside the block…
basically all os.write(new byte[] { 6, 7, 8 });
you can do! …
… and when you exit the block,
} catch (IOException e) {
the resource (file) will
… handle I/O errors that may arise
automatically be closed, even if
there is an exception!
when opening or using the stream…
}
▪
try ( InputStream is = new FileInputStream("foo.dat");
OutputStream os = new FileOutputStream("java.dat"))
{
Using two resources…
…
} catch (IOException e) {
Error handling is important!
… handle it …
Always make sure that every
}
file is closed!
}
jonkv@ida
Streams 3: Example
6
– Very little basic functionality… for a reason!
Division of responsibilities
”Basic” streams handle sources and destinations
Filter streams provide additional functionality
▪ Add buffering
▪ Support other types of data
▪ …
Your code
Filter Stream
Filter Stream
Basic Stream
jonkv@ida
Stream Filters 1: Introduction
7
A simple filter stream example:
▪ public class MyOutputStream {
private OutputStream out;
Your code
public MyOutputStream(final OutputStream out) {
this.out = out;
}
MyOutputStream
▪
public void write(byte b)
{ out.write(b); }
public void write(byte[] b)
{ out.write(b); }
…
FileOutputStream
▪
public void writeShort(short s) {
out.write((s & 0xFF00) >> 8);
…or any other
out.write(s & 0xFF);
”destination
}
stream”
…
}
▪ try (MyOutputStream out = new MyOutputStream(
new FileOutputStream("foo.dat"))) {
…
}
jonkv@ida
Stream Filters 2: How do they Work?
8
Useful output filters
BufferedOutputStream
Buffers I/O:
Don't write a single byte at a time…
PrintStream (System.out / err)
print(), println() methods
for primitive datatypes and Strings
Uses platform character encoding
to convert chars bytes
DataOutputStream
writeLong(), writeFloat(), …
writeUTF() – writes UTF-8 format
try (DataOutputStream os =
new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("java.dat"))))
{
os.write(new byte[] { 6, 7, 8 });
os.writeLong(1234567890123L);
os.writeFloat(2.7f);
} catch (final IOException e) {
… handle it …
}
jonkv@ida
Stream Filters 3: Output
Useful input filters
BufferedInputStream
Buffers I/O:
Don't read a single byte at a time…
DataInputStream
readLong(), readFloat(), …
readUTF() – reads UTF-8 format
readLine() – deprecated!
Ignores character encodings
Use Readers instead!
9
jonkv@ida
Stream Filters 4: Input
11
Distinct subsystem for text-based I/O: Reader, Writer
Sends full 16-bit Unicode text, not 8-bit bytes
Your code
Unicode
Unicode text
Filter Writer
Filter Reader
Unicode
Unicode
Filter Writer
Filter Reader
Unicode
Unicode
OutputStreamWriter
8-bit bytes
Your code
UTF-8:
“ä” c3 a4
ISO Latin-1: “ä” e4
OutputStream
InputStreamReader
8-bit bytes UTF-8:
c3 a4 “ä”
ISO Latin-1: c3 a4 “ä”
InputStream
jonkv@ida
Readers and Writers 2
12
Reading text
Writing text
abstract class Reader
abstract class Writer
Read a single char or an array of chars
Reader re;
Reading from a file
re = new FileReader("java.dat");
Reading from an array in memory
Read a single byte or an array of bytes
Writer wr;
Writing to a file
wr = new FileWriter("java.dat");
Writing to an array in memory
re = new CharArrayReader(…);
wr = new CharArrayWriter(…);
re = new StringReader(…);
wr = new StringWriter(…);
(writes to a StringBuffer)
…
…
No encoding specified: Use the platform’s
default to convert bytes chars
So don’t use this for files that should be
machine-readable on multiple systems!
jonkv@ida
Readers and Writers 3
13
Useful filters
Text output
BufferedWriter
Buffers I/O:
Don't write a single char at a time…
PrintWriter
print(), println() methods
for primitive datatypes and Strings
Text input
BufferedReader
Buffers I/O:
Don't read a single char at a time…
Method for reading a line
jonkv@ida
Readers and Writers 4: Filters
14
Specify a character encoding using OSW and ISR
OutputStreamWriter
OutputStream os =
new FileOutputStream("file.txt");
Writer wr =
new OutputStreamWriter(os, “Big5");
Your code
Unicode chars
OutputStreamWriter
Bytes in Big5 encoding
(Traditional Chinese)
FileOutputStream
InputStreamReader
Socket sock = …;
InputStream is = sock.getInputStream();
Reader re =
new InputStreamReader(is, “Cp1046”);
Your code
Unicode chars
InputStreamReader
Bytes in Cp1046
encoding (IBM arabic)
”SocketInputStream”
UTF-8 all characters supported, readable on most systems!
jonkv@ida
R/W 5: Specifying Encodings
File Objects (java.io.File) represent file and path names
They do not represent open files!
Also file system operations:
▪ File f = new File("/");
Find available space, total space,
File f2 = new File(f, "etc");
file system roots (C:\, D:\),
File f3 = new File(f, "passwd");
System.out.print(f3.getAbsolutePath());
if (f3.exists()) {
System.out.println("You have a password file");
System.out.println("It's in the directory " + f3.getParent());
System.out.println("Its length is " + f3.length());
if (f3.canRead()) System.out.println("I can read it");
if (f3.canWrite()) System.out.println("I can write to it");
if (f3.isHidden()) System.out.println("It is hidden");
if (f3.delete()) System.out.println("I have deleted it!");
try (OutputStream os = new FileOutputStream(f3)) { … };
}
File.createNewFile() is used for
atomic locking – just use a
FileOutputStream in most cases!
Also directory operations:
listFiles(), mkdir(),
renameTo(), …
16
jonkv@ida
File[name] Objects: The File Class
Object-based I/O:
Serialization
jonas.kvarnstrom@liu.se – 2015
18
Serialization: Convert objects to/from sequences of bytes
ObjectOutputStream
ObjectInputStream
OutputStream os =
new FileOutputStream("file.dat");
ObjectOutputStream out =
new ObjectOutputStream(os);
Writes an
out.writeObject(gameBoard);
out.writeObject(highscoreList); object and
everything it
out.close();
refers to!
Your code
Objects
ObjectOutputStream
Bytes: All you need to
reconstruct the objects
FileOutputStream
Socket sock = …;
InputStream is = sock.getInputStream();
ObjectInputStream in =
new ObjectInputStream(is);
List<Score> highscoreList =
(List<Score>) in.readObject();
in.close();
Your code
Objects
ObjectInputStream
Bytes
”SocketInputStream”
jonkv@ida
Serialization 1: Intro
19
The objects must implement java.io.Serializable
An interface without methods, indicating that serialization is allowed
▪ By accessing the byte stream you can read private fields!
▪ public class Pair implements Serializable {
private Object
first;
All fields must also be Serializable!
private Object
second;
private transient int hashCodeCache;
…except transient fields, which
Pair(Object first, Object second) {
this.first = first;
this.second = second;
}
we assume can be reconstructed
or are unnecessary for other reasons
}
The superclass must:
▪ Be Serializable, so we can save its data to the stream, or
▪ Have a no-args constructor, so we can reconstruct it from scratch
Many Java classes already implement Serializable
▪ Strings, Collections subclasses, …
jonkv@ida
Serialization 2: Serializable Interface
ObjectOutputStream must handle circular references
Node structure example:
▪ Node parent
= new Node(null);
Node child
= new Node(parent); // child points to parent
parent.addChild(node);
// parent points to child
Remembers which objects were written
▪ First time:
Write object ID + entire object representation
▪ Second time: Write object ID
Does not care whether the object was updated!
▪ List list = new ArrayList();
oos.write(list);
// Writes object ID + entire list
list.add("Another element");
oos.write(list);
// Writes the object ID…
To write a new copy of the object: Use reset()
▪ oos.reset();
20
jonkv@ida
Serialization 3: Writing An Object Twice
Can old saved objects be read after changing the class?
Some changes are allowed
▪ Adding fields – if you read an old object, the field will be set to 0/null
▪ Changing public/protected/private
▪ A few more types of changes
Others are forbidden
▪ Changing the class hierarchy in certain ways
▪ Removing Serializable
▪ …
You must have the same serial version ID
▪ By default this is a hash of certain features in the class — too strict!
▪ To allow adding new fields, declare your own version ID:
private final static long serialVersionUID = 1; // for example
▪ IMPORTANT! Change this if you make incompatible changes to your class!
21
jonkv@ida
Serialization 4: Class Versions
22
Error handling was omitted
▪
▪
▪
▪
▪
▪
ClassNotFoundException
InvalidClassException
StreamCorruptedException
OptionalDataException
NotSerializableException
IOException
– received an object of a non-existing class
– bad control information in the stream
– primitive data found instead of objects
– an object was not Serializable
– the usual Input/Output related exceptions
Many more serialization features…
▪ http://docs.oracle.com/javase/7/docs/technotes/guides/serialization/index.html
jonkv@ida
Serialization 5: Exceptions
24
How does your program find its image files, audio files, etc?
Your software may be installed in different locations
Path syntax depends on the OS
Your program, including images, can be packed inside a single JAR file
▪ Java ARchive, essentially a ZIP file
Resources reuse the Java class loading mechanism
Place files together with your code
Use resources to find and load them
Everything in a single JAR file:
mypackage/Main.class
mypackage/ShowImage.class
…
data/bin.dat
img/test.png
jonkv@ida
Resources 1: Data in the ClassPath
25
Since the class loading mechanism is used:
Must first have a ClassLoader or a java.lang.Class object
▪ Simplest way: SomeClassInYourProgram.class
Not a file name:
”.class” is magic syntax
Then, getResource() returns a java.net.URL
▪ URL url = Main.class.getResource("img/test.png");
Finally:
▪ Use the URL's getContent() method to return:
▪ an ImageProducer, for images
mypackage/Main.class
▪ an AudioClip,
for audio
mypackage/ShowImage.class
…
▪ an InputStream,
otherwise
data/bin.dat
▪ Or construct an ImageIcon from the URL!
img/test.png
▪ It calls getContent() for you
▪ ImageIcon icon = new ImageIcon(url);
jonkv@ida
Resources 2: Example
Most IDEs have a setting determining which files are resources
You place them in the source folders
Compilation copies them to output folders or JAR files
26
jonkv@ida
Resources 3: IDEs