Communication

Contents

 

 

files

 

Writing and reading files

 

Example - Counting Words

  Files as resources
Files on the network

 

Sockets

 

Practice exercises

files

First, we'll locate and manipulate files on the local hard drive. This is done using a File object. The handling and display of filenames is system-specific , so Java attempts to abstract these details. The File class provides methods for searching for files and for examining filenames to determine whether the files are readable and writable, or whether the name belongs to a directory.

In the following example, we find all files with the .txt extension. You could also use the FilenameFilter interface for this , but it can be done directly. To try it out, create a file named file.txt with the following content:

First line
äöüß

and perhaps a second file with the .txt extension . If Eclipse is used, the file should be saved at the top level of the project, since we read the current directory. In Eclipse, this directory is the project directory when a Java program is running.

import java.io.File;

public class Test
{
    public static void main (String args[])
    {
        // get the file.txt file
        File file = new File("file.txt");
        if (file.exists() && !file.isDirectory())
        {
            System.out.println("File " + file.getName() + " found");
            System.out.println("Full Name: " + file.getAbsolutePath());
        }

        // get all text files
        File dir = new File(".");
        String[] list = dir.list();
        for (int i = 0; i < list.length; i++)
            if (list[i].endsWith(".txt"))
            {
                long length = new File(dir, list[i]).length(); // get length
                System.out.println(list[i] + " [" + length + "]");
            }

    }
}

Note that the java.io package must be imported. The program outputs the full path of the test file and then all text files along with their lengths. It does this using the `list` method of `File`. This time, the filename must be a directory. We use the current directory, which is usually preceded by a dot (`.`). A `File` object is then created for each found name, and its `length` method returns the file's length.

File file.txt found
Full name: C:\Users\reneg\OneDrive\Documents\Workspaces\Course Examples\Test\file.txt
file.txt [21]

Writing and reading files

Now that we know a file called test.txt exists, we try to read its contents.

For this, we use an InputStream , more precisely a FileInputStream . We want to read the file line by line . To do this, we create a stream that can do this, namely the BufferedReader from our FileInputStream . The intermediate step InputStreamReader is explained further below. This reader has a method readLine , which returns null when the file has finished.

import java.io.BufferedReader;
import java.io.FileReader;

public class Test
{
    public static void main (String args[])
    {
        try
        {
            BufferedReader in = new BufferedReader(
                    new FileReader("file.txt"));
            while (true)
            {
                String s = in.readLine();
                if (s == null) break;
                System.out.println(s);
            }
            in.close();
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }
}

If you create the file under Windows and run the program in a Windows command prompt, the output of the German special characters äöüß may be incorrect. This is because the command prompt encodes the characters differently than Windows. We will correct this issue later.

The InputStream class (and therefore also FileInputStream) has a `read` method for reading a byte. The `available` method returns the number of available characters.

import java.io.FileInputStream;
import java.io.InputStream;

public class Test
{
    public static void main (String args[])
    {
        try
        {
            InputStream in = new FileInputStream("file.txt");
            while (in.available() > 0)
            {
                System.out.print(in.read() + " ");
            }
            in.close();
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
        System.out.println();
    }
}

The output depends on the encoding used to create the file file.txt . In my case, the file is created in UTF-8. In this case, German special characters are encoded with 2 bytes, where the first byte is equal to 195.

69 114 115 116 101 32 90 101 105 108 101 13 10 195 164 195 182 195 188 195 159

69 represents E, the first character in the file. Note that under Windows, the end of a line is represented by 13 and 10. Under Unix, only 10 is used, and on Apple computers, only 13.

Java provides classes that allow the translation of local encoding to Unicode. These are the Reader classes. As in the first example, this task is performed by the InputStreamReader.

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;

public class Test
{
    public static void main (String args[])
    {
        try
        {
            Reader in = new BufferedReader(
                    new InputStreamReader(
                            new FileInputStream("file.txt"), "UTF-8"));
            while (in.ready())
            {
                int c = in.read();
                if (c == -1) break;
                System.out.print(c + " ");
            }
            in.close();
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
        System.out.println();
        System.out.println(System.getProperty("file.encoding"));
    }
}

In this program, we output the characters as numbers in the Unicode character set. Java also internally stores char and strings in Unicode. The number 228 represents an 'ä' in Unicode.

69 114 115 116 101 32 90 101 105 108 101 13 10 228 246 252 223
UTF-8

Example - Count words in the Bible

We read the words from the English Gutenberg Bible and count them. Then the 10 most frequent words are displayed.

The words are stored in a hashtable along with their count. We use a custom class for this. The key for the hashtable is simply the word itself. You can iterate through the keys of a hashtable using the `keySet()` method , which creates a set of all keys.

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Arrays;
import java.util.Hashtable;

class Count implements Comparable<Count>
{
    String word;
    int count;

    public Count (String word)
    {
        this.word = word;
        count = 1;
    }

    @Override
    public int compareTo (Count o)
    {
        if (count < o.count)
            return -1;
        else if (count > o.count)
            return 1;
        else
            return 0;
    }
}

public class Test
{
    public static void main (String args[])
    {
        try
        {
            // reader from the file
            BufferedReader in = new BufferedReader(new FileReader("bible.txt"));

            // hashtable for word count
            Hashtable<String, Count> wordcount = new Hashtable<String, Count>();

            while (true)
            {
                String line = in.readLine();
                if (line == null) break; // end of file

                // split the line into words
                String words[] = line.split(" ");
                for (String word : words)
                {
                    // "And" is the same as "and"
                    word = word.toLowerCase();     

                    // exclude empty words and section numbers
                    if (word.equals("")) continue;
                    if (word.contains(":")) continue;

                    // put count in hashtable or increase count
                    Count count = wordcount.get(word);
                    if (count == null)
                        wordcount.put(word, new Count(word));
                    else
                        count.count++;
                }
            }

            System.out.print(wordcount.size() + " words found.");

            // Put counts from hashtable to array

            Count[] counts = new Count[wordcount.size()];

            int ci = 0;
            for (String word : wordcount.keySet())
            {
                counts[ci++] = wordcount.get(word);
            }

            // sort array
            Arrays.sort(counts);

            // print 10 most frequent words
            for (int i = 1; i <= 10; i++)
            {
                Count c = counts[counts.length - i];
                System.out.println(c.word + " : " + c.count);
            }

            in.close();
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }
}
24781 words found.the : 64011
and: 51313
of: 34631
to: 13567
that: 12784
in: 12503
he : 10261
shall: 9838
unto : 8987
for: 8810

Files as resources

Resources are files and settings that a program needs for its configuration. Files can contain, for example, text, graphics, and sound. Settings are pairs of keys and strings and are also stored in files. All these files can either be stored alongside the class files on the local hard drive or included in the JAR archive.

The essential characteristic of a resource is that it cannot be modified by the program ( read-only ). Therefore, there are no write accesses to resource files.

We will demonstrate how to open a text file as a resource. The following program displays a text file in a dialog box. This can be used, for example, to display help texts.

The crucial part is getting a stream to read from the file. This is done using the ` getResourceAsStream(filename)` method of `Class` . `Class` is a general class that contains class information. In this case, we use an instance of ` Class` that refers to the current class, `Help` . We obtain this instance using `getClass()` , a method that every object has. `Class` actually uses its `ClassLoader` , which can load classes from disk or the archive. Therefore, this `ClassLoader` can also load resources.

It should also be noted that resource files are named relative to the current directory, which is specified as the root directory "/" .

import java.awt.BorderLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

class Help extends JFrame implements ActionListener
{
    JTextArea V;
    JButton Close;

    // display the help from the file named subject
    public Help (String subject)
    {
        super("Help");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // TextArea to display the text:
        V = new JTextArea();
        V.setEditable(false);
        JScrollPane scroller = new JScrollPane(V);

        // Read the file from the resource:
        try
        {
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    getClass().getResourceAsStream("/" + subject)));
            // read line after line:
            while (true)
            {
                String s = in.readLine();
                if (s == null) break;
                V.append(s + "\n");
            }
            in.close();
        }
        catch (Exception e)
        {
            V.setText("Could not find the help file!");
        }

        // Layout:
        setLayout(new BorderLayout());
        add("Center", scroller);

        Panel p = new Panel();
        p.add(Close = new JButton("Close"));
        Close.addActionListener(this);
        add("South", p);

        setSize(800, 600);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    @Override
    public void actionPerformed (ActionEvent e)
    // close dialog
    {
        if (e.getSource() == Close)
        {
            setVisible(false);
            dispose();
        }
    }

}

public class Test
{
    public static void main (String args[])
    {
        new Help("test.txt");
    }

}

The constructor of `Help` takes the filename (e.g., "help.txt" ) as a parameter. Note that if the resource does not exist, the stream returned is null .

files innetwork

One of Java's design goals was the programming of network applications. Therefore, Java includes a number of classes for communication over TCP/IP. One of these allows you to read a file directly from a web server. The following example copies a file byte by byte from the internet.

Files on a network are accessed using a URL ( Uniform Resource Locator ). It's also possible to analyze the URL after it's generated, for example with methods like `getProtocol()`, `getHost()` , or `getFile()` . However, here we're only reading byte by byte and outputting the result to a file. For this, we use `FileOutputStream` .

import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL;

public class Test
{
    public static void main (String args[])
    {
        try
        {
            URL url = new URI("http://java.renegrothmann.de/index.html")
                    .toURL();
            InputStreamReader in = new InputStreamReader(url.openStream());
            int b;
            FileOutputStream out = new FileOutputStream("index.html");
            while (true)
            {
                b = in.read();
                if (b == -1) break;
                out.write(b);
            }
            in.close();
            out.close();
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }
}

Sockets

Programs can communicate with each other over the internet. Most external connections are blocked by a firewall, which should be installed. We test the communication only on one machine using Telnet . Most systems contain a telnet client. In Windows, it might be a special feature which needs to be installed. Open a command line and check if the telnet command works on your system.

The following program opens a so-called socket . This is done in a separate thread to show how a program could use a graphical interface and still have a communication channel open. In the example, the main thread simply ends. Our socket can read and write buffered text. It will stop if it receives a line "quit".

To check the program, start it and open another command line where you enter telnet localhost 6000 . 6000 is the port that we have assigned to the socket. You can then enter lines and they will be echoed back. Enter quit to finish.

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Test implements Runnable
{
    PrintWriter Out;
    BufferedReader In;
    ServerSocket server;

    public static void main (String args[])
    {
        new Test();
    }

    public Test()
    {
        try // generate input and output streams and a thread
        {
            server = new ServerSocket(6000);
            server.setSoTimeout(10000);
            Socket socket = server.accept();

            System.out.println("Server opened.");

            Out = new PrintWriter(
                    new DataOutputStream(socket.getOutputStream()), true);
            In = new BufferedReader(new InputStreamReader(
                    new DataInputStream(socket.getInputStream())));
            new Thread(this).start();
        }
        catch (Exception e)
        {
            System.out.println("No connection for 10 seconds.");
        }
    }

    @Override
    public void run()
    // the thread that manages a connection.
    {
        Out.println("Enter quit to stop.");

        try
        {
            while (true) // Echo loop
            {
                String s = In.readLine();
                if (s.toLowerCase().equals("quit")) break;
                Out.println("Echo: " + s);
            }
            // Always close streams:
            In.close();
            Out.close();
            server.close();
            System.out.println("Server closed");
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }
}

Here is a session.

>telnet localhost 6000

Enter "quit" to stop.
Hi, my name is Paul.
Echo: Hi, my name is Paul.
Okay, I leave.
Echo: Okay, I leave.
quit


Connection to host lost.
>

Exercisetasks

Solutions .

Problems without solutions

  1. Write a program that can copy a binary file. The file must not be translated to Unicode or processed line by line.
  2. Write a program that replaces all ä, ö, ü, etc. in a text file with their HTML equivalent ä etc. (ß is ß).

Back to the Java course