🦁

Buffered Streamsでテキストデータの読み込み、書き込みを行う方法

2024/03/28に公開

Buffered Streamsとは?


Buffered Streamsとは、データを一定量バッファに溜め込んでから処理するため、I/Oの回数を減らし、効率的に読み書きすることができる。上記に記載の通り、bytesや文字端谷ではなく、文章ごとで読み込みができる。

ハンズオン

概要

今回はハンズオンで、以下の流れを確認する。

  • 数千個の英単語が書かれたtxtファイルを読み込む
  • 100個ずつ分けて、分割ファイルを作成する
  • 作成したファイル内では、アルファベット順で並べられる。

詳細

フォルダ構造は以下の通り

  • MakeShards.java
  • unsorted.txt

二つ目のファイルがtxtファイルで、以下のような中身である。
pursuant
kinase
agencies
mineral
jar
conducted
past
tom
wx
tail
etc..

javaファイルを実行すると、shardsというフォルダが作成されて、shard00.txt、shard01.tx、etc.. といった形でtxtファイルが作成される。そして、その中身は以下の通りに、アルファベット順で記載される。
addressed
agencies
alexander
api
arrangement
attempting
author
beads
beats
bookmarks
etc..

プログラム作成

準備

まず、必要なライブラリをimportする。

import java.io.BufferedReader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

次に、各txtファイルに記載される単語を100個に絞りたいので、以下の通り、SHARD_SIZEを定義する。

public final class MakeShards {
  private static final int SHARD_SIZE = 100;

また、userから「どのテキストファイルを読み込むか」ということと「どのフォルダにアウトプットファイルを出力するか」ということをコマンドラインから入力して欲しいので、以下の通り記述する。こうすることで、一つ目のコマンド入力をinputファイル、二つ目をアウトプットフォルダと定義できる。

public static void main(String[] args) throws Exception {
    if (args.length != 2) {
      System.out.println("Usage: MakeShards [input file] [output folder]");
      return;
    }

    Path input = Path.of(args[0]);
    Path outputFolder = Files.createDirectory(Path.of(args[1]));

各ファイルに単語を追加

まずは、unsorted.txtファイルの読み込みをする。単語はnullになるまで、行ごとに読んこんでいく。

try (BufferedReader reader = Files.newBufferedReader(input)) {
      int shardNum = 0;
      String word = reader.readLine();
      while (word != null) {

一番最初にprivate static final int SHARD_SIZE = 100;と記述しているので、100個を想定して、各配列を作成する。whileループでは、100個に達するかwordがなくなるまで、wordを読み込んで、リストに追加していく。

        List<String> shard = new ArrayList<>(SHARD_SIZE);
        while (shard.size() < SHARD_SIZE && word != null) {
          shard.add(word);
          word = reader.readLine();
        }

shard.sort(String::compareTo);でアルファベット順に並べ替える。

shard.sort(String::compareTo);

次にここで、出力ファイルのパスを作成している。Path outputFolder = Files.createDirectory(Path.of(args[1]))にある通り、ここはユーザに入力してもらった[output folder]が出力されるコマンド。そして、getOutputFileName(shardNum)は、最初に設定したint shardNum = 0;が追加されていくイメージ。

つまりここでは、shardXX.TXTの形式で、追加されていく形となる。二桁になるのは、shard%02d.txtと記載されているから。

Path output = Path.of(outputFolder.toString(), getOutputFileName(shardNum));

そして、outputファイルが出来上がったので、writerで書き込んでいく。

        try (Writer writer = Files.newBufferedWriter(output)) {

shardに単語が100個溜め込んでいるので、これを一つずつ書き込んでいく。最後にlineSeparatorを使って、改行していく。

          for (int i = 0; i < shard.size(); i++) {
            writer.write(shard.get(i));
            if (i < shard.size() - 1) {
              writer.write(System.lineSeparator());
            }
          }
        }

最後にシャード番号を受け取って、shardXX.txtのように、シャード番号に基づいたファイル名を出力する。

  private static String getOutputFileName(int shardNum) {
    return String.format("shard%02d.txt", shardNum);

Discussion