Saturday, November 14, 2015

Input / Output in java Chapter 13

Chapter 13

Input/Output

Input/output (I/O) is one of the most common operations performed by computer programs. Examples of I/O operations include

images creating and deleting files

images reading from and writing to a file or network socket

images serializing (or saving) objects to persistent storage and retrieving the saved objects

Java support for I/O has been available since JDK 1.0 in the form of the I/O API in the java.io package. JDK 1.4 added the New I/O (NIO) APIs that offer performance improvement in buffer management, scalable network and file I/O. Java NIO APIs are part of the java.nio package and its subpackages. JDK 7 introduces yet a new set of packages called NIO.2 to complement the existing technologies. There is no java.nio2 package. Instead, new types can be found in the java.nio.file package and its subpackages. One of the new features NIO.2 introduces is the Path interface designed to displace the java.io.File class, now considered inferior. The old File class has often been a source of frustration because many of its methods fail to throw exceptions, its delete method often fails for inexplicable reasons, and its rename method doesn't work consistently across different operating systems.

Another addition in JDK 7 that has big impacts on the I/O and NIO APIs is the java.lang.AutoCloseable interface. The majority of java.io classes now implement this interface to support try-with-resources.

This chapter presents topics based on functionality and select the most important members of java.io and java.nio.file. java.io.File is no longer discussed in favor of the new Path interface. However, java.io.File was widely used prior to JDK 7 and therefore is still everywhere in applications written in previous versions of Java. It is therefore recommended that you read the Input/Output chapter of the second edition of this book (included in the zipped file accompanying this book).

File systems and paths are the first topic in this chapter. Here you learn what a path is and how the file system is represented in Java.

The second section, “File and Directory Handling and Manipulation,” discusses the powerful java.nio.file.Files class. You can use Files to create and delete files and directories, check the existence of a file, and read from and write to a file.

Note that support for reading from and writing to a files in Files is only suitable for small files. For larger files and for added functionality, you need a stream. Streams, which are discussed in the section “Input/Output Streams,” act like water pipes that facilitate data transmission. There are four types of streams: InputStream, OutputStream, Reader, and Writer. For better performance, there are also classes that wrap these streams and buffer the data being read or written.

Reading from and writing to a stream dictate that you do so sequentially, which means to read the second unit of data, you must read the first one first. For random access files'in other words, to access any part of a file randomly—you need a different Java type. The java.io.RandomAccessFile class used to be a good choice for non-sequential operations, however a better way now is to use java.nio.channels.SeekableByteChannel. The latter is discussed in the section “Random Access Files.”

This chapter concludes with object serialization and deserialization.

File Systems and Paths

A file system can contain three types of objects: file, directory (a.k.a folder), and symbolic link. Not all operating systems support symbolic links, and early operating systems featured a flat-file system with no subdirectories. However most operating systems today support at least files and directories and allow directories to contain subdirectories. A directory on top of the directory tree is called a root. Linux/UNIX variants have one root: /. Windows can have multiple roots: C:\, D:\, and so on.

An object in a file system can be uniquely identified by a path. For instance, you can refer to the image1.jpg file in your Mac's /home/user directory as /home/user/image1.jpg, which is a path. A temp directory under your Windows’ C:\ is C:\temp, which is also a path. Paths must be unique throughout a file system. For example, you cannot create a document.bak directory in /home/user if there is already a file named document.bak in that directory.

A path can be absolute or relative. An absolute path has all the information to point to an object in the file system. For instance, /home/kyleen and /home/alexis are absolute paths. A relative does not have all the information needed. For example, home/jayden is relative to the current directory. Only if the current directory is known can home/jayden be resolved.

In Java a file or a directory was traditionally represented by a java.io.File object. However, the File class has many drawbacks and Java 7 brings with it a better replacement in its NIO.2 package, the java.nio.file.Path interface.

The aptly named Path interface represents a path, which can be a file, a directory, or a symbolic link. It can also represent a root. Before I explain Path in detail, let me introduce you to another member of the java.nio.file package, the FileSystem class.

As the name implies, FileSystem represents a file system. It is an abstract class and to obtain the current file system, you call the FileSystems.getDefault() static method:

FileSystem fileSystem = FileSystems.getDefault();

FileSystems has other methods. The getSeparator method returns the name separator as String. In Windows this will be “\” and in UNIX/Linux it will be “/”. Here is its signature.

public abstract java.lang.String getSeparator()

Another method of FileSystem, getRootDirectories, returns an Iterable for iterating root directories.

public abstract java.lang.Iterable<Path> getRootDirectories()

To create a Path, use FileSystem's getPath method:

public abstract Path getPath(String first, String... more)

Only the first argument in getPath is required, the more argument is optional. If more is present, it will be appended to first. For example, to create a path that refers to /home/user/images, you would write either of these two statements.


Path path = FileSystems.getDefault().getPath("/home/user/images");

Path path = FileSystems.getDefault().getPath("/home", "user",
        "images");

The java.nio.file.Paths class provides a shortcut for creating a Path through its static get method:


Path path1 = Paths.get("/home/user/images");
Path path2 = Paths.get("/home", "user", "images");
Path path3 = Paths.get("C:\temp");
Path path4 = Paths.get("C:\", "temp");

Paths like /home/user/images or C:\temp can be broken into its elements. /home/user/images has three names, home, user, and images. C:\temp has only one name, temp, because the root does not count. The getNameCount method in Path returns the number of names in a path. Each individual name can be retrieved using getName:

Path getName(int index)

The index parameter is zero-based. Its value must be between 0 and the number of elements minus 1. The first element closest to the root has index 0. Consider this code snippet.


Path path = Paths.get("/home/user/images");
System.out.println(path.getNameCount()); // prints 3
System.out.println(path.getName(0)); // prints home
System.out.println(path.getName(1)); // prints user
System.out.println(path.getName(2)); // prints images

Other important methods of Path include getFileName, getParent, and getRoot.


Path getFileName()

Path getParent()

Path getRoot()

getFileName returns the file name of the current Path. Therefore, if path1 denotes /home/user1/Calculator.java, path1.getFileName() will return a relative path referring to the Calculator.java file. Calling path1.getParent() would return /home/user1 and calling path1.getRoot() would return /. Calling getParent on a root would return null.

A very important note: Creating a Path does not create a physical file or directory. Often Path instances reference non-existent physical objects. To create a file or directory, you need to use the Files class, which is discussed in the next section.

File and Directory Handling and Manipulation

java.nio.file.Files is a very powerful class that provides static methods for handling files and directories as well as reading from and writing to a file. With it you can create and delete a path, copy files, check if a path exists, and so on. In addition, Files comes with methods for creating stream objects that you'll find useful when working with input and output streams.

The following subsections elaborate what you can do with Files.

Creating and Deleting Files and Directories

To create a file you use the createFile method of Files. Here is its signature.


public static Path createFile(Path file,
        java.nio.file.attribute.FileAttribute<?>... attrs)

The attrs argument is optional, so you can ignore it if you don't need to set attributes. For example:


Path newFile = Paths.get("/home/jayden/newFile.txt");
Files.createFile(newFile);

createFile throws an IOException if the parent directory does not exist. It throws a FileAlreadyExistsException if there already exists a file, a directory, or a symbolic by the name specified by file.

To create a directory, use the createDirectory method.


public static Path createDirectory(Path directory,
        java.nio.file.attribute.FileAttribute<?>... attrs)

Like createFile, createDirectory may throw an IOException ora FileAlreadyExistsException.

To delete a file, a directory or a symbolic link, use the delete method:

public static void delete(Path path)

If path is a directory, then the directory must be empty. If path is a symbolic link, only the link is deleted and not the target of the link. If path does not exist, a NoSuchFileException is thrown.

To avoid having to check if a path exists when deleting a path, use deleteIfExists:

public static void deleteIfExists(Path path)

If you're deleting a directory with deleteIfExists, the directory must be empty. If not, a DirectoryNotEmptyException will be thrown.

Retrieving A Directory's Objects

You can retrieve the files, subdirectories, and symbolic links in a directory by using the newDirectoryStream method of the Files class. This method will return a DirectoryStream to iterate over all objects in a directory. The signature of newDirectoryStream is as follows.

public static DirectoryStream<Path> newDirectoryStream(Path path)

The DirectoryStream returned by this method must be closed after use.

For example, the following snippet prints all the subdirectories and files in a directory.


Path parent = ...
try (DirectoryStream<Path> children =
        Files.newDirectoryStream(parent)) {
    for (Path child : children) {
        System.out.println(child);
    }
} catch (IOException e) {
    e.printStackTrace();
}

Copying and Moving Files

There are three copy methods for copying files and directories. The easiest one to use is this one.


public static Path copy(Path source, Path target,
        CopyOption... options) throws java.io.IOException

CopyOption is an interface in java.nio.file. The StandardCopyOption enum is one of its implementations and offers three copy options:

images ATOMIC_MOVE. Move the file as an atomic file system operation.

images COPY_ATTRIBUTES. Copy attributes to the new file.

images REPLACE_EXISTING. Replace an existing file if it exists.



As an example, the following snippet copies the line1.bmp file in C:\temp to backup.bmp in the same directory.


Path source = Paths.get("C:/temp/line1.bmp");
Path target = Paths.get("C:/temp/backup.bmp")
try {
    Files.copy(source, target,
            StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
    e.printStackTrace();
}

You use the move method to move a file.


public static Path move(Path source, Path target,
        CopyOption... options) throws java.io.IOException

For example, the following code moves C:\temp\backup.bmp to C:\data.


Path source = Paths.get("C:/temp/backup.bmp");
Path target = Paths.get("C:/data/backup.bmp")
try {
    Files.move(source, target,
            StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
    e.printStackTrace();
}

Reading from and Writing to Files

The Files class provides methods for reading from and writing to a small binary and text file. The readAllBytes and readAllLines methods are for reading from a binary and text file, respectively.


public static byte[] readAllBytes(Path path)
        throws java.io.IOException
public static List<String> readAllLines(Path path,
        java.nio.charset.Charset charset) throws java.io.IOException

These write methods are for writing to a binary and text file, respectively.


public static Path write(Path path, byte[] bytes,
        OpenOption... options) throws java.io.IOException
public static Path write(Path path, java.lang.Iterable<? extends
        CharSequence> lines, java.nio.charset.Charset charset,
        OpenOption... options) throws java.io.IOException

Both write method overloads take an optional OpenOption and the second overload a Charset. The OpenOption interface defines options for opening a file for write access. The StandardOpenOption enum implements OpenOption and provides the following values.

images APPEND. If the file is opened for write access, the data written will be appended to the end of the file.

images CREATE. Create a new file if it does not exist.

images CREATE_NEW. Create a new file and throws an exception if it already exists.

images DELETE_ON_CLOSE. Delete the file on close.

images DSYNC. Dictate that update to the file content be written synchronously.

images READ. Open for read access.

images SPARSE. Sparse file.

images SYNC. Dictate that update to the file content and metadata be written synchronously.

images TRUNCATE_EXISTING. Truncate the file's length to 0 if it is opened for write and it already exists.

images WRITE. Open for write access.



java.nio.charset.Charset is an abstract class that represents a character set. You need to specify the character set being used when encoding characters to bytes and decoding bytes to characters. See the discussion of ASCII and Unicode in Chapter 2, “Language Fundamentals,” if you've forgotten about it.

The easiest way to create a Charset is by calling the static Charset.forName method, passing a character set name. For instance, to create a US ASCII Charset, you would write

Charset usAscii = Charset.forName("US-ASCII");

Now that you know a little bit about OpenOption and Charset, have a look at the following code snippet, which writes a few lines of text to C:\temp\speech.txt and write them back.


// write and read to a text file
Path textFile = Paths.get("C:/temp/speech.txt");
Charset charset = Charset.forName("US-ASCII");
String line1 = "Easy read and write";
String line2 = "with java.nio.file.Files";
List<String> lines = Arrays.asList(line1, line2);
try {
    Files.write(textFile, lines, charset);
} catch (IOException ex) {
    ex.printStackTrace();
}

// read back
List<String> linesRead = null;
try {
    linesRead = Files.readAllLines(textFile, charset);
} catch (IOException ex) {
    ex.printStackTrace();
}

if (linesRead != null) {
    for (String line : linesRead) {
        System.out.println(line);
    }
}

Note that the read and write methods in Files are only good for small files. For medium-sized and large files, use streams instead.

Input/Output Streams

I/O streams can be likened to water pipes. Just like water pipes connect city houses to a water reservoir, a Java stream connects Java code to a “data reservoir.” In Java terminology, this “data reservoir” is called a sink and could be a file, a network socket, or memory. The good thing about streams is you employ a uniform way to transport data from and to different sinks, hence simplifying your code. You just need to construct the correct stream.

Depending on the data direction, there are two types of streams, input stream and output stream. You use an input stream to read from a sink and an output stream to write to a sink. Because data can be classified into binary data and characters (human readable data), there are also two types of input streams and two types of output streams. These streams are represented by the following four abstract classes in the java.io package.

images Reader. A stream for reading characters from a sink.

images Writer. A stream for writing characters to a sink.

images InputStream. A stream for reading binary data from a sink.

images OutputStream. A stream for writing binary data to a sink.



The benefit of streams is they define methods for data reading and writing that can be used regardless the data source or destination. To connect to a particular sink, you simply need to construct the correct implementation class. The java.nio.file.Files class provides methods for constructing streams that connect to a file.

A typical sequence of operations when working with a stream is as follows:

1. Create a stream. The resulting object is already open, there is no open method to call.

2. Perform reading or writing operations.

3. Close the stream by calling its close method. Since most stream classes now implement java.lang.AutoCloseable, you can create a stream in a try-with-resources statement and get the streams automatically closed for you.



The stream classes will be discussed in clear detail in the following sections.

Reading Binary Data

You use an InputStream to read binary data from a sink. InputStream is an abstract class with a number of concrete subclasses, as shown in Figure 13.1.

images

Figure 13.1: The hierarchy of InputStream

Prior to JDK 7 you used FileInputStream to read binary from a file. With the advent of NIO.2, you can call Files.newInputStream to obtain an InputStream with a file sink. Here's the signature of newInputStream:


public static java.io.InputStream newInputStream(Path path,
        OpenOption... options) throws java.io.IOException

InputStream implements java.lang.AutoCloseable so you can use it in a try-with-resources statement and don't need to explicitly close it. Here is some boilerplate code.


Path path = ...
try (InputStream inputStream = Files.newInputStream(path,
        StandardOpenOption.READ) {

    // manipulate inputStream

} catch (IOException e) {
    // do something with e
}

The InputStream returned from Files.newInputStream is not buffered so you should wrap it with a BufferedInputStream for better performance. As such, your boilerplate code would look like this.


Path path = ...
try (InputStream inputStream = Files.newInputStream(path,
        StandardOpenOption.READ;
        BufferedInputStream buffered =
                new BufferedInputStream(inputStream)) {

        // manipulate buffered, not inputStream

} catch (IOException e) {
    // do something with e
}

At the core of InputStream are three read method overloads.


public int read()

public int read(byte[] data)

public int read(byte[] data, int offset, int length)

InputStream employs an internal pointer that points to the starting position of the data to be read. Each of the read method overloads returns the number of bytes read or -1 if no data was read into the InputStream. It returns -1 when the internal pointer has reached the end of file.

The no-argument read method is the easiest to use. It reads the next single byte from this InputStream and returns an int, which you can then cast to byte. Using this method to read a file, you use a while block that keeps looping until the read method returns -1:


int i = inputStream.read();
while (i != -1) {
    byte b = (byte) I;
    // do something with b
}

For speedier reading, you should use the second or third read method overload, which requires you to pass a byte array. The data will then be stored in this array. The size of the array is a matter of compromise. If you assign a big number, the read operation will be faster because more bytes are read each time. However, this means allocating more memory space for the array. In practice, the array size should start from 1000 and up.

What if there are fewer bytes available than the size of the array? The read method overloads return the number of bytes read, so you always know which elements of your array contain valid data. For example, if you use an array of 1,000 bytes to read an InputStream and there are 1,500 bytes to read, you will need to invoke the read method twice. The first invocation will give you 1,000 bytes, the second 500 bytes.

You can choose to read fewer bytes than the array size using the three-argument read method overload:

public int read(byte[] data, int offset, int length)

This method overload reads length bytes into the byte array. The value of offset determines the position of the first byte read in the array.

In addition to the read methods, there are also these methods:

public int available() throws IOException

This method returns the number of bytes that can be read (or skipped over) without blocking.

public long skip(long n) throws IOException

Skips over the specified number of bytes from this InputStream. The actual number of bytes skipped is returned and this may be smaller than the prescribed number.

public void mark(int readLimit)

Remembers the current position of the internal pointer in this InputStream. Calling reset afterwards would return the pointer to the marked position. The readLimit argument specifies the number of bytes to be read before the mark position gets invalidated.

public void reset()

Repositions the internal pointer in this InputStream to the marked position.

public void close()

Closes this InputStream. Unless you created an InputStream in a try-with-resources statement, you should always call this method when you are done with the InputStream to release resources.

As an example, the code in Listing 13.1 shows an InputStreamTest class that contains a compareFiles method for comparing two files.

Listing 13.1: The compareFiles method that uses InputStream


import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class InputStreamTest {
    public boolean compareFiles(Path path1, Path path2)
            throws NoSuchFileException {
        if (Files.notExists(path1)) {
            throw new NoSuchFileException(path1.toString());
        }
        if (Files.notExists(path2)) {
            throw new NoSuchFileException(path2.toString());
        }
        try {
        if (Files.size(path1) != Files.size(path2)) {
            return false;
        }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try (InputStream inputStream1 = Files.newInputStream(
                    path1, StandardOpenOption.READ);
            InputStream inputStream2 = Files.newInputStream(
                    path2, StandardOpenOption.READ)) {
            int i1, i2;
            do {
                i1 = inputStream1.read();
                i2 = inputStream2.read();
                if (i1 != i2) {
                    return false;
                }
            } while (i1 != -1);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    public static void main(String[] args) {
        Path path1 = Paths.get("C:\\temp\\line1.bmp");
        Path path2 = Paths.get("C:\\temp\\line2.bmp");
        InputStreamTest test = new InputStreamTest();
        try {
            if (test.compareFiles(path1, path2)) {
                System.out.println("Files are identical");
            } else {
                System.out.println("Files are not identical");
            }
        } catch (NoSuchFileException e) {
            e.printStackTrace();
        }

        // the compareFiles method is not the same as
        // Files.isSameFile
        try {
            System.out.println(Files.isSameFile(path1, path2));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

compareFiles returns true if the two files compared are identical. The brain of the method is this block.


int i1, i2;
do {
    i1 = inputStream1.read();
    i2 = inputStream2.read();
    if (i1 != i2) {
        return false;
    }
} while (i1 != -1);
return true;

It reads the next byte from the first InputStream to i1 and the second InputStream to i2 and compares i1 with i2. It will continue reading until i1 and i2 are different or the end of file is reached.

Writing Binary Data

The OutputStream abstract class represents a stream for writing binary data to a sink. Its child classes are shown in Figure 13.2.

images

Figure 13.2: The implementation classes of OutputStream

In pre-7 JDK you would use java.io.FileOutputStream to write binary to a file. Thanks to NIO.2, you can now call Files.newOutputStream to obtain an OutputStream with a file sink. Here's the signature of newOutputStream:


public static java.io.OutputStream newOutputStream(Path path,
        OpenOption... options) throws java.io.IOException

OutputStream implements java.lang.AutoCloseable so you can use it in a try-with-resources statement and don't need to explicitly close it. Here is how you can create an OutputStream with a file sink:


Path path = ...
try (OutputStream outputStream = Files.newOutputStream(path,
        StandardOpenOption.CREATE, StandardOpenOption.APPEND) {

    // manipulate outputStream

} catch (IOException e) {
    // do something with e
}

The OutputStream returned from Files.newOutputStream is not buffered so you should wrap it with a BufferedOutputStream for better performance. Therefore, your boilerplate code would look like this.


Path path = ...
try (OutputStream outputStream = Files.newOututStream(path,
        StandardOpenOption.CREATE, StandardOpenOption.APPEND;
        BufferedOutputStream buffered =
                new BufferedOutputStream(outputStream)) {

        // manipulate buffered, not outputStream

} catch (IOException e) {
    // do something with e
}

OutputStream defines three write method overloads, which are mirrors of the read method overloads in InputStream:


public void write(int b)

public void write(byte[] data)

public void write(byte[] data, int offset, int length)

The first overload writes the lowest 8 bits of integer b to this OutputStream. The second writes the content of a byte array to this OutputStream. The third overload writes length bytes of the data starting at position offset.

In addition, there are also the no-argument close and flush methods. close closes the OutputStream and flush forces any buffered content to be written out to the sink. You don't need to call close if you created the OutputStream in a try-with-resources statement.

As an example, Listing 13.2 shows how to copy a file using OutputStream.

Listing 13.2: The OutputStreamTest class


package app13;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class OutputStreamTest {
    public void copyFiles(Path originPath, Path destinationPath)
            throws IOException {
        if (Files.notExists(originPath)
                || Files.exists(destinationPath)) {
            throw new IOException(
                    "Origin file must exist and " +
                    "Destination file must not exist");
        }
        byte[] readData = new byte[1024];
        try (InputStream inputStream =
                    Files.newInputStream(originPath,
                    StandardOpenOption.READ);
            OutputStream outputStream =
                    Files.newOutputStream(destinationPath,
                    StandardOpenOption.CREATE)) {
            int i = inputStream.read(readData);
            while (i != -1) {
                outputStream.write(readData, 0, i);
                i = inputStream.read(readData);
            }
        } catch (IOException e) {
            throw e;
        }
    }

    public static void main(String[] args) {
        OutputStreamTest test = new OutputStreamTest();
        Path origin = Paths.get("C:\\temp\\line1.bmp");
        Path destination = Paths.get("C:\\temp\\line3.bmp");
        try {
            test.copyFiles(origin, destination);
            System.out.println("Copied Successfully");
        } catch (IOException e) {
            e.printStackTrace();
       }
    }
}

This part of the copyFile method does the work.


byte[] readData = new byte[1024];
try (InputStream inputStream =
            Files.newInputStream(originPath,
            StandardOpenOption.READ);
    OutputStream outputStream =
            Files.newOutputStream(destinationPath,
            StandardOpenOption.CREATE)) {
    int i = inputStream.read(readData);
    while (i != -1) {
        outputStream.write(readData, 0, i);
        i = inputStream.read(readData);
    }
} catch (IOException e) {
    throw e;
}

The readData byte array is used to store the data read from the InputStream. The number of bytes read is assigned to i. The code then calls the write method on the OutputStream, passing the byte array and i as the third argument.

outputStream.write(readData, 0, i);

Writing Text (Characters)

The abstract class Writer defines a stream used for writing characters. Figure 13.3 shows the implementations of Writer.

images

Figure 13.3: The subclasses of Writer

OutputStreamWriter facilitates the translation of characters into byte streams using a given character set. The character set guarantees that any Unicode characters you write to this OutputStreamWriter will be translated into the correct byte representation. FileWriter is a subclass of OutputStreamWriter that provides a convenient way to write characters to a file. However, FileWriter is not without flaws. When using FileWriter you are forced to output characters using the computer's encoding, which means characters outside the current character set will not be translated correctly into bytes. A better alternative to FileWriter is PrintWriter.

The following sections cover Writer and some of its descendants.

Writer

This class is similar to OutputStream, except that Writer deals with characters instead of bytes. Like OutputStream, Writer has three write method overloads:


public void write(int b)

public void write(char[] text)

public void write(char[] text, int offset, int length)

When working with text or characters, however, you ordinarily use strings. As such, there are two other overloads of the write method that accept a String object.


public void write(String text)

public void write(String text, int offset, int length)

The last write method overload allows you to pass a String and write part of the String to the Writer.

OutputStreamWriter

An OutputStreamWriter is a bridge from character streams to byte streams: Characters written to an OutputStreamWriter are encoded into bytes using a specified character set. The latter is an important element of OutputStreamWriter because it enables the correct translations of Unicode characters into byte representation.

The OutputStreamWriter class offers four constructors:


public OutputStreamWriter(OutputStream out)

public OutputStreamWriter(OutputStream out,
        java.nio.charset.Charset cs)

public OutputStreamWriter(OutputStream out,
        java.nio.charset.CharsetEncoder enc)

public OutputStreamWriter(OutputStream out, String encoding)

All the constructors accept an OutputStream, to which bytes resulting from the translation of characters written to this OutputStreamWriter will be written. Therefore, if you want to write to a file, you simply need to create an OutputStream with a file sink:


OutputStream os = Files.newOutputStream(path, openOption);
OutputStreamWriter writer = new OutputStreamWriter(os, charset);

Listing 13.3 shows an example of OutputStreamWriter.

Listing 13.3: Using OutputStreamWriter


package app13;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class OutputStreamWriterTest {
    public static void main(String[] args) {
        char[] chars = new char[2];
        chars[0] = '\u4F60'; // representing images
        chars[1] = '\u597D'; // representing images;
        Path path = Paths.get("C:\\temp\\myFile.txt");
        Charset chineseSimplifiedCharset =
                Charset.forName("GB2312");

        try (OutputStream outputStream =
                Files.newOutputStream(path,
                StandardOpenOption.CREATE);
            OutputStreamWriter writer = new OutputStreamWriter(
                    outputStream, chineseSimplifiedCharset)) {

            writer.write(chars);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The code in Listing 13.3 creates an OutputStreamWriter based on a OutputStream that writes to C:\temp\myFile.txt on Windows. Therefore, if you are using Linux/Unix you need to change the value of textFile. The use of an absolute path is intentional since most readers find it easier to find if they want to open the file. The OutputStreamWriter uses the GB2312 character set (simplified Chinese).

The code in Listing 13.3 passes two Chinese characters: (represented by the Unicode 4F60) and (Unicode 597D). means ‘How are you?’ in Chinese.

When executed, the OutputStreamWriterTest class will create a myFile.txt file. It is 4 bytes long. You can open it and see the Chinese characters. For the characters to be displayed correctly, you need to have the Chinese font installed in your computer.

PrintWriter

PrintWriter is a better alternative to OutputStreamWriter. Like OutputStreamWriter, PrintWriter lets you choose an encoding by passing the encoding information to one of its constructors. Here are two of its constructors:


public PrintWriter(OutputStream out)

public PrintWriter(Writer out)

To create a PrintWriter that writes to a file, simply create an OutputStream with a file sink.

PrintWriter is more convenient to work with than OutputStreamWriter because the former adds nine print method overloads for printing any type of Java primitives and objects. Here are the method overloads:


public void print(boolean b)

public void print(char c)

public void print(char[] s)

public void print(double d)

public void print(float f)

public void print(int i)

public void print(long l)

public void print(Object object)

public void print(String string)

There are also nine println method overloads, which are the same as the print method overloads, except that they print a new line character after the argument.

In addition, there are two format method overloads that enable you to print according to a print format. This method was covered in Chapter 5, “Core Classes.”

Always wrap your Writer with a BufferedWriter for better performance. BufferedWriter has the following constructors that allow you to pass a Writer object.


public BufferedWriter(Writer writer)

public BufferedWriter(Writer writer, in bufferSize)

The first constructor creates a BufferedWriter with the default buffer size (the documentation does not say how big). The second one lets you choose the buffer size.

With PrintWriter, however, you cannot wrap it like this


PrintWriter printWriter = ...;
BufferedWriter bw = new BufferedWriter(printWriter);

because then you would not be able to use the methods of the PrintWriter. Instead, wrap the Writer that is passed to a PrintWriter.

PrintWriter pw = new PrintWriter(new BufferedWriter(writer));

Listing 13.4 presents an example of PrintWriter.

Listing 13.4: Using PrintWriter


package app13;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class PrintWriterTest {
    public static void main(String[] args) {
        Path path = Paths.get("c:\\temp\\printWriterOutput.txt");
        Charset usAsciiCharset = Charset.forName("US-ASCII");
        try (BufferedWriter bufferedWriter =
                Files.newBufferedWriter(path, usAsciiCharset,
                StandardOpenOption.CREATE);
            PrintWriter printWriter =
                    new PrintWriter(bufferedWriter)) {
            printWriter.println("PrintWriter is easy to use.");
            printWriter.println(1234);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The nice thing about writing with a PrinterWriter is when you open the resulting file, everything is human-readable. The file created by the preceding example says:


PrinterWriter is easy to use.
1234

Reading Text (Characters)

You use the Reader class to read text (characters, i.e. human readable data). The hierarchy of this class is shown in Figure 13.4.

images

Figure 13.4: Reader and its descendants

The following sections discuss Reader and some of its descendants.

Reader

Reader is an abstract class that represents an input stream for reading characters. It is similar to InputStream except that Reader deals with characters and not bytes. Reader has three read method overloads that are similar to the read methods in InputStream:


public int read()

public int read(char[] data)

public int read(char[] data, int offset, int length)

These method overloads allow you to read a single character or multiple characters that will be stored in a char array. Additionally, there is a fourth read method for reading characters into a java.nio.CharBuffer.

public int read(java.nio.CharBuffer target)

Reader also provides the following methods that are similar to those in InputStream: close, mark, reset, and skip.

InputStreamReader

An InputStreamReader reads bytes and translates them into characters using the specified character set. Therefore, InputStreamReader is ideal for reading from the output of an OutputStreamWriter or a PrintWriter. The key is you must know the encoding used when writing the characters to correctly read them back.

The InputStreamReader class has four constructors, all of which require you to pass an InputStream.


public InputStreamReader(InputStream in)

public InputStreamReader(InputStream in,
        java.nio.charset.Charset charset)

public InputStreamReader(InputStream in,
        java.nio.charset.CharsetDecoder decoder)

public InputStreamReader(InputStream in, String charsetName)

For instance, to create an InputStreamReader that reads from a file, you can pass to its constructor an InputStream from Files.newInputStream.


Path path = ...
Charset charset = ...
InputStream inputStream = Files.newInputStream(path,
        StandardOpenOption.READ);
InputStreamReader reader = new InputStreamReader(
        inputStream, charset);

Listing 13.5 presents an example that uses a PrintWriter to write two Chinese characters and read them back.

Listing 13.5: Using InputStreamReader


package app13;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class InputStreamReaderTest {
    public static void main(String[] args) {
        Path textFile = Paths.get("C:\\temp\\myFile.txt");
        Charset chineseSimplifiedCharset =
                Charset.forName("GB2312");
        char[] chars = new char[2];
s        chars[0] = '\u4F60'; // representing images
        chars[1] = '\u597D'; // representing images;

        // write text
        try (BufferedWriter writer =
                Files.newBufferedWriter(textFile,
                    chineseSimplifiedCharset,
                    StandardOpenOption.CREATE)) {
            writer.write(chars);
        } catch (IOException e) {
            System.out.println(e.toString());
        }

        // read back
        try (InputStream inputStream =
                Files.newInputStream(textFile,
                StandardOpenOption.READ);

            InputStreamReader reader = new
                    InputStreamReader(inputStream,
                            chineseSimplifiedCharset)) {
            char[] chars2 = new char[2];
            reader.read(chars2);
            System.out.print(chars2[0]);
            System.out.print(chars2[1]);
        } catch (IOException e) {
            System.out.println(e.toString());
        }
    }
}

BufferedReader

BufferedReader is good for two things:

1. Wraps another Reader and provides a buffer that will generally improve performance.

2. Provides a readLine method to read a line of text.



The readLine method has the following signature:

public java.lang.String readLine() throws IOException

It returns a line of text from this Reader or null if the end of the stream has been reached.

The java.nio.file.Files class offers a newBufferedReader method that returns a BufferedReader. Here is the signature.


public static java.io.BufferedReader newBufferedReader(Path path,
        java.nio.charset.Charset charset)

As an example, this snippet reads a text file and prints all lines.


Path path = ...
BufferedReader br = Files.newBufferedReader(path, charset);
String line = br.readLine();
while (line != null) {
    System.out.println(line);
    line = br.readLine();
}

Also, prior to the addition of the java.util.Scanner class in Java 5, you had to use a BufferedReader to read user input to the console. Listing 13.6 shows a getUserInput method for taking user input on the console.

Listing 13.6: The getUserInput method


public static String getUserInput() {
    BufferedReader br = new BufferedReader(
            new InputStreamReader(System.in));
    try {
        return br.readLine();
    } catch (IOException ioe) {
    }
    return null;
}

You can do this because System.in is of type java.io.InputStream.

Note

java.util.Scanner was discused in Chapter 5, “Core Classes.”

Logging with PrintStream

By now you must be familiar with the print method of System.out. You use it especially for displaying messages to help you debug your code. However, by default System.out sends the message to the console, and this is not always preferable. For instance, if the amount of data displayed exceeds a certain lines, previous messages are no longer visible. Also, you might want to process the messages further, such as sending the messages by email.

The PrintStream class is an indirect subclass of OutpuStream. Here are some of its constructors:


public PrintStream(OutputStream out)

public PrintStream(OutputStream out, boolean autoFlush)

public PrintStream(OutputStream out, boolean autoFlush,
        String encoding)

PrintStream is very similar to PrintWriter. For example, both have nine print method overloads. Also, PrintStream has a format method similar to the format method in the String class.

System.out is of type java.io.PrintStream. The System object lets you replace the default PrintStream by using the setOut method. Listing 13.7 presents an example that redirects System.out to a file.

Listing 13.7: Redirecting System.out to a file


package app13;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class PrintStreamTest {
    public static void main(String[] args) {
        Path debugFile = Paths.get("C:\\temp\\debug.txt");
        try (OutputStream outputStream = Files.newOutputStream(
                debugFile, StandardOpenOption.CREATE,
                StandardOpenOption.APPEND);
            PrintStream printStream = new PrintStream(outputStream,
                    true)) {

            System.setOut(printStream);
            System.out.println("To file");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Note

You can also replace the default in and out in the System object by using the setIn and setErr methods.

Random Access Files

Using a stream to access a file dictates that the file is accessed sequentially, e.g. the first character must be read before the second, etc. Streams are ideal when the data comes in a sequential fashion, for example if the medium is a tape (widely used long ago before the emergence of harddisk) or a network socket. Streams are good for most of your applications, however sometimes you need to access a file randomly and using a stream would not be fast enough. For example, you may want to change the 1000th byte of a file without having to read the first 999 bytes. For random access like this, there are a few Java types that offer a solution. The first is the java.io.RandomAccessFile class, which is easy to use but now out-dated. The second is the java.nio.channels.SeekableByteChannel interface, which should be used in new applications. A discussion of RandomAccessFile can be found in Chapter 13 of the previous edition of this book. This edition, however, teaches random access files using SeekableByteChannel.

A SeekableByteChannel can perform both read and write operations. You can get an implementation of SeekableByteChannel using one of the Files class's newByteChannel methods:


public static java.nio.channels.SeekableByteChannel
        newByteChannel(Path path, OpenOption... options)

When using Files.newByteChannel() to open a file, you can choose an open option such as read-only or read-write or create-append. For instance


Path path1 = ...
SeekableByteChannel readOnlyByteChannel =
        Files.newByteChannel(path1, EnumSet.of(READ)));

Path path2 = ...
SeekableByteChannel writableByteChannel =
        Files.newByteChannel(path2, EnumSet.of(CREATE,APPEND));

SeekableByteChannel employs an internal pointer that points to the next byte to read or write. You can obtain the pointer position by calling the position method:

long position() throws java.io.IOException

When a SeekableByteChannel is created, initially it points to the first byte and position() would return 0L. You can change the pointer's position by invoking another position method whose signature is as follows.


SeekableByteChannel position(long newPosition)
        throws java.io.IOException

This pointer is zero-based, which means the first byte is indicated by index 0. You can pass a number greater than the file size without throwing an exception, but this will not change the size of the file. The size method returns the current size of the resource to which the SeekableByteChannel is connected:

long size() throws java.io.IOException

SeekableByteChannel is extremely simple. To read from or write to the underlying file, you call its read or write method, respectively.


int read(java.nio.ByteBuffer buffer) throws java.io.IOException

int write(java.nio.ByteBuffer buffer) throws java.io.IOException

Both read and write take a java.nio.ByteBuffer. This means to use SeekableByteChannel you need to be familiar with the ByteBuffer class. So, here is a crash course in ByteBuffer.

ByteBuffer is one of the many descendants of java.nio.Buffer, a data container for a specific primitive type. A ByteBuffer is of course a buffer for bytes. Other subclasses of Buffer include CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, and ShortBuffer.

A buffer has a capacity, which is the number of elements it contains. It also employs an internal pointer to indicate the next element to read or write. An easy way to create a ByteBuffer is by calling the static allocate method of the ByteBuffer class:

public static ByteBuffer allocate(int capacity)

For example, to create a ByteBuffer with a capacity of 100, you would write

ByteBuffer byteBuffer = ByteBuffer.allocate(100);

As you may suspect, a ByteBuffer is backed by a byte array. To retrieve this array, call the array method of ByteBuffer:

public final byte[] array()

The length of the array is the same as the ByteBuffer's capacity.

ByteBuffer provides two put methods for writing a byte:


public abstract ByteBuffer put(byte b)

public abstract ByteBuffer put(int index, byte b)

The first put method writes on the element pointed by the ByteBuffer's internal pointer. The second allows you to put a byte anywhere by specifying an index.

There are also two put methods for writing a byte array. The first one allows the content of a byte array or a subset of it to be copied to the ByteBuffer. It has this signature:

public ByteBuffer put(byte[] src, int offset, int length)

The src argument is the source byte array, offset is the location of the first byte in src, and length is the number of bytes to be copied.

The second put method puts the whole source byte array to be copied from position 0:

public ByteBuffer put(byte[] src)

ByteBuffer also provides various putXXX methods for writing different data types to the buffer. The putInt method, for example, writes an int whereas putShort puts a short. There are two versions of putXXX, one for putting a value at the next location pointed by the ByteBuffer's internal pointer, one for putting a value at an absolute position. The signatures of the putInt methods are as follows.


public abstract ByteBuffer putInt(int value)

public abstract ByteBuffer putInt(int index, int value)

To read from a ByteBuffer, the ByteBuffer class provides a number of get and getXXX methods, which come in two flavors: one for reading from the relative position and one for reading from an absolute element. Here are the signatures of some of the get and getXXX methods:


public abstract byte get()

public abstract byte get(int index)

public abstract float getFloat()

public abstract float getFloat(int index)

Okay. That's all you need to know about ByteBuffer, and now you are ready for SeekableByteChannel. Listing 13.8 shows how to use SeekableByteChannel.

Listing 13.8: Random access file


package app13;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class SeekableByteChannelTest {

    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(12);
        System.out.println(buffer.position()); // prints 0
        buffer.putInt(10);
        System.out.println(buffer.position()); // prints 8
        buffer.putLong(1234567890L);
        System.out.println(buffer.position()); // prints 16
        buffer.rewind(); // sets position to 0
        System.out.println(buffer.getInt()); // prints 10000
        System.out.println(buffer.getLong()); // prints 1234567890
        buffer.rewind();
        System.out.println(buffer.position()); // prints 0

        Path path = Paths.get("C:/temp/channel");
        System.out.println("-------------------------");
        try (SeekableByteChannel byteChannel =
                Files.newByteChannel(path,
                    StandardOpenOption.CREATE,
                    StandardOpenOption.READ,
                    StandardOpenOption.WRITE);) {
            System.out.println(byteChannel.position()); // prints 0
            byteChannel.write(buffer);
            System.out.println(byteChannel.position()); //prints 20

            // read file
            ByteBuffer buffer3 = ByteBuffer.allocate(40);
            byteChannel.position(0);
            byteChannel.read(buffer3);
            buffer3.rewind();
            System.out.println("get int:" + buffer3.getInt());
            System.out.println("get long:" + buffer3.getLong());
            System.out.println(buffer3.getChar());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The SeekableByteChannelTest class in Listing 13.8 starts by creating a ByteBuffer with a capacity of twelve and putting an int and a long in it. Remember that an int is four bytes long and a long takes 8 bytes.


        ByteBuffer buffer = ByteBuffer.allocate(12);
        buffer.putInt(10);
        buffer.putLong(1234567890L);

After receiving an int and a long, the buffer's position is at 16.

        System.out.println(buffer.position()); // prints 16

The class then creates a SeekableByteChannel and calls its write method, passing the ByteBuffer.


Path path = Paths.get("C:/temp/channel");
try (SeekableByteChannel byteChannel =
        Files.newByteChannel(path,
            StandardOpenOption.CREATE,
            StandardOpenOption.READ,
            StandardOpenOption.WRITE);) {
    byteChannel.write(buffer);

It then reads the file back and prints the results to the console.


// read file
ByteBuffer buffer3 = ByteBuffer.allocate(40);
byteChannel.position(0);
byteChannel.read(buffer3);
buffer3.rewind();
System.out.println("get int:" + buffer3.getInt());
System.out.println("get long:" + buffer3.getLong());
System.out.println(buffer3.getChar());

Object Serialization

Occasionally you need to persist objects into permanent storage so that the states of the objects can be retained and later retrieved. Java supports this through object serialization. To serialize an object, i.e. save it to permanent storage, you use an ObjectOutputStream. To deserialize an object, namely to retrieve the saved object, use ObjectInputStream. ObjectOutputStream is a subclass of OutputStream and ObjectInputStream is derived from InputStream.

The ObjectOutputStream class has one public constructor:

public ObjectOutputStream(OutputStream out)

After you create an ObjectOutputStream, you can serialize objects or primitives or the combination of both. The ObjectOutputStream class provides a writeXXX method for each individual type, where XXX denotes a type. Here is the list of the writeXXX methods.


public void writeBoolean(boolean value)

public void writeByte(int value)

public void writeBytes(String value)

public void writeChar(int value)

public void writeChars(String value)

public void writeDouble(double value)

public void writeFloat(float value)

public void writeInt(int value)

public void writeLong(long value)

public void writeShort(short value)

public void writeObject(java.lang.Object value)

For objects to be serializable their classes must implement java.io.Serializable. This interface has no method and is a marker interface. A marker interface is one that tells the JVM that an instance of an implementing class belongs to a certain type.

If a serialized object contains other objects, the contained objects’ classes must also implement Serializable for the contained objects to be serializable.

The ObjectInputStream class has one public constructor:

public ObjectInputStream(InputStream in)

To deserialize from a file, you can pass a InputStream that is connected to a file sink. The ObjectInputStream class has methods that are the opposites of the writeXXX methods in ObjectOutputStream. They are as follows:


public boolean readBoolean()

public byte readByte()

public char readChar()

public double readDouble()

public float readFloat()

public int readInt()

public long readLong()

public short readShort()

public java.lang.Object readObject()

One important thing to note: object serialization is based on a last in first out method. When deserializing multiple primitives/objects, the objects that were serialized first must be deserialized last.

Listing 13.10 shows a class that serializes an int and a Customer object. Note that the Customer class, given in Listing 13.9, implements Serializable.

Listing 13.9: The Customer class


package app13;
import java.io.Serializable;

public class Customer implements Serializable {
    public int id;
    public String name;
    public String address;
    public Customer (int id, String name, String address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }
}

Listing 13.10: Object serialization example


package app13;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class ObjectSerializationTest {

    public static void main(String[] args) {
        // Serialize
        Path path = Paths.get("C:\\temp\\objectOutput");
        Customer customer = new Customer(1, "Joe Blog",
                "12 West Cost");
        try (OutputStream outputStream =
                Files.newOutputStream(path,
                        StandardOpenOption.CREATE);
            ObjectOutputStream oos = new
                    ObjectOutputStream(outputStream)) {
            // write first object
            oos.writeObject(customer);
            // write second object
            oos.writeObject("Customer Info");
        } catch (IOException e) {
            System.out.print("IOException");
        }

        // Deserialize
        try (InputStream inputStream = Files.newInputStream(path,
                StandardOpenOption.READ);
            ObjectInputStream ois = new
                    ObjectInputStream(inputStream)) {
            // read first object
            Customer customer2 = (Customer) ois.readObject();
            System.out.println("First Object: ");
            System.out.println(customer2.id);
            System.out.println(customer2.name);
            System.out.println(customer2.address);

            // read second object
            System.out.println();
            System.out.println("Second object: ");
            String info = (String) ois.readObject();
            System.out.println(info);
        } catch (ClassNotFoundException ex) { // readObject still
      throws this exception
            System.out.print("ClassNotFound " + ex.getMessage());
        } catch (IOException ex2) {
            System.out.print("IOException " + ex2.getMessage());
        }
    }
}

s

Summary

Input/output operations are supported through the members of the java.io package. You can read and write data through streams and data is classified into binary data and text. In addition, Java support object serialization through the Serializable interface and the ObjectInputStream and ObjectOutputStream classes.

Questions

1. What is a stream?

2. Name four abstract classes that represent streams in the java.io package.

3. What is object serialization?

4. What is the requirement for a class to be serializable?

Friday, November 13, 2015

Ways to make money on the Internet.

Ways to make money on the Internet.

Earn small, but real money to start with - NOT the ' $1000+ a day' scams.
This page is simple to load quickly. No fancy graphics, just the honest facts.

First ... you need some 'tools'.
A dedicated credit card for the Internet. more...
Open FREE Internet banking accounts to receive payment. more...
Disposable email addresses. more...

~~~~~~~~~~~~~~~~~~~~~~~~~~~
Second ... programs where you earn money but are free to join.
Trickle income, like these sites below, build up a bank balance, give you confidence and earn you some funds to invest in Forex or other programs that require you to deposit money first.
Pay to Click (PTC) sites pay you a cent or less to click on advertisements every 24 hours. It may not sound much but it adds up while only a little time is required to earn from each site every day. Remember, you can click and earn from the same ad once every day.
The following Bux site is reliable and has $2 to $10 minimum payouts:- Neobux (proof)
Here is a tutorial on how to use Neobux which is useful for those who wish to translate the instructions from English.DonkeyMails still popular after years online - the classic 'paid mail' and PTC program. (proof)
ClixSense is another established program that pays 1c a click and also good for buying your own ads. It is best for Premium upgrade members (which costs from $17) as you will get many more links to click on and earn. My typical monthly earning proof here.

Bookmark your log-in page, remember your password and check your account several times daily for ads to click on.
You can upgrade your account by purchasing referrals.
Wait for the ad to load and then watch the 10 to 30 second timer count down. If you open two ads at the same time you will be paid for none of them. Be fair to the advertisers.
You can earn about 4c to 10c daily from one Bux/Mail site as a free member but a lot more if you upgrade. If you join 10 similar sites you can earn $1 a day in 30 minutes even without buying referrals!

Remember to bookmark this page and all the sites you join to make it easier to return daily.

Here are some tips on how to do offers and set up your PC to earn with GPT programs.
Surveys for payment or prizes. Get paid by manufacturers for your opinions on their products. All of these are free to join and really do pay. There are many survey scams on the Net and even some where they require payment from you. You should never have to pay to take part.
CashCrate has been paying for over 4 years with over 2 million members and pays worldwide although most surveys are for US, Canada and Europe. Sign up from the UK, for instance, and you get 52 options to complete offers, take surveys or shop online with payments ranging from 50 cents to $15. You get points for playing Flash games as well - good fun! They have a 'payment wall' where members post photos of their payments. They have a good tutorial here on how to earn money with CashCrate.

For sites where you earn by clicking on a link to make a search. Here is a tutorial on how to make a valid search . It will take longer than the 40 seconds shown to finish loading three pages but if the advertiser doesn't get paid, you wont get the links in the future..
High Payouts from 'free to join' programs.Normally I avoid very high payout programs where it sometimes takes a year to reach the minimum by which time the site may have vanished!
You WILL get paid with these programs; about $35 to $50 a month for just these programs and there are dozens more to choose from. Join up, add to your favourites or put an icon on your desktop by dragging on a links page for each program and visit the sites at intervals through the day and earn a bit each time. But do it EVERY day! It soon adds up.
TIPS -

1. Right click on the log-in page for each program and save a shortcut link to your desktop, or, Add to your Favourites in a new folder, named Daily, for instance. Much easier to remember your daily earning sites by double clicking on the icons or links.

2. Write the address and log-in details for each site in the back of your diary. It is easy to forget your user name and password and you can continue to earn money on another pc when away from home.

3. Get into the habit of regular visits. Most sites will cancel your account if you don't make use of it and any money earned will be lost.

4. Contact me if you need help or advice.
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Third ... programs where you need to invest some money.

The risk is greater but the rewards can be huge!
Playing the Foreign Exchange markets. A very volatile area where returns can be huge. More details on another page here ... Only start with money you can afford to loose.
High yield investment programs (HYIP) return high yields on your investment but are also high risk and of limited duration. Basically ' Pyramid' or 'Ponzi' schemes that pay out the early punters with income from later investors. Get in early with a sum you can afford to loose and earn 20% in a week or 45% profit in 14 days. Most use 'e-currency' so you will need to open free accounts here... To help in deciding which programs to invest in and when to pull out I have kept the statistics of several sites that have closed. This is a very volatile market but can be very profitable and exciting. A more detailed description is here.

~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fourth ... make a web site of your own and get advertisers on it.
The final group of earning programs can be placed on your own web site.
First you need a website with content interesting enough to attract visitors.
Think of a subject that you know a lot about - you, your family, your job, your hobby - whatever it is, focus on it and provide detailed information; facts, figures. Try to make your web site the definitive source of information on your chosen subject. A good tutorial on making a web site from start to finish is at HillofCash.com.
With a web site designed you need a domain name and a hosting service. It is like an address to the house where your web site lives. I use Easily to buy my domain names with HawkHost to host them. They give excellent service and support.
Promote your website using the points earned from working the PTS, PTR and PTC you joined above in section three and to get referrals to sign up under you. See a study on Promotion
There are many sites that will generate traffic to your web site. Sites that generate traffic automatically like QuietHits will produce a large number of hits but the visitor will only look at your page briefly. Visits from real people have more value and some of the best suppliers are EasyHits4U and TrafficSwarm. You may visit member's sites and so earn a visit to your site from a member. You can also purchase visits from a particular class of surfer to match your site content. DonkeyMails also has a manual surf section as well as earning from Pay to Read emails and Pay to Click sections so you can visit all the sections in turn and earn and get traffic at the same time.
Once you have a web site with solid content you have a 'product' to sell. Many of the top programs will not accept you as an affiliate unless you have a web site of substance.
The star payer is Google AdSense. They pay for clicks and pay very well and cleverly match their ads to the content of your page. Minimum payout is $100 by cheque.
A good affiliate scheme is TradeDoubler . where you can join up for free to any of dozens of schemes under one 'roof' . All affiliate schemes have a minimum payout limit of around $50 so grouping schemes together as with TradeDoubler . [aimed at European web sites] and Commission Junction [aimed at North America but covering the world] means that you can get a cheque earlier.
Lots of companies would love you to join them as an affiliate and will pay you a commission when your visitors buy some of their products. It makes sense to join up with companies compatible with your site. Amazon sell a lot more than just books now and pay 5% to 7.5% commission by targeting specific goods with a link from your site.

Bravenet has a lot of free goodies to add to your web site to attract more visitors and can help in setting up and hosting a web site with a free domain name. They also offer 50mb of free space on their servers to store your password protected back-up files and sensitive data. A well respected site of long standing..
Remember, these are all free to join; you have no outgoings other than your normal internet connection which you have anyway. To be perfectly frank, the only downside to these deals is that it takes up your time to organise the links, and your browser and/or web site will run a bit slower while advertising banners load.

The Internet is fast changing - please let us know if a good deal comes along or if you find a crooked deal; contact simetric.co.uk and we will check it out and give it an unbiased opinion.

Wednesday, November 11, 2015

Generics chapter-12

Chapter 12
Generics
With generics you can write a parameterized type and create instances of it by passing a reference type or reference types. The objects will then be restricted to the type(s). For example, thejava.util.List interface is generic. If you create a List by passing java.lang.String, you'll get a List that will only store Strings; In addition to parameterized types, generics support parameterized methods too.
The first benefit of generics is stricter type checking at compile time. This is most apparent in the Collections Framework. In addition, generics eliminate most type castings you had to perform when working with the Collections Framework.
This chapter teaches you how to use and write generic types. It starts with the section “Life without Generics” to remind us what we missed in earlier versions of JDK—s. Then, it presents some examples of generic types. After a discussion of the syntax, this chapter concludes with a section that explains how to write generic types.
Life without Generics
All Java classes derive from java.lang.Object, which means all Java objects can be cast to Object. Because of this, in pre-5 JDK—s, many methods in the Collections Framework accept anObject argument. This way, the collections become general-purpose utility types that can hold objects of any type. This imposes unpleasant consequences.
For example, the add method of List in pre-5 JDK's takes an Object argument:
public boolean add(java.lang.Object element)
As a result, you can pass an object of any type to add. The use of Object is by design. Otherwise, it could only work with a specific type of objects and there would then have to be differentList types, e.g. StringListEmployeeListAddressList, etc.
The use of Object in add is fine, but consider the get method, that returns an element in a List instance. Here is its signature prior to Java 5.
public java.lang.Object get(int index)
        throws IndexOutOfBoundsException
get returns an Object. Here is where the unpleasant consequences start to kick in. Suppose you have stored two String objects in a List:
List stringList1 = new ArrayList();
stringList1.add("Java 5 and later");
stringList1.add("with generics");
When retrieving a member from stringList1, you get an instance of java.lang.Object. In order to work with the original type of the member element, you must first downcast it to String.
String s1 = (String) stringList1.get(0);
With generic types, you can forget about type casting when retrieving objects from a List. And, there is more. Using the generic List interface, you can create specialized Lists, like one that only accepts Strings.
Introducing Generic Types
Like a method, a generic type can accept parameters. This is why a generic type is often called a parameterized type. Instead of passing primitives or object references in parentheses as with methods, you pass reference types in angle brackets to generic types.
Declaring a generic type is like declaring a non-generic one, except that you use angle brackets to enclose the list of type variables for the generic type.
MyType<typeVar1, typeVar2, ...>
For example, to declare a java.util.List, you would write
List<E> myList;
E is called a type variable, namely a variable that will be replaced by a type. The value substituting for a type variable will then be used as the argument type or the return type of a method or methods in the generic type. For the List interface, when an instance is created, E will be used as the argument type of add and other methods. E will also be used as the return type of getand other methods. Here are the signatures of add and get.
public boolean add<E o>
 
public E get(int index)
Note
A generic type that uses a type variable E allows you to pass E when declaring or instantiating the generic type. Additionally, if E is a class, you may also pass a subclass of E; if E is an interface, you may also pass a class that implements E.
If you pass String to a declaration of List, as in
List<String> myList;
the add method of the List instance referenced by myList will expect a String object as its argument and its get method will return a String. Because get returns a specific type of object, no downcasting is required.
Note
By convention, you use a single uppercase letter for type variable names.
To instantiate a generic type, you pass the same list of parameters as when declaring it. For instance, to create an ArrayList that works with String, you pass String in angle brackets.
List<String> myList = new ArrayList<String>();
The diamond language change in Java 7 allows explicit type arguments to constructors of parameterized classes, most notably collections, to be omitted in many situations. Therefore, the statement above can be written more concisely in Java 7 or later.
List<String> myList = new ArrayList<>();
In this case, the compiler will infer the arguments to the ArrayList.
As another example, java.util.Map is defined as
public interface Map<K, V>
K is used to denote the type of map keys and V the type of map values. The put and values methods have the following signatures:
V put(K key, V value)
Collection<V> values()
Note
A generic type must not be a direct or indirect child class of java.lang.Throwable because exceptions are thrown at runtime, and therefore it is not possible to check what type of exception that might be thrown at compile time.
As an example, Listing 12.1 compares List with and without generics.
Listing 12.1: Working with generic List
package app12;
import java.util.List;
import java.util.ArrayList;
 
public class GenericListTest {
    public static void main(String[] args) {
        // without generics
        List stringList1 = new ArrayList();
        stringList1.add("Java");
        stringList1.add("without generics");
        // cast to java.lang.String
        String s1 = (String) stringList1.get(0);
        System.out.println(s1.toUpperCase());
 
        // with generics and diamond
        List<String> stringList2 = new ArrayList<>();
        stringList2.add("Java");
        stringList2.add("with generics");
        // no type casting is necessary
        String s2 = stringList2.get(0);
        System.out.println(s2.toUpperCase());
    }
}
In Listing 12.1stringList2 is a generic List. The declaration List<String> tells the compiler that this instance of List can only store Strings. When retrieving member elements of the List, no downcasting is necessary because its get method returns the intended type, namely String.
Note
With generic types, type checking is done at compile time.

What's interesting here is the fact that a generic type is itself a type and can be used as a type variable. For example, if you want your List to store lists of strings, you can declare the List by passing List<String> as its type variable, as in
List<List<String>> myListOfListsOfStrings;
To retrieve the first string from the first list in myList, you would write:
String s = myListOfListsOfStrings.get(0).get(0);
Listing 12.2 presents a class that uses a List that accepts a List of Strings.
Listing 12.2: Working with List of Lists
package app12;
import java.util.ArrayList;
import java.util.List;
public class ListOfListsTest {
    public static void main(String[] args) {
        List<String> listOfStrings = new ArrayList<>();
        listOfStrings.add("Hello again");
        List<List<String>> listOfLists =
                new ArrayList<>();
        listOfLists.add(listOfStrings);
        String s = listOfLists.get(0).get(0);
        System.out.println(s); // prints "Hello again"
    }
}
Additionally, a generic type can accept more than one type variables. For example, the java.util.Map interface has two type variables. The first defines the type of its keys and the second the type of its values. Listing 12.3 presents an example that uses a generic Map.
Listing 12.3: Using the generic Map
package app12;
import java.util.HashMap;
import java.util.Map;
public class MapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        String value1 = map.get("key1");
    }
}
In Listing 12.3, to retrieve a value indicated by key1, you do not need to perform type casting.
Using Generic Types without Type Parameters
Now that the collection types in Java have been made generic, what about legacy codes? Fortunately, they will still work in Java 5 or later because you can use generic types without type parameters. For example, you can still use List the old way, as demonstrated in Listing 12.1.
List stringList1 = new ArrayList();
stringList1.add("Java");
stringList1.add("without generics");
String s1 = (String) stringList1.get(0);
A generic type used without parameters is called a raw type. This means that code written for JDK 1.4 and earlier versions will continue working in Java 5 or later.
One thing to note, though, starting from Java 5 the Java compiler expects you to use generic types with parameters. Otherwise, the compiler will issue warnings, thinking that you may have forgotten to define type variables with the generic type. For example, compiling the code in Listing 12.1 gave you the following warning because the first List was used as a raw type.
Note: app12/GenericListTest.java uses unchecked or unsafe
        operations.
Note: Recompile with –Xlint:unchecked for details.
You have these options at your disposal to get rid of the warnings when working with raw types:
images compile with the −source 1.4 flag.
images use the @SuppressWarnings(“unchecked”) annotation (See Chapter 18, “Annotations”)
images upgrade your code to use List<Object>. Instances of List<Object> can accept any type of object and behave like a raw type List. However, the compiler will not complain.

Warning
Raw types are available for backward compatibility. New development should shun them. It is possible that future versions of Java will not allow raw types.
Using the? Wildcard
I mentioned that if you declare a List<aType>, the List works with instances of aType and you can store objects of one of these types:
images an instance of aType.
images an instance of a subclass of aType, if aType is a class
images an instance of a class implementing aType if aType is an interface.

However, note that a generic type is a Java type by itself, just like java.lang.String or java.io.File. Passing different lists of type variables to a generic type result in different types. For example, list1 and list2 below reference to different types of objects.
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
list1 references a List of java.lang.Object instances and list2 references a List of String objects. Even though String is a subclass of ObjectList<String> has nothing to do withList<Object>. Therefore, passing a List<String> to a method that expects a List<Object> will raise a compile time error. Listing 12.4 shows this.
Listing 12.4: AllowedTypeTest.java
package app12;
import java.util.ArrayList;
import java.util.List;
 
public class AllowedTypeTest {
    public static void doIt(List<Object> l) {
    }
    public static void main(String[] args) {
        List<String> myList = new ArrayList<>();
        // this will generate a compile error
        doIt(myList);
    }
}
Listing 12.4 won't compile because you are passing the wrong type to the doIt method. doIt expects an instance of List<Object> and you are passing an instance of List<String>.
The solution to this problem is the ? wildcard. List<?> means a list of objects of any type. Therefore, the doIt method should be changed to:
public static void doIt(List<?> l) {
}
There are circumstances where you want to use the wildcard. For example, if you have a printList method that prints the members of a List, you may want to make it accept a List of any type. Otherwise, you would end up writing many overloads of printListListing 12.5 shows the printList method that uses the ? wildcard.
Listing 12.5: Using the? wildcard
package app12;
import java.util.ArrayList;
import java.util.List;
 
public class WildCardTest {
    public static void printList(List<?> list) {
        for (Object element : list) {
            System.out.println(element);
        }
    }
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<>();
        list1.add("Hello");
        list1.add("World");
        printList(list1);
 
        List<Integer> list2 = new ArrayList<>();
        list2.add(100);
        list2.add(200);
        printList(list2);
    }
}
The code in Listing 12.4 demonstrates that List<?> in the printList method means a List of any type.
Note, however, it is illegal to use the wildcard when declaring or creating a generic type, such as this.
List<?> myList = new ArrayList<?>(); // this is illegal
If you want to create a List that can accept any type of object, use Object as the type variable, as in the following line of code:
List<Object> myList = new ArrayList<>();
Using Bounded Wildcards in Methods
In the section “Using the? Wildcard” above, you learned that passing different type variables to a generic type creates different Java types. In many cases, you might want a method that accepts a List of different types. For example, if you have a getAverage method that returns the average of numbers in a list, you may want the method to be able to work with a list of integers or a list of floats or a list of another number type. However, if you write List<Number> as the argument type to getAverage, you won't be able to pass a List<Integer> instance or a List<Double> instance because List<Number> is a different type from List<Integer> or List<Double>. You can use List as a raw type or use a wildcard, but this is depriving you of type safety checking at compile time because you could also pass a list of anything, such as an instance of List<String>. You could use List<Number>, but you must always pass aList<Number> to the method. This would make your method less useful because you work with List<Integer> or List<Long> probably more often than with List<Number>.
There is another rule to circumvent this restriction, i.e. by allowing you to define an upper bound of a type variable. This way, you can pass a type or its subtype. In the case of thegetAverage method, you may be able to pass a List<Number> or a List of instances of a Number subclass, such as List<Integer> or List<Float>.
The syntax for using an upper bound is as follows:
GenericType<? extends upperBoundType>
For example, for the getAverage method, you would write:
List<? extends Number>
Listing 12.6 illustrates the use of such a bound.
Listing 12.6: Using a bounded wildcard
package app12;
import java.util.ArrayList;
import java.util.List;
public class BoundedWildcardTest {
    public static double getAverage(
            List<? extends Number> numberList) {
        double total = 0.0;
        for (Number number : numberList) {
            total += number.doubleValue();
        }
        return total/numberList.size();
    }
 
    public static void main(String[] args) {
        List<Integer> integerList = new ArrayList<>();
        integerList.add(3);
        integerList.add(30);
        integerList.add(300);
        System.out.println(getAverage(integerList)); // 111.0
        List<Double> doubleList = new ArrayList<>();
        doubleList.add(3.0);
        doubleList.add(33.0);
        System.out.println(getAverage(doubleList)); // 18.0
    }
}
Thanks to the upper bound, the getAverage method in Listing 12.6 allows you to pass a List<Number> or a List of instances of any subclass of java.lang.Number.
Lower Bounds
The extends keyword is used to define an upper bound of a type variable. Though useable only in very few applications, it is also possible to define a lower bound of a type variable, by using the super keyword. For example, using List<? super Integer> as the type to a method argument indicates that you can pass a List<Integer> or a List of objects whose class is a superclass of java.lang.Integer.
Writing Generic Types
Writing a generic type is not much different from writing other types, except for the fact that you declare a list of type variables that you intend to use somewhere in your class. These type variables come in angle brackets after the type name. For example, the Point class in Listing 12.7 is a generic class. A Point object represents a point in a coordinate system and has an X component (abscissa) and a Y component (ordinate). By making Point generic, you can specify the degree of accuracy of a Point instance. For example, if a Point object needs to be very accurate, you can pass Double as the type variable. Otherwise, Integer would suffice.
Listing 12.7: The generic Point class
package app12;
public class Point<T> {
    T x;
    T y;
    public Point(T x, T y) {
        this.x = x;
        this.y = y;
    }
    public T getX() {
        return x;
    }
    public T getY() {
        return y;
    }
    public void setX(T x) {
        this.x = x;
    }
    public void setY(T y) {
        this.y = y;
    }
}
In Listing 12.7T is the type variable for the Point class. T is used as the return value of both getX and getY and as the argument type for setX and setY. In addition, the constructor also accepts two T type variables.
Using Point is just like using other generic types. For example, the following code creates two Point objects, point1 and point2. The former passes Integer as the type variable, the latter Double.
Point<Integer> point1 = new Point<>(4, 2);
point1.setX(7);
Point<Double> point2 = new Point<>(1.3, 2.6);
point2.setX(109.91);
Summary
Generics enable stricter type checking at compile time. Used especially in the Collections Framework, generics make two contributions. First, they add type checking to collection types at compile time, so that the type of objects that a collection can hold is restricted to the type passed to it. For example, you can now create an instance of java.util.List that hold strings and will not accept Integer or other types. Second, generics eliminate the need for type casting when retrieving an element from a collection.
Generic types can be used without type variables, i.e. as raw types. This provision makes it possible to run pre-Java 5 codes with JRE 5 or later. For new applications, you should not use raw types as future releases of Java may not support them.
In this chapter you have also learned that passing different type variables to a generic type results in different Java types. This is to say that List<String> is a different type fromList<Object>. Even though String is a subclass of java.lang.Object, passing a List<String> to a method that expects a List<Object> generates a compile error. Methods that expect aList of anything can use the ? wildcard. List<?> means a List of objects of any type.
Finally, you have seen that writing generic types is not that different from writing ordinary Java types. You just need to declare a list of type variables in angle brackets after the type name. You then use these type variables as the types of method return values or as the types of method arguments. By convention, a type variable name consists of a single up

1. What are the main benefits of generics?

2. What does “parameterized type” mean?