Slide navigation: Forward with space bar, → arrow key, or PgDn. Backwards with ← or PgUp.

Copyright © Cay S. Horstmann 2016
java.util.streamjava.nio.file.Files class:
Path path = Paths.get(filenameString); // We'll cover paths later this lesson InputStream in = Files.newInputStream(path); OutputStream out = Files.newOutputStream(path);
URL url = new URL("http://horstmann.com/index.html");
InputStream in = url.openStream();byte[] array:
byte[] bytes = ...; InputStream in = new ByteArrayInputStream(bytes);
ByteArrayOutputStream and then collect the bytes:
ByteArrayOutputStream out = new ByteArrayOutputStream(); Write to out byte[] bytes = out.toByteArray();
read method returns a single byte (as an int) or -1 at the end of input:
InputStream in = ...;
int b = in.read();
if (b != -1) { byte value = (byte) b; ... }
byte[] bytes = ...; int len = in.read(bytes);
ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] bytes = new byte[1024]; while ((len = in.read(bytes)) != -1) out.write(bytes, 0, len); bytes = out.toByteArray();
byte[] bytes = Files.readAllBytes(path);
OutputStream out = ...; int b = ...; out.write(b); byte[] bytes = ...; out.write(bytes); out.write(bytes, start, length);
out.close();
try-with-resources block:
try (OutputStream out = ...) {
out.write(bytes);
}Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);

byte[] bytes = url.openStream().readAllBytes();There is also
readNBytes.InputStream.transferTo(OutputStream) transfers all bytes from an input stream to an output stream.Reader.transferTo(Writer)PrintWriter, Scanner, etc. can be specified as Charset instead of String
new Scanner(path, StandardCharsets.UTF_8)
Scanner.tokens gets a stream of tokens, similar to Pattern.splitAsStream from Java 8:
Stream<String> tokens = new Scanner(path).useDelimiter("\\s*,\\s*").tokens(); StandardCharsets.UTF_8 for Charset parameters, "UTF-8" for string parameters.Reader for any input stream:
InputStream inStream = ...; Reader in = new InputStreamReader(inStream, charset);
read method reads one char value.
String content = new String(Files.readAllBytes(path), charset);
List<String> lines = Files.readAllLines(path, charset);
try (Stream<String> lines = Files.lines(path, charset)) {
...
}
import java.nio.file.*;
import java.nio.charset.*;
Files.readAllLines(Paths.get("poem.txt"), StandardCharsets.UTF_8)
Files.readAllLines(Paths.get("poem-win1252.txt"), StandardCharsets.UTF_8)
// Throws MalformedInputException
Files.readAllLines(Paths.get("poem-win1252.txt"), Charset.forName("windows-1252"))
// Ok
Files.readAllLines(Paths.get("poem.txt"), Charset.forName("windows-1252"))
// Looks weird
Scanner to split input into numbers, words, and so on:
Scanner in = new Scanner(path, "UTF-8");
while (in.hasNextDouble()) {
double value = in.nextDouble();
...
}in.useDelimiter("\\PL+");
while (in.hasNext()) {
String word = in.next();
...
}import java.nio.file.*;
import java.nio.charset.*;
Scanner in = new Scanner(Paths.get("poem.txt"), "UTF-8");
while (in.hasNext()) System.out.println(in.next());
// Now try again with
in.useDelimiter("\\PL+");
PrintWriter out = new PrintWriter(Files.newBufferedWriter(path, charset)); PrintWriter out = new PrintWriter(filenameString, charsetString);
out.print, out.println, or out.printf to produce output.try (PrintWriter out = ...) { ... }Files.write(path, contentString.getBytes(charset)); Files.write(path, lines, charset);
Files.write(path, lines, charset, StandardOpenOption.APPEND);
import java.nio.file.*;
import java.nio.charset.*;
PrintWriter out = new PrintWriter("test.txt", "UTF-8")
for (int i = 1; i <= 100; i++) out.printf("%6d%n", i * i);
// Now open another console and type cat squares.txt
out.close();
// In the other console, type cat squares.txt
Writer object. Example: Throwable.printStackTrace(PrintWriter out)
StringWriter:
StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer));
String stackTrace = writer.toString();
StringWriter writer = new StringWriter(); new Throwable().printStackTrace(new PrintWriter(writer)); writer.toString()
DataInput/DataOutput interfaces have methods readInt/writeInt, readDouble/writeDouble, and so on.DataInputStream/DataOutputStream:
DataInput in = new DataInputStream(Files.newInputStream(path)); DataOutput out = new DataOutputStream(Files.newOutputStream(path));
"r" for reading or "rw" for writing:
RandomAccessFile file = new RandomAccessFile(filenameString, "rw");
getFilePointer method yields the current position (as a long).seek method moves to a new position.int value = file.readInt(); file.seek(file.getFilePointer() - 4); file.writeInt(value + 1);
FileChannel channel = FileChannel.open(path,
StandardOpenOption.READ, StandardOpenOption.WRITE)ByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE,
0, channel.size());get, getInt, getDouble, and so on to read, and the equivalent put methods to write:
int position = ...; int value = buffer.getInt(position); buffer.put(position, value + 1);
java memoryMap.MemoryMapTest /opt/jdk1.8.0/src.zip java memoryMap.MemoryMapTest2 /opt/jdk1.8.0/src.zip
Path objects specify abstract path names (which may not currently exist on disk)./ or C:\Paths.get to create paths:
Path absolute = Paths.get("/", "home", "cay");
Path relative = Paths.get("myapp", "conf", "user.properties");/ or \ is supplied for the default file system.Path homeDirectory = Paths.get("/home/cay");p.resolve(q) computes “p then q”.q is absolute, that's just q.p, then follow q:
Path workPath = homeDirectory.resolve("myapp/work");resolve is relativize, yielding “how to get from p to q”.
Paths.get("/home/cay").relativize(Paths.get("/home/fred/myapp")) yields "../fred/myapp".normalize removes ./ or directory/../ and other redundancies.toAbsolutePath makes a path absolute. Path p = Paths.get("/home", "cay", "myapp.properties");
Path parent = p.getParent(); // The path /home/cay
Path file = p.getFileName(); // The last element, myapp.properties
Path root = p.getRoot(); // The initial segment / (null for a relative path)
Path first = p.getName(0); // The first element
Path dir = p.subpath(1, p.getNameCount()); // All but the first elementfor (Path component : path) {
...
}File class, use:
File file = path.toFile(); Path path = file.toPath();
import java.nio.file.*;
Path p = Paths.get(".")
p = p.toAbsolutePath()
p.resolve("../lesson2")
p.resolve("../lesson2").normalize()
p.getParent()
p.getFileName()
p.getRoot()
p.getName(0)
p.getNameCount()
Files.createDirectory(path); // All but the last component must exist Files.createDirectories(path); // Missing components are created
Files.createFile(path);
Path tempFile = Files.createTempFile(dir, prefix, suffix); Path tempFile = Files.createTempFile(prefix, suffix); Path tempDir = Files.createTempDirectory(dir, prefix); Path tempDir = Files.createTempDirectory(prefix);
Files.createTempFile(null, ".txt") might return a path such as
/tmp/1234405522364837194.txtFiles.exists(path) checks whether a path currently exists.Files.isDirectory(path), Files.isRegularFile(path), Files.isSymbolicLink(path) to find out whether the path is a directory, file, or symlink.isHidden, isExecutable, isReadable, isWritable of the Files class.Files.size(path) reports the file size as a long value.copy or move method:
Files.copy(fromPath, toPath); Files.move(fromPath, toPath);
Files.copy(fromPath, toPath, StandardCopyOption.REPLACE_EXISTING,
SteandardCopyOption.COPY_ATTRIBUTES);
Files.move(fromPath, toPath, StandardCopyOption.ATOMIC_MOVE);Files.delete(path); // Throws exception if path doesn't exist
boolean deleted = Files.deleteIfExists(path);Files.list(dirpath) yields a Stream<Path> of the directory entries.try (Stream<Path> entries = Files.list(pathToDirectory)) { ... }Files.walk(dirpath) to visit all descendants of subdirectories as well.... java/nio/ByteBufferAsDoubleBufferB.java java/nio/charset java/nio/charset/CoderMalfunctionError.java java/nio/charset/CharsetDecoder.java java/nio/charset/spi java/nio/charset/spi/CharsetProvider.java ... java/nio/charset/UnsupportedCharsetException.java java/nio/HeapFloatBufferR.java ...
find instead of walk for greater efficiency:
Files.find(path, maxDepth, (path, attr) -> attr.size() > 100000)
Files.list(Paths.get("../..")).forEach(System.out::println)
Files.walk(Paths.get("../..")).forEach(System.out::println)
Files.find(Paths.get("../.."), Integer.MAX_VALUE,
(p, attr) -> attr.size() > 100000).forEach(System.out::println)
Files.walk to copy a directory tree:
Files.walk(source).forEach(p -> {
try {
Path q = target.resolve(source.relativize(p));
if (Files.isDirectory(p))
Files.createDirectory(q);
else
Files.copy(p, q);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
});FileVisitor instead:
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
public FileVisitResult postVisitDirectory(Path dir, IOException ex) throws IOException {
if (ex != null) throw ex;
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});Paths class looks up paths in the default file system.FileSystem zipfs = FileSystems.newFileSystem(Paths.get(zipname), null);
Files.copy(zipfs.getPath(sourceName), targetPath);
Files.walk(zipfs.getPath("/")).forEach(p -> { Process p });Path zipPath = Paths.get("myfile.zip");
URI uri = new URI("jar", zipPath.toUri().toString(), null);
// Constructs the URI jar:file://myfile.zip
try (FileSystem zipfs = FileSystems.newFileSystem(uri, Collections.singletonMap("create", "true"))) {
// To add files, copy them into the ZIP file system
Files.copy(sourcePath, zipfs.getPath("/").resolve(targetPath));
}Path p = Paths.get("/opt/jdk1.8.0/src.zip")
FileSystem zipfs = FileSystems.newFileSystem(p, null)
Files.walk(zipfs.getPath("/")).limit(100).forEach(System.out::println)
Files.copy(zipfs.getPath("/java/lang/String.java"), Paths.get("/tmp/String.java"));
Path zipPath = Paths.get("/tmp/myfile.zip");
URI uri = new URI("jar", zipPath.toUri().toString(), null);
FileSystem zipfs = FileSystems.newFileSystem(uri,
Collections.singletonMap("create", "true"))
InputStream in = new ByteArrayInputStream("Hello".getBytes("UTF-8"));
Files.copy(in, zipfs.getPath("/hello.txt"))
zipfs.close();
URL url = new URL("http://horstmann.com/index.html");
InputStream in = url.openStream();GET request).URLConnection class for more complex cases:
POST requestURLConnection object:
URLConnection connection = url.openConnection();
connection.setRequestProperty("Accept-Charset", "UTF-8, ISO-8859-1");connection.setDoOutput(true);
try (OutputStream out = connection.getOutputStream()) { Write to out }connection.connect(); // If you skipped step 3 Map<String, List<String>> headers = connection.getHeaderFields();
try (InputStream in = connection.getInputStream()) { Read from in }HttpURLConnection, the default encoding is application/x-www-form-urlencoded.URLConnection connection = url.openConnection();
connection.setDoOutput(true);
try (Writer out = new OutputStreamWriter(
connection.getOutputStream(), StandardCharsets.UTF_8)) {
boolean first = true;
for (Map.Entry<String, String> entry : postData.entrySet()) {
if (first) first = false;
else out.write("&");
out.write(URLEncoder.encode(entry.getKey(), "UTF-8"));
out.write("=");
out.write(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
}firefox https://www.usps.com/zip4/ java post.PostTest > /tmp/out.html firefox /tmp/out.html
java.HTTPie.
URLConnection/HttpURLConnectionjdk.incubator package.
--add-modules jdk.incubator.httpclientHttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.ALWAYS)
.build();HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://horstmann.com"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());
client.sendAsync(request, HttpResponse.BodyHandler.asString()) .completeOnTimeout(errorResponse, 10, TimeUnit.SECONDS) .thenAccept(response -> Process response.body());
jshell --add-modules jdk.incubator.httpclient
import jdk.incubator.http.*;
import java.net.*;
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder().
uri(URI.create("http://www.gutenberg.org/files/11/11-0.txt")).
GET().
build();
client.sendAsync(request, HttpResponse.BodyHandler.asString()).
thenAccept(response -> System.out.println(response.body()));
[Jj]e?a.+ matches Java and jealous but not Jim or ja.. * + ? { | ( ) [ \ ^ $. matches any character.* is 0 or more, + 1 or more, ? 0 or 1 repetition.{2,4}| denotes alternatives: (Java|Scala)() are used for grouping.[...] delimit character classes, such as [A-Za-z]\s (space), \pL (Unicode letters), complements \S, \PL^ and $ match the beginning and end of input.\ to match them literally.\ in Java strings.Pattern pattern = Pattern.compile(regexString);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
String match = matcher.group();
...
}matcher.start(), matcher.end() to get the position of the current match in the string.import java.util.regex.*
Matcher matcher = Pattern.compile("[0-9]+").matcher(input)
String input = "9:45am";
while (matcher.find()) System.out.println(matcher.group());
matches method to check whether a string matches a regex:
String regex = "[12]?[0-9]:[0-5][0-9][ap]m";
if (Pattern.matches(regex, input)) { ... } Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(input); if (matcher.matches()) ...
Stream<String> result = streamOfStrings.filter(pattern.asPredicate());
String regex = "[12]?[0-9]:[0-5][0-9][ap]m";
Pattern.matches(regex, "9:45am")
Pattern.matches(regex, "9:65")
import java.util.stream.*
import java.util.regex.*
import java.nio.file.*
Files.lines(Paths.get("/usr/share/dict/words")).
filter(Pattern.compile(".+q.+q.+").asPredicate()).
forEach(System.out::println)
Blackwell Toaster USD29.95
(\p{Alnum}+(\s+\p{Alnum}+)*)\s+([A-Z]{3})([0-9.]*)group method to get at each group:
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
item = matcher.group(1);
currency = matcher.group(3);
price = matcher.group(4);
}(?<item>\p{Alnum}+(\s+\p{Alnum}+)*)\s+(?<currency>[A-Z]{3})(?<price>[0-9.]*)item = matcher.group("item");Pattern commas = Pattern.compile("\\s*,\\s*");
String[] tokens = commas.split(input);
// String "1, 2, 3" turns into array ["1", "2", "3"]Stream<String> tokens = commas.splitAsStream(input);
String.split method:
String[] tokens = input.split("\\s*,\\s*");replaceAll on the matcher:
Matcher matcher = commas.matcher(input);
String result = matcher.replaceAll(", ");String.replaceAll method:
String result = input.replaceAll("\s*,\s*", ", ");$n or names $name are replaced with the captured group:
String result = "3:45".replaceAll(
"(\\d{1,2}):(?<minutes>\\d{2})",
"$1 hours and ${minutes} minutes");
Matcher.stream and Scanner.findAll gets a stream of match results:
Pattern pattern = Pattern.compile("[^,]");
Stream<String> matches = pattern.matcher(str).results().map(MatchResult::group);
matches = new Scanner(path).findAll(pattern).map(MatchResult::group);Matcher.replaceFirst/replaceAll now have a version with a replacement function: String result = Pattern.compile("\\pL{4,}")
.matcher("Mary had a little lamb")
.replaceAll(m -> m.group().toUpperCase());
// Yields "MARY had a LITTLE LAMB"
Serializable marker interface:
public class Employee implements Serializable { ... }ObjectOutputStream object:
ObjectOutputStream out = new ObjectOutputStream(
Files.newOutputStream(path));
writeObject method:
Employee peter = new Employee("Peter", 90000);
Employee paul = new Manager("Paul", 180000);
out.writeObject(peter);
out.writeObject(paul);ObjectInputStream object:
ObjectInputStream in = new ObjectInputStream(
Files.newInputStream(path));
Employee e1 = (Employee) in.readObject(); Employee e2 = (Employee) in.readObject();
Employee peter = new Employee("Peter", 40000);
Manager paul = new Manager("Paul", 105000);
Manager mary = new Manager("Mary", 180000);
paul.setAdmin(peter);
mary.setAdmin(peter);
ObjectOutputStream out = new ObjectOutputStream(
Files.newOutputStream(path));
out.writeObject(peter);
out.writeObject(paul);
out.writeObject(mary);transient modifer.readObject/writeObject methods.
readResolve/writeReplace methods.
serialVersionUID is obtained by hashing field names and types.serialVersionUID changes, readObject throws an exception.private static final long serialVersionUID = 2L; // Version 2