java - processing input and output

30
PROCESSING INPUT AND OUTPUT PROGRAMMAZIONE CONCORRENTE E DISTR. Università degli Studi di Padova Dipartimento di Matematica Corso di Laurea in Informatica, A.A. 2015 – 2016 [email protected]

Upload: riccardo-cardin

Post on 13-Apr-2017

662 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Java - Processing input and output

PROCESSING INPUT AND OUTPUTPROGRAMMAZIONE CONCORRENTE E DISTR.Università degli Studi di Padova

Dipartimento di Matematica

Corso di Laurea in Informatica, A.A. 2015 – [email protected]

Page 2: Java - Processing input and output

2Programmazione concorrente e distribuita

SUMMARY Introduction Obtaining streams Reading / writing bytes Character encodings Text input / output Random access files Processing files URLs Serialization

Riccardo Cardin

Page 3: Java - Processing input and output

3Programmazione concorrente e distribuita

INTRODUCTION Java provides an elegant API to read and write

data in binary and text formatThe API let’s you work in the same way with files,

directories, web pages and so onA source from which one can read bytes is called an

input stream Bytes can come from a file, a network connection or an array

in memoryA destination for bytes in an output stream In contrast readers and writers consume and produce

sequences of characters

Riccardo Cardin

Page 4: Java - Processing input and output

4Programmazione concorrente e distribuita

OBTAINING STREAMS A stream can be obtained from different sources

From a file

From an URL

From an array of bytes

Once the stream is obtained we can I/O from and to the source using the same API

Riccardo Cardin

InputStream in = Files.newInputStream(path);OutputStream out = Files.newOutputStrem(path);

URL url = new URL("http://rcardin.github.io");InputStream in = url.openStream();

byte[] bytes = /* ... */;InputStream in = new ByteArrayInputStream(bytes);OutputStream out = new ByteArrayOutputStream();bytes = out.toByteArray();

Page 5: Java - Processing input and output

5Programmazione concorrente e distribuita

READING BYTES The type to read bytes from a source is java.io.InputStream An input stream can read a single byte

Cast to byte only after you’ve checked that is not -1Or it can read in bulk into a byte array

Riccardo Cardin

InputStream in = /* ... */;// A byte is an integer from 0 to 255. -1 is reserved to the // end of the input streamint b = in.read();

bytes[] bytes = /* ... */;// Returns the number of actual read bytesint actualBytesRead = in.read(bytes);// Writes the bytes from a position of the array, for at max // ‘length’ number of bytesactualBytesRead = in.read(bytes, start, length);

Page 6: Java - Processing input and output

6Programmazione concorrente e distribuita

WRITING BYTES The type to write bytes to a target is java.io.OutputStream Output stream can write a single byte or a bytes array

When done, you have to close streams Streams implement AutoClosable and so you can use a try-

with-resources statements

Riccardo Cardin

OutputStream in = /* ... */;int b = /* ... */;out.write(b);byte[] bytes = /* ... */;out.write(bytes);out.write(bytes, start, length)

try (OutputStream out = /* ... */) { out.write(bytes);}

Page 7: Java - Processing input and output

7Programmazione concorrente e distribuita

OBTAINING STREAMS

Riccardo Cardin

Page 8: Java - Processing input and output

8Programmazione concorrente e distribuita

CHARACTER ENCODINGS In many cases you will interpret bytes as a

sequence of charactersHow such characters were encoded? Java uses Unicode standard for characters

Each char, or code point, has a 21-bit integer numberUTF-8 encondes each Unicode code point into a

sequence of one to four bytes ASCII character set are represented with only 1 byte

UTF-16 encodes Unicode code points into one or two 16-bit values This encoding is the default used in Java strings

Riccardo Cardin

Page 9: Java - Processing input and output

9Programmazione concorrente e distribuita

CHARACTER ENCODINGS There is no realiable way to automatically detect the

encoding from a stream of bytesYou should always explicitly specify the encoding using StandardCharsets class

Use the Charset object when reading or writing text

If you specify nothing, the computer default charset is used

Riccardo Cardin

// Values are of type CharsetStandardCharsets.UTF_8StandardCharsets.UTF_16StandardCharsets.UTF_16BEStandardCharsets.UTF_16LEStandardCharsets.ISO_8859_1StandardCharsets.US_ASCII

String str = new String(bytes, StandardCharsets.UTF_8)

Page 10: Java - Processing input and output

10Programmazione concorrente e distribuita

TEXT INPUT To read text input use a Reader

Obtain a reader from an input stream using an InputStreamReader decorator

It is not very convenient to read a char at time If you want to read an input line by line, usa the

decorator class BufferedReader

Riccardo Cardin

// Here you can view the "onion" structureReader in = new InputStreamReader(new InputStream(/*...*/, charset);// Reads a code unit between 0 and 65536, or -1int ch = in.read();

try (BufferedReader reader = new BufferedReader(new InputStreamReader( new InputStream(/*...*/)) { // A null is returned when the stream is done String line = reader.readLine();}

Page 11: Java - Processing input and output

11Programmazione concorrente e distribuita

TEXT OUTPUT To write text us the class Writer

To turn an output stream to a writer use OutputStreamWriter decorator

The write method writes strings to the streamClass PrintWriter adapts the interface of writers to the print, println and printf used with System.out

StringWriter lets you to write a stream into a String You can combine it with a PrintWriter

Riccardo Cardin

Writer out = new OutputStreamWriter( new OutputStream(/*...*/), charset);out.write("Any string");

PrintWriter wrt = new PrintWriter(out, "UTF-8");wrt.println("Any string");

Page 12: Java - Processing input and output

12Programmazione concorrente e distribuita

TEXT OUTPUT

Riccardo Cardin

Page 13: Java - Processing input and output

13Programmazione concorrente e distribuita

DEALING WITH BINARY DATA The DataInput type reads from binary source

The DataOutput type writes in binary formatDealing with binary data is useful beacuse it is fixed in

width and efficient No parsing operation is needed

The classes DataInputStream and DataOutputStream adapt stream to the interface

Riccardo Cardin

byte readByte();char readChar();int readInt();long readLong();// ...

DataInput in = new DataInputStream(Files.newInputStream(path));DataOutput out = new DataOutputStream(Files.newOutputStream(path));

Page 14: Java - Processing input and output

14Programmazione concorrente e distribuita

RANDOM ACCESS FILES The type RandomAccessFile lets you read or

write data anywhere in a file Implements DataInput / DataOutput interfacesUse "r" to open in read mode, "rw" in read-write

Such a file has a pointer that indicates the position of the next byte Use the seek method to position the pointer inside the file

Riccardo Cardin

RandomAccessFile file = new RandomAccessFile(path.toString(), "rw");

// Read the next integer in the fileint value = file.readInt();// Move the pointerfile.seek(file.getFilePointer(), 4);// Write an integer to the filefile.writeInt(value + 1);

Writing moves the pointer to the next sequence of bytes

Page 15: Java - Processing input and output

15Programmazione concorrente e distribuita

FILE LOCKING If more than a program tries to modify the same

file, it can easily become damagedThe FileLock solves the problem

Use the lock method to lock a file Use the tryLock method to verify if a file is locked

Returns null if the lock is not available

Use a FileChannel to obtain the lock The file remains locked until the lock or the channel is closed

It is best to use try-with-resourcesRiccardo Cardin

FileChannel channel = FileChannel.open(path);FileLock lock = channel.lock();// orFileLock lock = channel.tryLock()

Page 16: Java - Processing input and output

16Programmazione concorrente e distribuita

FILE CREATION A Path is a sequence of directory names,

optionally followed by a file name If the first component is a root element, then the

path is absolute, otherwise is relative Root elements may be «/» or «C:\»

The Paths class is a companion class with a lot of utilities An InvalidPathException will be thrown if the path is

not valid in the given filesystemA Path does not have to correspond to a file that

actually existsRiccardo Cardin

Path abs = Paths.get("/", "home", "rcardin");Path rel = Paths.get("home", "rcardin");Path another = Paths.get("/home/rcardin");

Page 17: Java - Processing input and output

17Programmazione concorrente e distribuita

FILE CREATION Create a directory

Create only the last part of the path

Create also intermediate directory as well

Create a file

Throws an exception if the file already exists Check for existence and creation are an atomic operation

Riccardo Cardin

Files.createDirectory(path);

Files.createDirectories(path);

Files.createFile(path);

// Checks if a file already existsFiles.exists(path);Files.isDirectory(); // Test if the path is a directoryFiles.isRegularFile(); // Test if the path is a regular file

Page 18: Java - Processing input and output

18Programmazione concorrente e distribuita

FILE CREATION It’s possible to create temporary file / folders

Names of temp files and folders are generated randomly

It is possible to give a prefix, a suffix and a target path If no path is given, the default SO temporary folder is used

The file / folder will not be deleted automatically on JVM termination Call File.deleteOnExit() or specify the attribute StandardOpenOption.DELETE_ON_CLOSE during creation

Riccardo Cardin

Files.createTempFile(dir, prefix, suffix);Files.createTempDirectory(dir, prefix)

Files.createTempDirectory(dir, prefix, StandardOpenOption.DELETE_ON_CLOSE);

Page 19: Java - Processing input and output

19Programmazione concorrente e distribuita

OPERATIONS ON FILES Abstractions on file serve to allow you to

operate on them It’s possible to copy or move a file or an empty dir.

If the StandardCopyOperation.REPLACE_EXISTING is not set, the above operations will fail if the target exists

With StandardCopyOperation.REPLACE_EXISTING you can specify to maintain the source file if the operation fails

It’s possible to delete a file or an empty directory

Riccardo Cardin

Files.copy(fromPath, toPath);// Moves a file or an empty directoryFiles.move(fromPath, toPath);

Files.delete(path)boolean deleted = Files.deleteIfExists(path)

Page 20: Java - Processing input and output

20Programmazione concorrente e distribuita

OPERATIONS ON FILES It is possible to walk through a file tree

Use the walkFileTree method

The FileVisitor interface defines method that are called prior, during and post directory visit

The class SimpleFileVisitor gives a wrapper implementation

The FileVisitResult defines how to continue the walking process

Riccardo Cardin

// The second argument is an implementation of FileVisitorFiles.walkFileTree(startingDir, fv);

FileVisitResult postVisitDirectory(T dir, IOException exc)FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)FileVisitResult visitFile(T file, BasicFileAttributes attrs)FileVisitResult visitFileFailed(T file, IOException exc)

Page 21: Java - Processing input and output

21Programmazione concorrente e distribuita

OPERATIONS ON FILES

Riccardo Cardin

public static class PrintFiles extends SimpleFileVisitor<Path> { // Print information about each type of file. @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attr) { if (attr.isSymbolicLink()) { System.out.format("Symbolic link: %s ", file); } else if (attr.isRegularFile()) { System.out.format("Regular file: %s ", file); } else { System.out.format("Other: %s ", file); } return CONTINUE; } // Print each directory visited. @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) { System.out.format("Directory: %s%n", dir); return CONTINUE; }}

Page 22: Java - Processing input and output

22Programmazione concorrente e distribuita

OPERATIONS ON FILES

Riccardo Cardin

Page 23: Java - Processing input and output

23Programmazione concorrente e distribuita

URL CONNECTIONS The simplest method to read from an URL is to

get an input stream from it

Using URLConnection it is possible to retrieve additional resources from URL and to write to it The type has a subtype for each type of URL

Send data to the server using an output stream

Riccardo Cardin

// Opens an input stream on the URLInputStream in = url.openStream();

// From an HTTP URL returns an HttpURLConnectionURLConnection con = url.openConnection();

con.setDoOutput(true);try (OutputStream out = con.getOutputStream()) { // Write to out}

Page 24: Java - Processing input and output

24Programmazione concorrente e distribuita

SERIALIZATION Representation of an object as a sequence of bytes,

that includes data as well as typeThe process is JVM independent The type must implement java.io.Serializable

Marker interface with no methods

All fields in the class must be serializable. If a field is not, it must be marked as transient Transient fields are not serialized and are lost intentionally A transient variable cannot be final or static

Riccardo Cardin

public class Employee implements Serializable { private String name; private double salary; // ...}

Page 25: Java - Processing input and output

25Programmazione concorrente e distribuita

SERIALIZATION Serialization process uses the stream API

To serialize objects, use an ObjectOutputStream

The writeObject method serializes the objectTo deserialize objects, use an ObjectInputStream

The readObject does the magicSerialization process is recursive on object attributes

Name of class and name / values of attributes are savedRiccardo Cardin

ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(path));Employee paul = new Employee("Paul", 29000D);out.writeObject(paul);

ObjectInputStream in = new ObjectInputStream(Files.newInputStream(path));Employee paul = (Employee) in.readObject();

Page 26: Java - Processing input and output

26Programmazione concorrente e distribuita

SERIALIZATION Serialization works fine with duplicated objects

Each object gets a serial number when it is saved An ObjectOutputStream checks if an object was previously

written with the same serial number. In that case, it just write out the serial number

The ObjectInputStream works conversely It is possible to tweak the serialization process

Redefine readObject and writeObject methods

Use defaultWriteObject and defaultReadObject on streamsRiccardo Cardin

// Used to deserialize an objectprivate void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException// Used to serialize an objectprivate void writeObject(ObjectOutputStream out) throws IOException

Page 27: Java - Processing input and output

27Programmazione concorrente e distribuita

SERIALIZATION Versioning

If you use serialization for long term persistence, you need to consider what happens when classes evolve How do we deserialize objects into new versions of a class?

Serialization supports versioning Assign a serialVersionUID to a Serializable class. The

version uid is written with other information

When the class change in an incompatible way, modify the version uid If uids are different, an InvalidClassException is thrown

Default uid is generated from hash code of the class

Riccardo Cardin

Private static final long serialVersionUID = 1L;

Page 28: Java - Processing input and output

28Programmazione concorrente e distribuita

SERIALIZATION

Riccardo Cardin

Page 29: Java - Processing input and output

29Programmazione concorrente e distribuita

EXAMPLES

Riccardo Cardin

https://github.com/rcardin/pcd-snippets

Page 30: Java - Processing input and output

30Programmazione concorrente e distribuita

REFERENCES Chap. 9 «Processing Input and Output», Core Java for the

Impatient, Cay Horstmann, 2015, Addison-Wesley Walking the File Tree https://

docs.oracle.com/javase/tutorial/essential/io/walk.html

Riccardo Cardin