2
2

More than 3 years have passed since last update.

【Java】ストリーム処理

Posted at

ストリームとは

  • データの流れ
  • 入出力先にかかわらずデータの連なりとして同じように操作することができる
    • 入力(受け取り)/ 出力(書き出し)ストリーム
    • 文字ストリーム / バイナリストリーム
基本クラス 入力ストリーム 出力ストリーム
文字ストリーム Reader Writer
バイナリストリーム InputStream OutputStream
  • 基本クラスをもとに操作対象に応じ操作クラスを提供している

ファイル書き込み

  • ファイルオープン

    • BufferedWriterクラスのnewBufferedWriterメソッドを使う(Bufferは文字列データを一時的に保存するメモリ領域)
    • 引数にStandardOpenOption.APPEND指定で追記モード
  • ファイル出力

    • writeメソッド
    • データをBufferに保存して溜まったらまとめてファイル出力
    • newLineメソッドで改行区切り(Unixは\n,Windowsは\r\n)
    • Files.writeメソッドで文字列リストをまとめてファイルに書き込みできる
      • Files.write(Paths.get("./data.log"),list,StandardCharsets.UTF_8);
  • ファイルクローズ

    • try-with-resources構文を使う
    • tryで生成されたオブジェクトはブロックを抜けたら自動で破棄される!(途中のエラーでcloseメソッドが呼び出されない場合でも大丈夫)
//実行時間を./data.logに記録
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
//import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;

public class Main {
  public static void main(String[] args) {
    try (var writer = Files.newBufferedWriter(Paths.get("./data.log"))) {
    //ファイル追記
    //try (var writer = Files.newBufferedWriter(Paths.get("./data.log"), StandardOpenOption.APPEND)) {
    writer.write(LocalDateTime.now().toString());
    // 改行文字を統一する場合
    //write(LocalDateTime.now().toString()+"\r\n");
      writer.newLine();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

ファイル入力

  • BufferedReaderクラスのnewBufferedReaderメソッドを使う
  • readLineメソッドでファイルポインタで1行ずつ読みとり現在行の文字列を返す
    • ファイルポインター:現在位置の目印。ファイルオープン時にファイル先頭にある。次の行がない場合にnullを返す
  • Files.readAllLinesメソッドでは、ファイル内容を行単位でまとめてリスト取得できる。ファイルサイズが大きい場合メモリの消費が激しい
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Main {
  public static void main(String[] args) {
    try (var reader = Files.newBufferedReader(Paths.get("./sample.txt"))) {
      var line = "";
      while ((line = reader.readLine()) != null) {
        //ファイルの中身を
        System.out.println(line);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

バイナリファイルの読み書き

  • BufferedInputStream / BufferedOutputStream
    • バッファー機能を備えたバイトストリーム
    • ファイルへの入出力はFileInputStream / FileOutputStream
    • ストリームへの読み書きは read / writeメソッド
      • readの戻り値はバイトデータ(0~255)
      • ストリーム終端は-1を返す
//input.pngをBufferedInputStreamで読み込み
//結果をBufferedOutputStreamでoutput.pngに出力
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
  public static void main(String[] args) {
    try (
        var in = new BufferedInputStream(
          new FileInputStream("./input.png"));
        var out = new BufferedOutputStream(
          new FileOutputStream("./output.png"))) {
      var data = -1;
      while ((data = in.read()) != -1) {
        out.write((byte) data);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

オブジェクトのシリアライズ

  • シリアライズ:のような構造化データをバイト配列に変換
  • オブジェクトをバイト配列にシリアライズすることでオブジェクトをDBに保存、ネットワーク経由の受け渡し可能
  • シリアライズ可能クラスの条件

    • Serializableインターフェース実装
      public class Article implements Serializable {
      • 宣言のみでメソッドを持たない=マーカーインターフェース
    • インスタンスフィールドは基本型、シリアライズ可能な型
    • シリアライズバーション宣言
      • serialVersionUIDでクラスのバージョン指定
      • シリアライズ/デシリアライズ間で異なるバージョンのクラスを使用するとInvalidClassException
    • 基底クラスがシリアライズできないとき、引数のないコンストラクタを持つ
      • 基底クラスがSerializableインターフェース実装せず、派生クラスのみシリアライズ可能の時、派生クラスのデシリアライズに基底クラスのコンストラクタを呼ぶ
  • ObjectOutputStreamクラスでオブジェクトのシリアライズを行う

    • 引数にFileOutputStream(file)でファイル出力
    • writeObjectメソッドにオブジェクトを渡す(article.ser作成)
  • ObjectInputStreamクラスでデシリアライズ

    • 引数に読み込むfileを渡しreadObjectメソッドで読み込む
    • 戻り値はオブジェクト
//article.serにArticleクラス(シリアライズ可能クラス)を保存
//ファイルからバイト配列を読みデシリアライズした公開鍵暗号オブジェクトの内容を出力
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Main {
  public static void main(String[] args) {
    final var file = "./article.ser";
    try (var out = new ObjectOutputStream(new FileOutputStream(file))) {
      out.writeObject(new Article("Java11の変更点と新しいAPI",
        "https://codezine.jp/article/corner/751", false));
    } catch (IOException e) {
      e.printStackTrace();
    }

    try (var in = new ObjectInputStream(new FileInputStream(file))) {
      var a = (Article)in.readObject();
      System.out.println(a);
    } catch (ClassNotFoundException | IOException e) {
      e.printStackTrace();
    }
  }
}
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2