August 2nd, 2024

Common I/O Tasks in Modern Java

The article outlines Java I/O improvements since Java 8, emphasizing UTF-8 encoding, the java.nio.file.Files class for file operations, and recommending modern methods for reading, writing, and managing files.

Read original articleLink Icon
Common I/O Tasks in Modern Java

The article discusses common I/O tasks in modern Java, particularly focusing on improvements made since Java 8. Key topics include reading and writing text files, handling web data, and managing files in directories. Java 18 established UTF-8 as the default character encoding, simplifying text I/O operations. The java.nio.file.Files class, enhanced in Java 8, 11, and 12, provides efficient methods for file operations. For reading text files, developers can use Files.readString and Files.readAllLines, while large files can be processed lazily with Files.lines. Writing text files is straightforward with Files.writeString and Files.write. The article also highlights the use of InputStream for reading data from the web, recommending HttpClient for requests requiring headers, and simpler methods for direct data retrieval. The Files API is emphasized for directory traversal, with Files.list and Files.walk being the primary methods for accessing directory entries. For ZIP file handling, Java 8 introduced a more user-friendly ZIP file system, allowing for easier file operations within ZIP archives. Temporary files and directories can be created using Files.createTempFile and Files.createTempDirectory. The article concludes by encouraging developers to utilize the Files methods for common tasks, avoiding legacy classes like java.io.File, and to adopt simpler approaches for I/O operations.

Related

Moving to Java 17 or how I learned to stop worrying and love NoSuchMethodError

Moving to Java 17 or how I learned to stop worrying and love NoSuchMethodError

Icon Solutions upgraded to Java 17 in IPF 2024.1 for Spring 6 and Spring Boot 3 compatibility. Challenges included plugin and dependency adjustments, emphasizing centralized management and code cleanliness post-upgrade for smoother transitions.

Migrating from Java 8 to Java 17 II: Notable API Changes Since Java 8

Migrating from Java 8 to Java 17 II: Notable API Changes Since Java 8

The article details API changes in Java versions 9 to 17, emphasizing improvements for Java 8 migrations. Changes include null handling, performance enhancements, string improvements, switch expressions, record classes, and utility additions for developer productivity and code readability.

Implementing a Single-Threaded Blocking Bare Bones TCP/IP Server

Implementing a Single-Threaded Blocking Bare Bones TCP/IP Server

The article explains creating a single-threaded TCP/IP server in Java, covering port listening, client connections, message handling, and server behavior. It discusses networking concepts and demonstrates concurrent client connections.

Mini-JVM: Educational Implementation of a Simplified Java Virtual Machine (JVM)

Mini-JVM: Educational Implementation of a Simplified Java Virtual Machine (JVM)

A GitHub project offers a simplified Java Virtual Machine (JVM) in Java, executing a subset of Java bytecode instructions. It covers frames, call stack, heap, class table, and a custom instruction set. Consider limitations.

Is Java Still Relevant Nowadays?

Is Java Still Relevant Nowadays?

In 2023, 49% of developers use Java, with 33% as their primary language. Its versatility, strong educational presence, and ongoing support ensure Java remains relevant and offers career opportunities.

Link Icon 8 comments
By @layer8 - 9 months
Note that

    try (Stream<String> lines = Files.lines(path)) {
        ...
    }
has a catch (pun not intended ;)), in that if you write

    catch (IOException ex) {
        ... handle it ...
    }
this surprisingly only catches I/O errors thrown directly by the lines() method, but not those thrown during the stream processing, since those are UncheckedIOExceptions. This is because the Stream API designers decided (very unfortunately, IMO) to not want to deal with checked exceptions.

I therefore prefer using Files::newBufferedReader and BufferedReader::readLine.

———

The `new Scanner(path)` example is arguably even worse, because upon I/O error the tokens() implementation simply behaves as if the end of the file was reached, and you have to manually check with Scanner::ioException if an error occurred.

By @eknkc - 9 months
The "URL.openConnection()" API has always looked out of place to me. I thought it was deprecated at some point but guess not. It feels backwards. Like you would not do "select * from tbl".execute(db)..

There was something more fucked up about the URL API which I can not remember. I think it triggers blocking DNS resolution on construction or something. Haven't written Java for more than 10 years though. Might be mixing something up.

By @whartung - 9 months
These articles are useful for grognards like me who have these patterns etched into muscle memory from 20 years ago.
By @foolfoolz - 9 months
i like all of these except passing a remote url to .readAllBytes(). this seems fine for coding little things on your own. but in production i would recommend instead setting up an http client with the settings you want, calling a get merit that returns an input stream, and then calling .readAllBytes()
By @echelon - 9 months
Java I/O has come a long way since the Java 7 days, not to mention the rest of the language. I remember being stuck on Java 7 until 2019 and lamenting the nice features we couldn't use.

Rust I/O feels like it was inspired heavily by Java's I/O and it owes a lot of credit.

By @ncann - 9 months
Too bad there still isn't a way to delete recursively a folder without manually traversing it.
By @okr - 9 months
Yeah, do not forget to close streams always, when you do not know, where the stream come from.

FileSystem from Zip, i did know that. Does it also work for writing?

And people use var nowadays. Pity, val has not found its way into java.

And i wish for more useful stream operators, which can lift streams up, like groups. And tee is finally in it, but looks a bit bloated when being used.

And parallelStreams(), people always forget, that it is not good for long running tasks. You always block the default executor.

But in general, iam happy with the progress. We have pressure from Kotlin, but so far, i have not felt the desire to switch.