File Handling and I/O

Writing and Updating Text Files

ReadingPreview

আপনি একটি free preview lesson দেখছেন।

Lesson Overview

আগের lesson-এ আমরা text file পড়েছি।

এখন আমরা শিখব কীভাবে Java দিয়ে text file:

  • Create করা যায়
  • Overwrite করা যায়
  • Append করা যায়
  • Lines হিসেবে লেখা যায়
  • UTF-8 encoding ব্যবহার করা যায়
  • Parent directory ensure করা যায়
  • Safer update strategy ব্যবহার করা যায়

Modern Java-তে common APIs:

Files.writeString()
Files.write()
Files.createDirectories()
Files.move()

এই lesson-এ আমরা বিশেষভাবে focus করব:

Small text files
Markdown content
Generated reports
Configuration exports
Course content storage

Learning Objectives

এই lesson শেষে আপনি পারবেন:

  • Files.writeString() দিয়ে text লিখতে
  • Existing file overwrite করতে
  • New file create করতে
  • Append mode ব্যবহার করতে
  • StandardOpenOption বুঝতে
  • Files.write() দিয়ে lines লিখতে
  • Parent directories তৈরি করতে
  • UTF-8 explicitly ব্যবহার করতে
  • Write failures translate করতে
  • Temporary file + replacement strategy explain করতে

Basic File Writing

Suppose:

Path path =
        Path.of(
                "course.md"
        );

Write:

Files.writeString(
        path,
        "# Java Course"
);

If successful, file contains:

# Java Course

Files.writeString()

Common signature:

Files.writeString(
        path,
        content
);

It writes a String to a file.

Example:

String content =
        """
        # Java

        Learn Java the right way.
        """;

Files.writeString(
        path,
        content
);

Explicit UTF-8

Prefer:

Files.writeString(
        path,
        content,
        StandardCharsets.UTF_8
);

Import:

import java.nio.charset.StandardCharsets;

This makes the storage encoding explicit.


What Happens If the File Does Not Exist?

With the normal writeString() behavior, Java usually creates the file.

Example:

Path path =
        Path.of(
                "new-course.md"
        );

Files.writeString(
        path,
        "Java"
);

If the parent directory exists, the file is created.


What Happens If the File Already Exists?

By default:

Files.writeString(
        path,
        content
);

replaces the existing content.

Example existing file:

Old content

Write:

Files.writeString(
        path,
        "New content"
);

Result:

New content

Overwrite Is Destructive

This is important:

Files.writeString(...)

does not automatically preserve old content.

If existing file contains:

Lesson 1
Lesson 2
Lesson 3

and you write:

Updated lesson

the old content is replaced.

Before choosing overwrite, understand the operation contract.


StandardOpenOption

Java allows more explicit write behavior through:

StandardOpenOption

Import:

import java.nio.file.StandardOpenOption;

Common options:

CREATE
CREATE_NEW
WRITE
APPEND
TRUNCATE_EXISTING

CREATE

StandardOpenOption.CREATE

Meaning:

Create the file if it does not exist.

If it already exists, Java can still open it depending on other options.


CREATE_NEW

StandardOpenOption.CREATE_NEW

Meaning:

Create only if the file does not exist.

If file already exists:

FileAlreadyExistsException

is thrown.


WRITE

StandardOpenOption.WRITE

opens the file for writing.

Usually combined with other options.


TRUNCATE_EXISTING

StandardOpenOption.TRUNCATE_EXISTING

means:

If the file exists, clear its current content before writing.

Example:

Files.writeString(
        path,
        content,
        StandardCharsets.UTF_8,
        StandardOpenOption.CREATE,
        StandardOpenOption.TRUNCATE_EXISTING,
        StandardOpenOption.WRITE
);

This explicitly expresses overwrite behavior.


APPEND

StandardOpenOption.APPEND

adds content to the end of the existing file.

Example:

Files.writeString(
        path,
        "New line\n",
        StandardCharsets.UTF_8,
        StandardOpenOption.CREATE,
        StandardOpenOption.APPEND
);

If file contains:

Java

result becomes:

Java
New line

assuming the previous content ended with a line break or you added one deliberately.


Append Does Not Add a New Line Automatically

This:

Files.writeString(
        path,
        "Spring",
        StandardCharsets.UTF_8,
        StandardOpenOption.APPEND
);

does not automatically insert:

\n

If file contains:

Java

the result may become:

JavaSpring

If you want a new line:

Files.writeString(
        path,
        System.lineSeparator()
        + "Spring",
        StandardCharsets.UTF_8,
        StandardOpenOption.APPEND
);

System.lineSeparator()

Instead of hardcoding:

"\n"

you can use:

System.lineSeparator()

It represents the platform line separator.

For many application file formats, especially controlled text formats, using \n is also common.

The important thing is consistency.


Create Only If Missing

Suppose course content should never overwrite an existing file accidentally.

Use:

Files.writeString(
        path,
        content,
        StandardCharsets.UTF_8,
        StandardOpenOption.CREATE_NEW
);

If file exists:

FileAlreadyExistsException

is thrown.


Handling FileAlreadyExistsException

try {
    Files.writeString(
            path,
            content,
            StandardCharsets.UTF_8,
            StandardOpenOption.CREATE_NEW
    );
} catch (
        FileAlreadyExistsException exception
) {
    throw new IllegalStateException(
            "Course content already exists.",
            exception
    );
} catch (
        IOException exception
) {
    throw new IllegalStateException(
            "Could not write course content.",
            exception
    );
}

Specific exception first.


Creating Parent Directories

Suppose target is:

content/java-oop/module-1/lesson.md

If:

content/java-oop/module-1

does not exist, file writing may fail.

Create parents first:

Path parent =
        path.getParent();

if (parent != null) {
    Files.createDirectories(
            parent
    );
}

createDirectories()

Files.createDirectories(
        path
);

creates all missing directories in the path.

Example:

content/java-oop/module-1

If:

content

exists but:

java-oop/module-1

does not, Java creates the missing levels.


createDirectory() vs createDirectories()

createDirectory()

Creates one directory.

Its parent must already exist.

createDirectories()

Creates all missing parent directories as needed.

For application storage paths, createDirectories() is often more practical.


Parent May Be null

For:

Path.of(
        "course.md"
)

calling:

path.getParent()

may return:

null

So:

Files.createDirectories(
        path.getParent()
);

could fail.

Use:

Path parent =
        path.getParent();

if (parent != null) {
    Files.createDirectories(
            parent
    );
}

Writing Multiple Lines

Java also provides:

Files.write(...)

Example:

List<String> lines =
        List.of(
                "Java",
                "Spring",
                "Kafka"
        );

Files.write(
        path,
        lines,
        StandardCharsets.UTF_8
);

This writes lines to the file.


Files.write() vs writeString()

Use:

writeString()

when content is naturally one text document.

Use:

write()

when you already have:

Iterable<String>

or:

List<String>

Example:

Course Markdown → writeString()
Generated list of topics → write()

Writing a Markdown Lesson

String markdown =
        """
        # Introduction to Java

        Java is a strongly typed programming language.
        """;

Files.writeString(
        Path.of(
                "content",
                "java-oop",
                "introduction.md"
        ),
        markdown,
        StandardCharsets.UTF_8
);

Safe Storage Method

A reusable method:

public static void writeText(
        Path path,
        String content
) {
    if (path == null) {
        throw new IllegalArgumentException(
                "Path is required."
        );
    }

    if (content == null) {
        throw new IllegalArgumentException(
                "Content is required."
        );
    }

    try {
        Path parent =
                path.getParent();

        if (parent != null) {
            Files.createDirectories(
                    parent
            );
        }

        Files.writeString(
                path,
                content,
                StandardCharsets.UTF_8
        );
    } catch (
        IOException exception
    ) {
        throw new IllegalStateException(
                "Could not write text file.",
                exception
        );
    }
}

Validate Before Writing

Weak:

Files.writeString(
        path,
        content
);

if (content.isBlank()) {
    throw new IllegalArgumentException(
            "Content cannot be blank."
    );
}

The invalid content has already been written.

Better:

if (
        content == null
        || content.isBlank()
) {
    throw new IllegalArgumentException(
            "Content is required."
    );
}

Files.writeString(
        path,
        content
);

Validate before side effects.


Decide Whether Empty Content Is Valid

Do not assume:

Empty file = invalid

Some use cases allow empty files.

Example:

Placeholder file
Empty generated export
Optional content

Other cases may require non-blank content.

The domain contract decides.


Appending Course Activity

Suppose you want a simple audit file:

course-events.log

Append:

public static void appendEvent(
        Path path,
        String event
) {
    try {
        Path parent =
                path.getParent();

        if (parent != null) {
            Files.createDirectories(
                    parent
            );
        }

        Files.writeString(
                path,
                event
                + System.lineSeparator(),
                StandardCharsets.UTF_8,
                StandardOpenOption.CREATE,
                StandardOpenOption.APPEND
        );
    } catch (
        IOException exception
    ) {
        throw new IllegalStateException(
                "Could not append course event.",
                exception
        );
    }
}

Append Is Not a Database

A text file append strategy may work for:

  • Simple local logs
  • Development tools
  • Small exports

But it should not automatically be treated as a replacement for:

Database
Durable event log
Transactional storage

Concurrent writers and consistency require more careful design.


Concurrent Writes

Suppose two threads write to the same file.

Without coordination:

Thread A writes
Thread B writes

results can be surprising depending on operation and timing.

Potential issues:

  • Lost updates
  • Interleaved content
  • Last writer wins
  • Partial business state

File APIs do not automatically solve application-level concurrency.


Read-Modify-Write Risk

Weak pattern:

String current =
        Files.readString(
                path
        );

String updated =
        current
        + "\nNew content";

Files.writeString(
        path,
        updated
);

Two writers can both read the same old state and overwrite each other.

This is a classic lost-update problem.


Simple Overwrite vs Safer Replacement

Direct overwrite:

Files.writeString(
        target,
        content
);

is simple.

But if writing fails midway, depending on the system and failure mode, the target may not contain the intended complete content.

For important files, a safer pattern is:

Write temporary file
↓
Move temporary file over target

Temporary File Replacement Strategy

Concept:

course.md

Update safely by:

  1. Write new content to temporary file
  2. Ensure write completes
  3. Move temp file over target

Example:

Path temp =
        Files.createTempFile(
                target.getParent(),
                "course-",
                ".tmp"
        );

Then:

Files.writeString(
        temp,
        content,
        StandardCharsets.UTF_8
);

Then:

Files.move(
        temp,
        target,
        StandardCopyOption.REPLACE_EXISTING
);

StandardCopyOption.REPLACE_EXISTING

Import:

import java.nio.file.StandardCopyOption;

Use:

Files.move(
        temp,
        target,
        StandardCopyOption.REPLACE_EXISTING
);

This replaces the target if it already exists.


Atomic Move

Java also provides:

StandardCopyOption.ATOMIC_MOVE

Example:

Files.move(
        temp,
        target,
        StandardCopyOption.REPLACE_EXISTING,
        StandardCopyOption.ATOMIC_MOVE
);

An atomic move means observers should see either:

Old file

or:

New file

rather than an intermediate state.


Atomic Move Is Not Always Supported

Important:

ATOMIC_MOVE

may not be supported by every file system or across different file systems.

It can throw:

AtomicMoveNotSupportedException

Therefore robust code may attempt atomic move and fall back when appropriate.


Safer Replace Helper

public static void replaceText(
        Path target,
        String content
) {
    if (target == null) {
        throw new IllegalArgumentException(
                "Target path is required."
        );
    }

    if (content == null) {
        throw new IllegalArgumentException(
                "Content is required."
        );
    }

    Path parent =
            target.toAbsolutePath()
                    .normalize()
                    .getParent();

    if (parent == null) {
        throw new IllegalArgumentException(
                "Target parent directory is required."
        );
    }

    Path temp = null;

    try {
        Files.createDirectories(
                parent
        );

        temp =
                Files.createTempFile(
                        parent,
                        "write-",
                        ".tmp"
                );

        Files.writeString(
                temp,
                content,
                StandardCharsets.UTF_8
        );

        try {
            Files.move(
                    temp,
                    target,
                    StandardCopyOption.REPLACE_EXISTING,
                    StandardCopyOption.ATOMIC_MOVE
            );
        } catch (
                AtomicMoveNotSupportedException exception
        ) {
            Files.move(
                    temp,
                    target,
                    StandardCopyOption.REPLACE_EXISTING
            );
        }
    } catch (
        IOException exception
    ) {
        throw new IllegalStateException(
                "Could not safely replace text file.",
                exception
        );
    } finally {
        if (
                temp != null
                && Files.exists(
                        temp
                )
        ) {
            try {
                Files.deleteIfExists(
                        temp
                );
            } catch (
                IOException ignored
            ) {
                // Cleanup failure should normally be logged.
            }
        }
    }
}

Why Write the Temp File in the Same Directory?

Atomic rename behavior is strongest when source and target are on the same file system.

Creating the temp file inside:

target parent directory

increases the chance that the move can be atomic.


Cleanup Failure

If temporary-file cleanup fails:

Files.deleteIfExists(
        temp
);

what should happen?

Usually the primary write failure remains more important.

The cleanup failure may be logged.

Avoid replacing the primary exception with an unrelated cleanup exception.


Do Not Silently Ignore Cleanup in Production

The previous example used:

catch (
        IOException ignored
) {
}

only to keep the example compact.

In real application code, log useful context:

Temporary file could not be deleted

without hiding the primary operation result.


Write Failure Categories

File writing may fail because:

Parent directory missing
Permission denied
Disk full
Read-only file system
File already exists
Target is a directory
Storage unavailable

Do not translate every write failure to:

File already exists

Catch specific exceptions only when the distinction matters.


AccessDeniedException

Example:

catch (
        AccessDeniedException exception
) {
    throw new CourseContentStorageException(
            "Course content cannot be written because storage access was denied.",
            exception
    );
}

This can provide useful internal classification.

External client still may receive a generic storage failure.


Storage Exception

public final class CourseContentStorageException
        extends RuntimeException {

    public CourseContentStorageException(
            String message,
            Throwable cause
    ) {
        super(
                message,
                cause
        );
    }
}

Course Content Writer

package io.liveklass.content;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public final class CourseContentWriter {

    private final Path baseDirectory;

    public CourseContentWriter(
            Path baseDirectory
    ) {
        if (baseDirectory == null) {
            throw new IllegalArgumentException(
                    "Base directory is required."
            );
        }

        this.baseDirectory =
                baseDirectory
                        .toAbsolutePath()
                        .normalize();
    }

    public void write(
            String courseCode,
            String fileName,
            String content
    ) {
        Path target =
                resolveTarget(
                        courseCode,
                        fileName
                );

        try {
            Path parent =
                    target.getParent();

            if (parent != null) {
                Files.createDirectories(
                        parent
                );
            }

            Files.writeString(
                    target,
                    content,
                    StandardCharsets.UTF_8,
                    StandardOpenOption.CREATE,
                    StandardOpenOption.TRUNCATE_EXISTING,
                    StandardOpenOption.WRITE
            );
        } catch (
            IOException exception
        ) {
            throw new CourseContentStorageException(
                    "Could not write course content.",
                    exception
            );
        }
    }

    private Path resolveTarget(
            String courseCode,
            String fileName
    ) {
        if (
                courseCode == null
                || courseCode.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Course code is required."
            );
        }

        if (
                fileName == null
                || fileName.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "File name is required."
            );
        }

        Path target =
                baseDirectory
                        .resolve(
                                courseCode
                                        .strip()
                                        .toLowerCase()
                        )
                        .resolve(
                                fileName
                        )
                        .normalize();

        if (
                !target.startsWith(
                        baseDirectory
                )
        ) {
            throw new IllegalArgumentException(
                    "Content path is outside the allowed directory."
            );
        }

        return target;
    }
}

Design Review

Why Create Parent Directories?

A valid content path may reference nested storage that does not exist yet.

Why Use Explicit Open Options?

This makes the intended behavior clear:

Create if missing
Overwrite if present
Write mode

Why Validate Final Path?

To prevent path traversal outside the allowed base directory.

Why Translate IOException?

Higher layers should depend on application storage semantics, not raw Java file-system details.


Create vs Update Contracts

Do not automatically use one method for every operation.

Clear APIs may separate:

create(...)
update(...)
append(...)

Why?

Because semantics differ.


Create Method

A strict create method can use:

StandardOpenOption.CREATE_NEW

Example:

public void create(
        Path path,
        String content
) throws IOException {
    Files.writeString(
            path,
            content,
            StandardCharsets.UTF_8,
            StandardOpenOption.CREATE_NEW,
            StandardOpenOption.WRITE
    );
}

If file exists, creation fails.


Update Method

A strict update method might first require an existing regular file:

if (
        !Files.isRegularFile(
                path
        )
) {
    throw new IllegalStateException(
            "Content file does not exist."
    );
}

Then overwrite.

But remember:

Check does not guarantee later write.

The write itself still needs exception handling.


Upsert Method

Upsert means:

Create if missing
Update if present

Typical options:

CREATE
TRUNCATE_EXISTING
WRITE

This is different from strict create or strict update.

Name your method according to its actual contract.


Append Method

Append means:

Preserve existing content
Add new content at end

Typical:

CREATE
APPEND

Avoid Ambiguous save()

A method named:

save()

may mean:

Create?
Update?
Upsert?
Append?

Sometimes save is accepted by the application architecture.

But where behavior matters, more precise names improve clarity.


Writing Binary Data Is Different

This lesson focuses on text.

Text:

Files.writeString(...)

Binary:

Files.write(
        path,
        byte[]
)

or:

OutputStream

Examples of binary files:

Images
PDFs
ZIP archives
Video
Audio

Do not decode arbitrary binary files as UTF-8 text.


Large Text Output

writeString() accepts one whole String.

If you are generating huge output incrementally, building the entire content first may consume too much memory.

Example bad approach:

String gigantic =
        buildHugeExport();

Files.writeString(
        path,
        gigantic
);

For large generated output, streaming writers are better.

We will cover streams and buffers in the next lesson.


Writing Lines from a List

List<String> topics =
        List.of(
                "Java",
                "Spring Boot",
                "PostgreSQL",
                "Kafka"
        );

Files.write(
        path,
        topics,
        StandardCharsets.UTF_8
);

This is simple when data already exists as lines.


Files.write() Still Is Not Streaming from Your Source

If you already built:

List<String>

all data is already in memory.

For very large generated datasets, a BufferedWriter may be more appropriate.


Do Not Mix Validation and Storage Responsibilities Too Much

Storage component should know:

How to write a file
Where to store it
How to translate I/O failures

Domain service should know:

Whether content may be edited
Who can edit it
Whether course status allows updates

Example:

course.ensureEditable();

contentWriter.write(
        courseCode,
        fileName,
        content
);

Avoid making file adapter decide course business rules.


Common Mistakes

Overwriting Existing Content Accidentally

Default write behavior can replace content.


Forgetting Parent Directories

Nested target paths may fail if parents do not exist.


Using APPEND Without a Line Separator

Content may join onto the previous line.


Using CREATE_NEW When Upsert Is Intended

Existing files will fail unexpectedly.


Using CREATE When Duplicate Creation Must Fail

May overwrite or reopen an existing file depending on options.


Validating After Writing

Invalid data may already be persisted.


Treating Pre-Checks as Guarantees

File-system state can change after the check.


Reading Then Rewriting for Simple Append

Creates unnecessary work and lost-update risk.


Ignoring Concurrent Writers

File operations alone do not solve application concurrency.


Losing the Original IOException

Makes diagnosis harder.


Writing Important Files Directly Without Considering Partial Failure

Temporary-file replacement may be safer for critical updates.


Assuming ATOMIC_MOVE Always Works

File system support varies.


Writing Huge Generated Content as One String

Can consume excessive memory.


Practice Exercises

Exercise 1: Write Markdown

Create:

void writeMarkdown(
        Path path,
        String content
)

Requirements:

  • UTF-8
  • Create parent directories
  • Create or overwrite file
  • Preserve IOException as cause

Exercise 2: Create Only Once

Create:

void createContent(
        Path path,
        String content
)

Use:

CREATE_NEW

Return a meaningful custom failure if file already exists.


Exercise 3: Append Activity

Append:

COURSE_PUBLISHED

to:

events.log

Requirements:

  • Create file if missing
  • Preserve old content
  • Add a line separator

Exercise 4: Write Lines

Given:

List<String> topics

write them to:

topics.txt

using:

Files.write()

Exercise 5: Parent Directory

Given:

content/java/module-1/lesson.md

ensure all missing parent directories exist before writing.


Exercise 6: Safer Replace

Implement:

void replaceSafely(
        Path target,
        String content
)

using:

Temporary file
Files.writeString()
Files.move()
REPLACE_EXISTING

Try ATOMIC_MOVE first.


Exercise 7: Choose the Open Option

Choose the right strategy:

  1. Fail if a file already exists
  2. Add a new log line
  3. Replace existing Markdown content
  4. Create or replace course content
  5. Preserve existing file and add more content

Use:

CREATE
CREATE_NEW
APPEND
TRUNCATE_EXISTING
WRITE

Predict the Result

Question 1

Existing file:

Java

Then:

Files.writeString(
        path,
        "Spring"
);

What is the likely final content?

Answer

Spring

The old content is replaced.


Question 2

Existing file:

Java

Then:

Files.writeString(
        path,
        "Spring",
        StandardCharsets.UTF_8,
        StandardOpenOption.APPEND
);

What is the content?

Answer

JavaSpring

unless the original or appended content contains a line separator.


Question 3

A file already exists and you use:

CREATE_NEW

What happens?

Answer

Java throws:

FileAlreadyExistsException

Question 4

Does:

Files.createDirectories(
        directory
)

fail simply because the directory already exists?

Answer

Normally no.

It ensures the directory path exists.


Question 5

Does:

ATOMIC_MOVE

work on every file system?

Answer

No.

It may throw:

AtomicMoveNotSupportedException

Knowledge Check

Question 1

What does Files.writeString() do?

Question 2

What usually happens when the target file already exists?

Question 3

What does CREATE_NEW mean?

Question 4

What does APPEND mean?

Question 5

What does TRUNCATE_EXISTING do?

Question 6

Why explicitly use UTF-8?

Question 7

Why create parent directories first?

Question 8

What is the difference between createDirectory() and createDirectories()?

Question 9

Why should validation happen before writing?

Question 10

Why is read-modify-write vulnerable to lost updates?

Question 11

What is a temporary-file replacement strategy?

Question 12

What does REPLACE_EXISTING do during move?

Question 13

Why is ATOMIC_MOVE useful?

Question 14

Why can it not always be relied upon?

Question 15

Why might BufferedWriter be preferable for very large generated output?


Knowledge Check Answers

Answer 1

It writes a String to a text file.

Answer 2

Existing content is normally replaced unless append or another explicit option is used.

Answer 3

Create the file only if it does not already exist.

Answer 4

Add new data to the end of existing content.

Answer 5

It clears existing content before writing new content.

Answer 6

To make character encoding predictable and consistent across systems.

Answer 7

Writing a file does not automatically guarantee all missing parent directories will be created.

Answer 8

createDirectory() creates one directory; createDirectories() creates missing parent levels too.

Answer 9

To avoid persisting invalid data before discovering the validation failure.

Answer 10

Multiple writers can read the same old state and later overwrite one another's changes.

Answer 11

Write new content to a temporary file, then move it over the target after the write succeeds.

Answer 12

It allows the destination file to be replaced if it already exists.

Answer 13

It can make replacement appear as one indivisible move rather than exposing an intermediate target state.

Answer 14

Atomic moves depend on file-system and storage capabilities.

Answer 15

It can write content incrementally instead of requiring one huge String in memory.


Lesson Summary

এই lesson-এ আমরা শিখেছি:

  • Files.writeString() text file লিখতে ব্যবহার করা যায়
  • UTF-8 explicitly define করা ভালো practice
  • Default write behavior existing content replace করতে পারে
  • CREATE_NEW duplicate creation prevent করে
  • APPEND existing content-এর শেষে data যোগ করে
  • Append automatically newline add করে না
  • TRUNCATE_EXISTING old content clear করে
  • Files.write() line collections লিখতে useful
  • Nested files লেখার আগে parent directories create করতে হতে পারে
  • createDirectories() missing parent levels তৈরি করে
  • Validation side effect-এর আগে complete করা উচিত
  • File-system pre-check later write success guarantee করে না
  • Read-modify-write concurrent lost updates তৈরি করতে পারে
  • File system application-level concurrency automatically solve করে না
  • Critical updates temporary file + move strategy দিয়ে safer করা যায়
  • REPLACE_EXISTING target replace করতে পারে
  • ATOMIC_MOVE stronger replacement semantics দিতে পারে
  • Atomic move support platform-dependent
  • Original IOException cause preserve করা উচিত
  • Storage adapter file-system details higher layers থেকে hide করতে পারে
  • Create, update, append, and upsert different contracts
  • Very large generated text incremental writer দিয়ে handle করা ভালো

Next Lesson

পরবর্তী lesson:

Working with Streams and Buffers

আমরা শিখব:

  • Byte streams vs character streams
  • InputStream
  • OutputStream
  • Reader
  • Writer
  • BufferedInputStream
  • BufferedOutputStream
  • BufferedReader
  • BufferedWriter
  • Buffering কেন useful
  • Binary vs text data
  • Copying large files
  • Streaming large output