Lecture 17: I/O

We have a change of plans. Originally we planned to do Collections and Generics, but instead we will do IO now. 

Reading

JP chapter 23.

Study Guide

In this lecture will shall look at I/O (Input/Output) and its different usages. I/O is a universal issue for any programming language to handle - we shall of course look at Javas way of implementing it.

I/O is basicly about getting access to external resources - it is used whenever a program wants to get information from or send information to sources outside itself.

The task of implementing an I/O library is a challenging one, since such a library has to provide functionality for communicating with a number of different media (files, the console, network connections), in a wide variety of ways (sequential, random-access, buffered, binary, character, by lines, by words, etc.).

The way Java has decided to solve this problem is to have a number of classes with basic functionality, and a number of classes with additional functionality that the programmer can wrap the basic classes with. This approach of course gives a high level of flexibility, but also explains why the I/O library seems, at a first glance, at best complex, if even not completely confusing and incomprehensable.

The lecture and excercises will hopefully guide you through the jungle of Java I/O, and equip you with an understanding which will make it possible for you to find your way through on your own.

When reading the pages in JP see if you can find answers to the following questions:

Excercises for lecture 5

  1. (Hand-In) Working with files and directories

    Write a class FileInfo.java, which takes the path of a directory as parameter to the constructor (so that you e.g. can make a FileInfo object with this call: FileInfo fi = new FileInfo("c:/oop/lecture5/excercises");).

    1. Write a method which counts and prints out how many files there are in the directory (you should not consider subdirectories yet).
    2. Write a method that prints out the size in bytes of all the files in the directory.
    3. Write a method which takes a String parameter, which indicates the types of files which should be counted, e.g. that you only want to count the .class files in the directory. The method should print out the number of files.
    4. Write a method that recursively counts the number of files in the directory AND in all subdirectories.

  2. NOT MANDATORY: Make a new type of Writer

    In this excercise you should make a class called WriterFork.java, which extends java.io.Writer. The idea of this class is that it is connected to two other writers, which it writes to whenever somebody calls its write() method. The WriterFork should get references to these two other writers in its constructor, like this: public WriterFork(Writer a, Writer b). If we call write("Hello") on the WriterFork object, it should call write("Hello") on both its Writers. Write a test program with a main method that tests if the WriterFork is working as intended, e.g. make it write to both a file and the console.


  3. (Hand-IN) A logging facility

    This excercise is about the construction of a logging facility, which should keep a log file of everything that one might want to monitor in a program execution (similar to the way System.out.println is often used).

    1. Write a class LoggingFacility with a static method log(String s). This method should write the String s to a file called log.txt. Make a test, where you use the logging facility when you execute another program (call LoggingFacility.log("something"), where you would normally have used a System.out.println). You should not be concerned that the log.txt is overwritten everytime you run the program.
    2. Extend the logging facility with two methods, setLogToFile() and setLogToConsole(), which are used to indicate whether the log should write to a file or to the console.
    3. NOT MANDATORY: Change the program so that log files are never overwritten: Give the log files names which indicate their numbers, e.g. log-1.txt, log-2.txt, log-3.txt, etc. You should get the names of all existing log files, extract the biggest number, and name the new log file with a number just above that number. Write a test to see if it works.

  4. (Hand-IN) Serialization of objects

    In this excercise you will make some experiments with object serialization using ObjectOutputStreams and ObjectInputStreams.

    1. Save a couple of objects which refer to each other using an ObjectOutputStream (you might use the Persons and Cars from a previous excercise). Try reading them in again with an ObjectInputStream.
    2. Save the objects again, change one of the objects, and save them again. Read them in again. Has the change been saved?
    3. Try to save an object with a reference to another object which do not implement the Serializable interface. What happens?
    4. Save an object, remove its .class file, and try to read it in again. What happens?

  5. NOT MANDATORY: Client/server communication based on Sockets

    In this excercise you should write a client and a server communicating through sockets. You can use the example in JP page 105 as inspiration. The server should answer requests about taxes: when the client provides the server with information about how much he or she has earned, the server replies with a calculation of how much tax the client should pay. You are free to implement it with the tax rate of your dreams...