Interacting with the World
The often not well-understood topic.
java.io
java.nio
java.net
java.io
first
IO is were performance counts.
The entry point to the file system.
user.dir
, temp.dir
and more
equals
works similarly to String.equals
file://
Different path names and separators
':'
or ';'
'/'
or '\'
foo/bar.txt
or bar.txt
user.dir
mostly start dir of VM
/tmp
or c:\tmp
/tmp//../tmp
is /tmp
Don't assume that certain things will happen. There is OS and FS magic going on. This is especially valid for mounts and links. Don't forget, your Mac sucks, because it does not know anything about casing aka it is a little Windows-like.
What can happen
EOFException, InterruptedIOException and others
The classic version
// newFile object, NOT a new file or file connection
final File file = new File("/tmp/foobar.txt");
// create this new file
final boolean created = file.createNewFile();
// remove this file again
final boolean deleted = file.delete();
// create a temp file
final File tempFile = File.createTempFile("foo", ".txt")
// alternatively register for automatic deletion
tempFile.deleteOnExit();
The modern version
// get us a new path
final Path path = Paths.get("/tmp", "foobar.txt");
// create this new file
final Path file = Files.createFile(path);
// delete it
Files.delete(file);
// create a temp file
final Path tempFile = Files.createTempFile("foo", ".txt");
// register for automatic deletion
tempFile.toFile().deleteOnExit();
There are many more methods of course.
A Byte at the time
Just bytes, nothing else.
FileInputStream
: Read from a fileByteArrayInputStream
: Read from an array
FilterInputStream
: Filter a streamObjectInputStream
: Read Java objectsPipedInputStream
: Receiving end of pipeSequenceInputStream
: Read more than one stream and switch to the next automaticallyFileOutputStream
: Write to a fileByteArrayOutputStream
: Write to an array
FilterOutputStream
: Filter a streamObjectOutputStream
: Write Java objectsPipedOutputStream
: Sending end of pipeMost other streams are specialized versions of Filter*Stream.
Copy file data
read()
is int and communicates also state (sigh)public void copy()
{
try (final InputStream in = new FileInputStream("/tmp/in.txt");
final OutputStream out = new FileOutputStream("/tmp/out.txt");)
{
int b; // I will hold the read byte or status code
// 0-255 indicate a byte, -1 indicates nothing to read anymore
while ((count = in.read()) != -1)
{
out.write(count);
}
}
catch(final FileNotFoundException e)
{
// cannot do anything
}
catch (IOException e)
{
// something went wrong
}
// due to try-with-resource, we don't have to close anything explicitly
}
This is inefficient, but see later.
Transition to NIO
public void copy()
{
try (final InputStream in =
new FileInputStream("/tmp/in.txt");
final OutputStream out =
new FileOutputStream("/tmp/out.txt");)
{
int b; // I will hold the read byte or status code
// 0-255 indicate a byte, -1 indicates nothing to read anymore
while ((count = in.read()) != -1)
{
out.write(count);
}
}
catch(final FileNotFoundException e)
{
// cannot do anything
}
catch (IOException e)
{
// something went wrong
}
// due to try-with-resource, we don't have to close anything explicitly
}
public void copy()
{
try (final InputStream in =
Files.newInputStream(Paths.get("/tmp/in.txt"));
final OutputStream out =
Files.newOutputStream(Paths.get("/tmp/out.txt"));)
{
int b; // I will hold the read byte or status code
// 0-255 indicate a byte, -1 indicates nothing to read anymore
while ((count = in.read()) != -1)
{
out.write(count);
}
}
catch(final FileNotFoundException e)
{
// cannot do anything
}
catch (IOException e)
{
// something went wrong
}
// due to try-with-resource, we don't have to close anything explicitly
}
Opening is more efficient due to NIO usage.
Full NIO now
public void copy()
{
try (final InputStream in =
Files.newInputStream(Paths.get("/tmp/in.txt"));
final OutputStream out =
Files.newOutputStream(Paths.get("/tmp/out.txt"));)
{
int b; // I will hold the read byte or status code
// 0-255 indicate a byte, -1 indicates nothing to read anymore
while ((count = in.read()) != -1)
{
out.write(count);
}
}
catch(final FileNotFoundException e)
{
// cannot do anything
}
catch (IOException e)
{
// something went wrong
}
// due to try-with-resource, we don't have to close anything explicitly
}
/**
Behaviorial not 100% identical
*/
public void copy()
{
try
{
Files.copy(
Paths.get("/tmp/in.txt"),
Paths.get("/tmp/out.txt"),
StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e)
{
// something went wrong
}
}
Opening is more efficient due to NIO usage.
A character at the time
Characters not bytes!
Typical character streams
BufferedReader
: Read a character with internal bufferingCharArrayReader
: Read from a char arrayFilterReader
: Filter a stream of charactersInputStreamReader
: Translate from a byte streamPipedReader
: Read from a pipeStringReader
: Read from a string (odd, isn't it)BufferedWriter
: Write buffered to a sinkCharArrayWriter
: Write to an arrayFilterWriter
: Filter a streamOutputStreamWriter
: Translate to a byte output streamPipedWriter
: StringWriter
: Characters, not bytes!
Just read lines from a file
public void readLines()
{
try (final BufferedReader r =
new BufferedReader(
new FileReader("/tmp/in.txt")))
{
String readLine = null;
while ((readLine = r.readLine()) != null)
{
System.console().printf(readLine);
}
}
catch (FileNotFoundException e)
{
// handling here
}
catch (IOException e)
{
// handling here
}
}
A plain reader does not offer lines, only characters or character arrays.
Everything is nicer in NIO land
public void readLines()
{
try
{
Files.lines(Paths.get("/tmp", "in.txt"))
.forEach(
s -> System.console().printf(s)
);
}
catch (IOException e)
{
// handling here
}
}
A plain reader does not offer lines, only characters or character arrays.
Harvest the power of nesting
BufferedWriter bw = null; FileOutputStream fos = null;
CheckedOutputStream acos = null; CheckedOutputStream bcos = null;
try
{
fos = new FileOutputStream("/tmp/test.gz");
BufferedOutputStream bos = new BufferedOutputStream(fos);
acos = new CheckedOutputStream(bos, new CRC32());
GZIPOutputStream gzipos = new GZIPOutputStream(acos);
bcos = new CheckedOutputStream(gzipos, new CRC32());
OutputStreamWriter osw = new OutputStreamWriter(bcos);
bw = new BufferedWriter(osw);
bw.write("This is a test. This is a test.\n");
}
catch(IOException e)
{
// handle here
}
finally
{
if (bw != null)
{
try
{
bw.close();
// we closed normally
System.out.format("Checksum before compression %s and after %s",
bcos.getChecksum().getValue(),
acos.getChecksum().getValue());
}
catch (final IOException e)
{
// ok, make sure the file is closed at least
try
{
if (fos != null)
{
fos.close();
}
}
catch(IOException ioe)
{
// really bad
}
}
}
}
Place the buffer at the right position.
Important considerations
deprecated
, many methods or classes are not longer suitable for us
Read, filter, write