Input and Output in Java

Java's input and output scheme is undeniably a good idea, but still needs some work. There are just too many un-memorable classes involved. Even the simple act of reading a line from standard input requires a sequence of conversions that even now I can't remember. Ploughing through the documentation to be reminded how to do every little operation is not a reasonable use of time. This "page" attempts to summarise things in a convenient way.

After the Quick Summary there is a more detailed introduction with links to details specific to each class mentioned. Here are the direct links:
InputStream; InputStreamReader; BufferedReader; StringTokenizer; FileReader; LineNumberReader; format conversions; redirecting input;
OutputStream; PrintStream; PrintWriter; FileWriter; redirecting output;
internet Sockets; multithreaded servers; IOException; System Properties;

Quick Summary

To print on standard output:
        System.out.println(something);
To read a line from standard input:
        InputStreamReader ISRin=new InputStreamReader(System.in);
        BufferedReader in=new BufferedReader(ISRin);
        String s=in.readLine();
To convert a string to an int:
        try { i=Integer.parseInt(s); }
        catch (NumberFormatException e) { ... }
To write something to a file:
        FileWriter fw=new FileWriter("filename");
        PrintWriter fout=new PrintWriter(fw);
        fout.println(something);
        fout.close();
To read a line from a file:
        FileReader fr=new FileReader("filename");
        BufferedReader fin=new BufferedReader(fr);
        String s=fin.readLine();
        fin.close();


The General Outline

System.in is an
InputStream. All you can do with it is read bytes (numeric ascii codes).
Normally you convert System.in to a InputStreamReader, then into a BufferedReader.
System.out is a PrintStream. Surprisingly, a PrintStream is quite useful, with println etc. Absurdly, PrintStreams are "deprecated" (i.e. old and frowned upon). We are supposed to use PrintWriters instead. So why isn't System.out now a PrintWriter??? Make a PrintWriter out of it with new PrintWriter(System.out)
System.err is also a PrintStream, usually used for reporting errors instead of System.out.
Redirecting i/o is possible. see setIn and setOut for details.
Files are conveniently accessed through FileReaders and FileWriters.
Internet input and output is quite simple, through Sockets.
Numeric or any other Non-string input must be performed by reading Strings then converting them to the desired type.
System.getProperty can be used to find useful system-dependent information, such as what characters separate directories in paths ('/' in unix, '\' in dos, etc.) and what characters appear at the end of a proper text line. See getProperty.
Exceptions: IOException is thrown by most i/o methods.

System Properties
System.getProperty(String propertyname) returns a String describing the named system-dependent properties, or null if there is no such property. Examples are:
        "java.version" returns e.g. "1.1.5"
        "os.name" returns e.g. "VAX/VMS" or (if you're unlucky) "Windows 95"
        "os.arch" (architecture) returns e.g. "x86"
        "os.version" returns e.g. "7.5"
        "file.separator" returns e.g. "/" for unix, "\" for dos
        "path.separator" returns e.g. ";" (between entries in PATH variable)
        "line.separator" returns e.g. "\r\n" for dos, "\n" for unix
        "user.name" returns current user's login (account) name
        "user.home" returns user's home directory (full path)
        "user.dir" returns the current working directory. (full path)

Redirecting standard input and output streams
System.setIn(InputStream i) changes where System.in reads from; you must make a
InputStream to use it.
System.setOut(PrintStream o) and System.setErr(PrintStream e) change where standard output and standard error print to. You need to make a PrintStream to use them, even though PrintStreams are deprecated.

IOException is an exception thrown by most of the i/o methods. You must either put every i/o operation inside a try like this:
            try
            { int i=System.in.read();
              System.out.println("Received byte "+i); }
            catch (IOException e)
            { ... do something to deal with it ... }
How you deal with the exception is up to you. You are free to completely ignore it once it has been caught
        If you want to take note of the exception, there are a few semi-helpful methods beloning to all exceptions: For a realy serious error, the best solution may be to print a message on System.err or System.out, then call System.exit(1) to kill the program. (Note that applets usually can't exit).

        The other alternative is to declare that the method you are writing may throw IOException like this:
          public int getInput() throws IOException
          { ... do anything you like,
                forgetting that IOException even exists ... }
This puts the responsibility for catching IOException on whoever calls your method. It is acceptable to declare that main throws IOException.

OutputStream methods:
(All methods throw
IOException)
An OutputStream as relatively lame, normally it should be converted into a PrintWriter before use, thus:
        OutputStream OSout= any OutputStream
        PrintWriter PWout=new PrintWriter(OSout);


InputStream methods:
(All methods throw
IOException; System.in is an InputStream.)
An InputStream as relatively lame, normally it should be converted into a BufferedReader before use, thus:
        InputStream ISin= any InputStream, maybe System.in
        InputStreamReader ISRin=new InputStreamReader(ISin);
        BufferedReader BRin=new BufferedReader(ISRin);


An InputStreamReader puts a civilising layer on top of an InputStream. InputStreams deal with raw, unprocessed bytes; InputStreamReaders convert them into proper characters. The change is subtle, but usually necessary.
        InputStreamReader ISRin=new InputStreamReader(System.in);
is usually a good thing to do, but see BufferedReader too.
The constructor InputStreamReader(InputStream old) accepts any InputStream. InputStreamReader methods are:

(All methods throw IOException.)

A BufferedReader adds efficiency to any kind of Reader. Unbuffered Readers do real input operations exactly as and when requested by the program, so reading jst a few characters at a time can be very inefficient. A BufferedReader always tries to read a lot of characters, so the next time your program has to read, they are likely to be already available.
        InputStreamReader ISRin=new InputStreamReader(System.in);
        BufferedReader BRin=new BufferedReader(ISRin);
is usually a good thing to do. So is:
        FileReader FRfile=new FileReader("filename.ext");
        BufferedReader BRfile=new BufferedReader(FRfile);
If you want the system to keep track of line numbers for you, convert the BufferedReader into a LineNumberReader with this extra step:
        LineNumberReader LNRin=new LineNumberReader(BRin);
The constructor BufferedReader(Reader old) accepts any Reader. BufferedReader methods are the same as InputStreamReader methods, with the addition of readLine():
(All methods throw
IOException.)

PrintStream methods:
DEPRECATED, use a
PrintWriter instead.
These methods NEVER throw IOException.

PrintWriter methods:
        Printwriter out=new PrintWriter(System.out);
is a useful thing to do.
These methods NEVER throw IOException.
A PrintWriter has exactly the same methods as a PrintStream, but is not deprecated.

A FileReader is a kind of InputStreamReader, and so is treated in the same way. A FileReader is created by:
The constructor FileReader(String name) which automatically opens the file. The constructor may throw FileNotFoundException.
It is normal to convert a FileReader into a BufferedReader like this:
        FileReader FRfile=new FileReader("input.txt");
        BufferedReader BRfile=new BufferedReader(FRfile);
before using it.

A FileWriter is a kind of OutputStreamWriter, which is a kind of Writer, so it can be converted into a PrintWriter for convenient use. The constructor FileWriter(String name) automatically creates the file and may throw IOException.
If you want to write to the end of an already existing file, use the alternate constructor FileWriter(String name, boolean) with the boolean set to true.
It is normal to convert a FileWriter into a PrintWriter like this:
        FileWriter FWfile=new FileWriter("output.txt");
        PrintWriter PWfile=new PrintWriter(FWfile);
before using it. PrintWriters know how to print just about anything readably.

Internet Connections
To act as a client, that is, to make a connection to an already running server whose IP address and port number you know, create a normal active socket with the constructor Socket(String host, int port). The host string maybe in the alphanumeric form "www.ratbag.edu" or the numeric form "123.111.45.145". Example:
        Socket csock=new Socket("www.pesky.computers.com", 80);
This constructor throws UnknownHostException for the obvious reasons, and IOException if anything else goes wrong, including "connection refused". UnknownHostException is derived from IOException, so its catch clause must come first.
        Once a socket has been successfully made,
InputStreams and OutputStreams can be extracted from it:
        InputStream IScsock=csock.getInputStream();
        OutputStream OScsock=csock.getOutputStream();
These can both be used in the normal way to send data to and receive data from the server. Remember that InputStreams and OutputStreams are fairly useless, so they are converted to BufferedReaders and PrintWriters first:
        InputStreamReader ISRcsock=new InputStreamReader(IScsock);
        BufferedReader netin=new BufferedReader(ISRcsock);
        PrintWriter netout=new PrintWriter(OScsock,true);
The true in the PrintWriter constructor makes it automatically flushing, so data is actually sent each time you do a println call.
After communications (through println and readLine) have been completed,
        csock.close();
closes the connection.


To act as a Server, that is, make an open socket on a selected port number, ready to receive connections from clients, create a ServerSocket with the
constructor ServerSocket(int portnumber), for example:
        ServerSocket ssock=new ServerSocket(1212);
(unless you are running a privileged process, make sure you choose port numbers over 1024).
Once a ServerSocket is ready, connections are accepted by:
        Socket tempsock=ssock.accept();
The accept() method waits until a client requests a connection to your port. It then creates a totally new socket (which is returned as the result) through which you may communicate with the client exactly as described above. Only communicate on this temporary socket, and close it when the session is over. The original socket as created by ServerSocket() is not touched; it is left open so that other clients may request connections while the first client is still being served. A server usually executes accept in an infinite loop; after each accept, it is normal to start a new thread to deal with the client, so the main loop can continue and concurrently accept new connections:
        ServerSocket ssock=new ServerSocket(1212);
        while (true)
        { Socket temp=ssock.accept();
          Handler h=new Handler(temp);
          h.start(); }
Handler would be a class that implements Thread, converting its socket into a BufferedReader and a PrintWriter, interacting with the client as desired, then closing the socket and ending.
        accept() is a blocking call, which means that when you call it, nothing can happen until a client requests a connection. To change this, you can set a timeout period. If no connection request is received before the timeout expires, an exception is thrown, so your program can continue to run:
        ssock.setSoTimeout(int milliseconds);


To find out where a socket is connected (this is usually done to the temporary socket returned by accept() to find out where the client is), Socket objects have a method:
        InetAddress getInetAddress()
InetAddress is a simple class that represents IP addresses, it has a few useful methods:
        String getHostAddress() returns the IP address in numeric form.
        String getHostName() returns the address in human form "www.nukem.mil", can be slow.
Example: System.out.println("Connection from "+temp.getInetAddress().getHostName());
        static InetAddress getByName(String) looks up a name, like "www.toad.com", can sometimes be slow.
        static InetAddress getLocalHost() looks up address of the computer you are using.


Threads
To make something able to execute as a separate thread, that is concurrently with the rest of the program (the Java Virtual Machine uses timesharing to support threads), make a new class that extends Thread. It must have a constructor which is used to give the thread its initial data (perhaps a socket that it is to talk on), and a method void run() which specifies what the thread does when it executes.
        Construct a new object of that type, and call its void start() method, and it will run. You must not redefine start() it is inherited from Thread, and is responsible for creating the actual Thread structures then calling the run method that you did define. Example implementing a concurrent internet server
import java.io.*;
import java.net.*;
        public class Server extends Thread
        { Socket sock;
          public Server(Socket s)
          { sock=s; }
          public void run()
          { try
            { InputStream issock=sock.getInputStream();
              OutputStream ossock=sock.getOutputStream();
              InputStreamReader isrsock=new InputStreamReader(issock);
              BufferedReader in=new BufferedReader(isrsock);
              PrintWriter out=new PrintWriter(ossock,true);
              while (true)
              { String s=in.readLine();
                if (s==null) break;
                out.println("You sent \""+s+"\""); }
              sock.close(); }
            catch (Exception e)
            { System.out.println("Failure: "+e.getMessage()); } } }
        ....
        ....
        try
        { ServerSocket ssock=new ServerSocket(3456);
          while (true)
          { Socket temp=ssock.accept();
            Server agent=new Server(temp);
            agent.start(); } }
        catch (Exception e)
        { System.out.println("Failure: "+e.getMessage()); }
A client to work with this example would follow this form:
        try
        { Socket sock=new Socket("www.bumbly.com",3456);
          InputStream issock=sock.getInputStream();
          OutputStream ossock=sock.getOutputStream();
          InputStreamReader isrsock=new InputStreamReader(issock);
          BufferedReader in=new BufferedReader(isrsock);
          PrintWriter out=new PrintWriter(ossock,true);
          out.println("hello");
          System.out.println("I sent \"hello\"");
          String s=in.readLine();
          System.out.println("and got back \""+s+"\"");
          out.println("good bye");
          System.out.println("I sent \"good bye\"");
          s=in.readLine();
          System.out.println("and got back \""+s+"\"");
          sock.close(); }
        catch (Exception e)
        { System.out.println("Failure: "+e.getMessage()); }


Converting Strings to other things
(all throw NumberFormatException)
To convert a String to an int:
        i = Integer.parseInt(s);
To convert a String to a float:
        f = new Float(s).floatValue();
But you should probably not use floats, use double instead:
        d = new Double(s).doubleValue();
(Java assumes that non-integers are doubles, and doubles have higher precision that floats, and on pentiums are the same speed)
To separate a String into substrings use a
StringTokenizer.

StringTokenizers split strings into substrings. They are not very flexible, so for anything at all complex they are more trouble than they are worth, but in simple cases a StringTokenizer is quite easy to use:
        StringTokenizer st=new StringTokenizer(s);
        String a="",b="",c="",d="";
        if (st.hasMoreTokens())
          a=st.nextToken();
        if (st.hasMoreTokens())
          b=st.nextToken();
        if (st.hasMoreTokens())
          c=st.nextToken();
        if (st.hasMoreTokens())
          d=st.nextToken();
That splits up a string assuming that white-space is the separator, so if s has the value "one two three", then a will become "one", b will become "two", c will become "three", and d will be left empty.
Normally, any invisible character is considered to be a separator, and multiple consecutive separators are ignored. To specify a different set of separators, use an enlarged constructor, e.g.:
        new StringTokenizer(s, " \n,.")
specifies that white space, commas, and full stops are the separators.
A third form of the constructor:
        new StringTokenizer(s, " \n,.",true)
tells it not to ignore the separators, but to consider them as one-character substrings to be extracted just like all the others.