
dtonhofer
Functional Programming in Java, Second Edition: Functional Programming in Java, Second Edition: JUnit code improvements for Chapter 11, pages 192 ff “Refactoring File Processing”
In this code:
- We actually create the (temporary) file we want to read and delete it again at the end.
- Default charsets for reading text files are the work of the devil, we set UTF-8 explicitly.
- The files need to be properly closed with try-with-resources, this also applies to the stream approach.
- A “long” count as return value seems excessive, dropping to int.
package chapter11;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class FileProcessingTest {
private static File actualFile;
private final static Charset charset = StandardCharsets.UTF_8;
// Creates a file "/tmp/WordCount13982583023783245787.java" for example
@BeforeAll
static void createTmpFile() throws IOException {
actualFile = File.createTempFile("WordCount", ".java");
try (FileWriter writer = new FileWriter(actualFile, charset)) {
writer.write("package foo;\n");
writer.write("public class X {\n");
writer.write("}\n");
writer.write("public class Y {\n");
writer.write("}\n");
}
}
@AfterAll
static void deleteTmpFile() throws IOException {
// or one could have installed a handler with deleteOnExit()
actualFile.delete();
}
interface WordCount {
int countInFile(String word, File file) throws IOException;
}
// https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/io/FileReader.html
// https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/io/BufferedReader.html
static class WordCountBefore implements WordCount {
public int countInFile(final String searchWord, final File file) throws IOException {
int count = 0;
// Use try-with-resources / automatic resource management to clean up.
// Specify the charset, "default chartset" is the devil's work!
try (final var bufferedReader = new BufferedReader(new FileReader(file, charset))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
final String[] words = line.split(" ");
for (String word : words) {
if (word.equals(searchWord)) {
count++;
}
}
}
return count;
}
}
}
// https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/nio/file/Files.html
static class WordCountAfter implements WordCount {
// The Files.lines() call may throw IOException.
// Additionally, the count() this yields a "long", so we need to cast to fit the interface.
// We still must use try-with-resources to close the file.
public int countInFile(final String searchWord, final File file) throws IOException {
try (final Stream<String> stream = Files.lines(file.toPath(), charset)) {
return (int) stream
.flatMap(line -> Stream.of(line.split(" ")))
.filter(word -> word.equals(searchWord))
.count();
}
}
}
private static void commonFileProcessingTests(final WordCount wordCount, File file) {
assertAll(
() -> assertEquals(2, wordCount.countInFile("public", file)),
() -> assertEquals(1, wordCount.countInFile("package", file)));
}
@Test
void fileProcessingBefore() {
commonFileProcessingTests(new WordCountBefore(), actualFile);
}
@Test
void fileProcessingAfter() {
commonFileProcessingTests(new WordCountAfter(), actualFile);
}
}
Popular Pragmatic Bookshelf topics

Some minor things in the paper edition that says “3 2020” on the title page verso, not mentioned in the book’s errata online:
p. 186 But...
New

Title: Web Development with Clojure, Third Edition, pg 116
Hi - I just started chapter 5 and I am stuck on page 116 while trying to star...
New

Hi! I know not the intentions behind this narrative when called, on page XI:
mount() |> handle_event() |> render()
but the correc...
New

Hi @venkats,
It has been mentioned in the description of ‘Supervisory Job’ title that 2 things as mentioned below result in the same eff...
New

I’m running Android Studio “Arctic Fox” 2020.3.1 Patch 2, and I’m embarrassed to admit that I only made it to page 8 before running into ...
New

When I run the coverage example to report on missing lines, I get:
pytest --cov=cards --report=term-missing ch7
ERROR: usage: pytest [op...
New

Is there any place where we can discuss the solutions to some of the exercises? I can figure most of them out, but am having trouble with...
New

I’m a newbie to Rails 7 and have hit an issue with the bin/Dev script mentioned on pages 112-113.
Iteration A1 - Seeing the list of prod...
New

The allprojects block listed on page 245 produces the following error when syncing gradle:
“org.gradle.api.GradleScriptException: A prob...
New

Getting an error when installing the dependencies at the start of this chapter:
could not compile dependency :exla, "mix compile" failed...
New
Other popular topics

Bought the Moonlander mechanical keyboard. Cherry Brown MX switches. Arms and wrists have been hurting enough that it’s time I did someth...
New

Do the test and post your score :nerd_face:
:keyboard:
If possible, please add info such as the keyboard you’re using, the layout (Qw...
New

We’ve talked about his book briefly here but it is quickly becoming obsolete - so he’s decided to create a series of 7 podcasts, the firs...
New

Author Spotlight
Mike Riley
@mriley
This month, we turn the spotlight on Mike Riley, author of Portable Python Projects. Mike’s book ...
New

The overengineered Solution to my Pigeon Problem.
TL;DR: I built a wifi-equipped water gun to shoot the pigeons on my balcony, controlle...
New

Author Spotlight
Erin Dees
@undees
Welcome to our new author spotlight! We had the pleasure of chatting with Erin Dees, co-author of ...
New

Inside our android webview app, we are trying to paste the copied content from another app eg (notes) using navigator.clipboard.readtext ...
New

Large Language Models like ChatGPT say The Darnedest Things.
The Errors They MakeWhy We Need to Document Them, and What We Have Decided ...
New

I’m able to do the “artistic” part of game-development; character designing/modeling, music, environment modeling, etc.
However, I don’t...
New

Background
Lately I am in a quest to find a good quality TTS ai generation tool to run locally in order to create audio for some videos I...
New
Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /ruby
- /wasm
- /erlang
- /phoenix
- /keyboards
- /rails
- /js
- /python
- /security
- /go
- /swift
- /vim
- /clojure
- /emacs
- /haskell
- /java
- /onivim
- /svelte
- /typescript
- /crystal
- /kotlin
- /c-plus-plus
- /tailwind
- /gleam
- /ocaml
- /react
- /flutter
- /elm
- /vscode
- /ash
- /opensuse
- /centos
- /php
- /deepseek
- /html
- /zig
- /scala
- /sublime-text
- /textmate
- /nixos
- /debian
- /lisp
- /agda
- /react-native
- /kubuntu
- /arch-linux
- /revery
- /django
- /ubuntu
- /manjaro
- /spring
- /diversity
- /nodejs
- /lua
- /slackware
- /julia
- /c
- /neovim