CodeGym /Courses /JAVA 25 SELF /Setting the encoding when reading/writing files

Setting the encoding when reading/writing files

JAVA 25 SELF
Level 37 , Lesson 2
Available

1. Introduction

Let’s be honest right away: if you’ve ever seen something like Привет instead of Russian text, you’ve already fallen victim to an incorrect encoding. This happens when a file was written in one encoding and read in another. For example, the file was saved as UTF-8 but read as Windows-1251, or vice versa.

By default, Java uses the system encoding, which you can get like this:

System.out.println(System.getProperty("file.encoding"));

On one machine it might be UTF-8, on another — Windows-1251, and elsewhere — ISO-8859-1. That’s why it’s always better to specify the encoding explicitly. This is especially important if you work with multilingual data; if files will be used on different machines or opened in other programs; or if you need your code to behave consistently in any environment, not just on your own machine.

The Charset class: your friend in the world of encodings

In Java, the class java.nio.charset.Charset is used to work with encodings. It lets you specify an encoding by name (for example, "UTF-8") or use standard constants (StandardCharsets.UTF_8).

Examples of standard encodings:

Encoding Java constant
UTF-8
StandardCharsets.UTF_8
UTF-16
StandardCharsets.UTF_16
ISO-8859-1
StandardCharsets.ISO_8859_1
Windows-1251
Charset.forName("Windows-1251")

Using constants is preferable: there’s less chance of misspelling a name, and you won’t get an UnsupportedCharsetException.

2. Reading files with an explicit encoding

Old way:

import java.io.*;
import java.nio.charset.StandardCharsets;

BufferedReader reader = new BufferedReader(
    new InputStreamReader(
        new FileInputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Specify the encoding explicitly
    )
);

Modern way:

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.BufferedReader;

BufferedReader reader = Files.newBufferedReader(
    Paths.get("example.txt"),
    StandardCharsets.UTF_8 // <-- Specify the encoding explicitly
);

It’s recommended to use the second approach — it’s shorter, safer, and works well with try-with-resources.

Example: read a line from a file

try (BufferedReader reader = Files.newBufferedReader(
        Paths.get("hello.txt"),
        StandardCharsets.UTF_8)) {
    String line = reader.readLine();
    System.out.println("Read: " + line);
}

Why this matters: If the file was saved in UTF-8 but you read it as Windows-1251, Cyrillic characters will be garbled. If you specify the correct encoding, the text will be read correctly on any OS.

3. Writing files with an explicit encoding

Old way:

import java.io.*;
import java.nio.charset.StandardCharsets;

BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(
        new FileOutputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Specify the encoding explicitly
    )
);

Modern way:

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.BufferedWriter;

BufferedWriter writer = Files.newBufferedWriter(
    Paths.get("example.txt"),
    StandardCharsets.UTF_8 // <-- Specify the encoding explicitly
);

Example: write a line to a file

try (BufferedWriter writer = Files.newBufferedWriter(
        Paths.get("hello.txt"),
        StandardCharsets.UTF_8)) {
    writer.write("Hello, world!");
}

Result: The file will be saved in UTF-8, and it can be opened correctly in any editor that supports UTF-8.

4. Useful details

How to list supported encodings

import java.nio.charset.Charset;

public class ListCharsets {
    public static void main(String[] args) {
        System.out.println("Available encodings:");
        Charset.availableCharsets().forEach((name, charset) -> System.out.println(name));
    }
}

Tip: If you use an exotic encoding (for example, for ancient Chinese ideographs or Martian emoji), check whether your JVM supports it.

Using try-with-resources: don’t forget to close streams

When working with files, it’s important to close streams to avoid resource leaks. Modern Java code uses the try-with-resources construct:

try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
    // Work with the file
}

The stream will close automatically, even if an error occurs.

Recommendations

  • It’s better to always specify the encoding explicitly when reading and writing files, even if you’re sure that “the default works.”
  • Use UTF-8 for new files — it’s the de facto standard, especially if you work with the web, JSON, XML, or want your files to be readable everywhere.
  • For legacy files (for example, an export from 1C, old databases, CSV from Windows) use the encoding they were saved with (for example, Windows-1251, ISO-8859-1).
  • Don’t use outdated classes where the encoding isn’t specified explicitly: FileReader/FileWriter. Use InputStreamReader/OutputStreamWriter with an explicit encoding or methods from Files instead.
  • For large files use buffering (BufferedReader/BufferedWriter) to avoid consuming too much memory.

5. Common mistakes when working with encodings

Mistake #1: No encoding specified when reading/writing a file.
If you don’t specify an encoding, Java uses the system default ("file.encoding"). It may work on your machine, but your colleague gets “mojibake.”

Mistake #2: Mismatch between encodings when reading and writing.
The file was written in one encoding but read in another. For example, the file was written in UTF-8 but read as Windows-1251 — Cyrillic gets mangled.

Mistake #3: Using the legacy classes FileReader/FileWriter.
These classes don’t let you specify the encoding explicitly — avoid using them. Instead, use InputStreamReader/OutputStreamWriter with an explicit encoding or methods from Files.

Mistake #4: Typo in the encoding name.
For example, you wrote "utf8" instead of "UTF-8" or "win1251" instead of "Windows-1251". Java will throw an UnsupportedCharsetException.

Mistake #5: Stream not closed — the file wasn’t written.
If you don’t use try-with-resources or explicitly close the stream, some data may not be flushed to disk.

1
Task
JAVA 25 SELF, level 37, lesson 2
Locked
Audit of Java machine system settings 🖥️
Audit of Java machine system settings 🖥️
1
Task
JAVA 25 SELF, level 37, lesson 2
Locked
Digital Language Atlas: Overview of Supported Charsets 🗺️
Digital Language Atlas: Overview of Supported Charsets 🗺️
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION