From 4a2807e5125e631bcb86a4b874e6e45db72d493c Mon Sep 17 00:00:00 2001 From: Jim Bethancourt Date: Sat, 5 Sep 2026 08:03:22 -0500 Subject: [PATCH 1/2] Replace Charset.defaultCharset() with StandardCharsets.UTF_8 --- .../java/org/hjug/refactorfirst/report/ReportWriter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/report/src/main/java/org/hjug/refactorfirst/report/ReportWriter.java b/report/src/main/java/org/hjug/refactorfirst/report/ReportWriter.java index fe0095da..5fd25cff 100644 --- a/report/src/main/java/org/hjug/refactorfirst/report/ReportWriter.java +++ b/report/src/main/java/org/hjug/refactorfirst/report/ReportWriter.java @@ -10,7 +10,7 @@ import java.io.OutputStreamWriter; import java.nio.channels.Channels; import java.nio.channels.SeekableByteChannel; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.NoSuchFileException; @@ -162,7 +162,7 @@ private void writeAtomicallySecure(SecureDirectoryStream directory, Path r try { try (SeekableByteChannel channel = directory.newByteChannel(temporaryName, options); BufferedWriter writer = new BufferedWriter( - new OutputStreamWriter(Channels.newOutputStream(channel), Charset.defaultCharset()))) { + new OutputStreamWriter(Channels.newOutputStream(channel), StandardCharsets.UTF_8))) { writer.write(content); } directory.move(temporaryName, directory, reportName); @@ -218,7 +218,7 @@ public void writeAtomically(Path reportName, String content) throws IOException try { try (SeekableByteChannel channel = Files.newByteChannel(temporaryName, options); BufferedWriter writer = new BufferedWriter( - new OutputStreamWriter(Channels.newOutputStream(channel), Charset.defaultCharset()))) { + new OutputStreamWriter(Channels.newOutputStream(channel), StandardCharsets.UTF_8))) { writer.write(content); } // Verify temp file is not a symlink before move From debc03e5d1ba3e9ef0fa2b175d9f87d0a269693e Mon Sep 17 00:00:00 2001 From: Jim Bethancourt Date: Sat, 5 Sep 2026 08:27:04 -0500 Subject: [PATCH 2/2] Added test to ensure only UTF-8 charaters are emitted --- .../refactorfirst/report/ReportWriterTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/report/src/test/java/org/hjug/refactorfirst/report/ReportWriterTest.java b/report/src/test/java/org/hjug/refactorfirst/report/ReportWriterTest.java index 11ed41d5..05bb226d 100644 --- a/report/src/test/java/org/hjug/refactorfirst/report/ReportWriterTest.java +++ b/report/src/test/java/org/hjug/refactorfirst/report/ReportWriterTest.java @@ -5,6 +5,7 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardWatchEventKinds; @@ -279,4 +280,20 @@ void containReportDirectory_rejectsSymlinkedAncestor(@TempDir Path tempDir) thro IllegalArgumentException.class, () -> ReportWriter.containReportDirectory(tempDir.toFile(), "linked/site")); } + + @Test + void writeReportToDisk_emitsUtf8ForNonAsciiContent(@TempDir Path tempDir) throws IOException { + String nonAsciiContent = "café 漢字 😀"; + Path outputDir = tempDir.resolve("output"); + Files.createDirectories(outputDir); + + ReportWriter.writeReportToDisk(outputDir.toString(), "test.html", nonAsciiContent); + + Path outputFile = outputDir.resolve("test.html"); + assertTrue(Files.exists(outputFile)); + + byte[] writtenBytes = Files.readAllBytes(outputFile); + byte[] expectedBytes = nonAsciiContent.getBytes(StandardCharsets.UTF_8); + assertArrayEquals(expectedBytes, writtenBytes, "ReportWriter must emit UTF-8 bytes"); + } }