便利なコードパーツ集!

やまろうのプログラミングTips

Java

[Java] ファイルの閉じ忘れを防止する自前の仕組み

投稿日:2016年12月6日 更新日:

2003/03/22
僕はファイル入出力のプログラムをよく書きます。
ソースコードを自動生成させたり、Excelの表データを生成したりと。
プログラミングできるおかげで仕事を自動化出来てる面が結構あります。
そんなわけでファイルIOのライブラリを作ってみました。

package yamarou.util;

import java.io.*;
import java.util.*;

/** FileUtilを使うサンプル */
class Main {
  public static void main(String[] args) throws Exception {
    
    PrintWriter writer = new PrintWriter(System.out);    
    
  	//args[0]のファイルを全行読み込む
    String[] lines = FileUtil.getLines(args[0]);
  	
  	//全行書き出す
    FileUtil.writeLines(writer, lines);
    
  	//args[1]のディレクトリ配下のファイル一覧を取得
    FileList fileList = FileUtil.getFileList(args[1]);
  	
  	//ファイル一覧からファイルのみの一覧を取得
    File[] files = fileList.getFiles();
  	
  	//ファイルオブジェクト配列からファイルパス配列を取得
    String[] filePaths = FileUtil.getFilePaths(files);
  	
    //ファイルパス配列を全て書き出す
    FileUtil.writeLines(writer, filePaths);

    writer.close();
  }

}

/** FileIOのユーティリティ */
class FileUtil {

  /**
   * 引数のファイルを全て読み込んだ配列を返す
   */
  public static String[] getLines(String filePath)
    throws IOException {
    
    ArrayList list = getLineList(filePath);
    String[] lines = new String[list.size()];
    list.toArray(lines);
    
    return lines;
  }

  /**
   * 引数のファイルを全て読み込んだArrayListを返す
   */
  public static ArrayList getLineList(String filePath)
    throws IOException {

    BufferedReader in = new BufferedReader(new FileReader(filePath));
    ArrayList list = new ArrayList(5000);
    String line = null;
    while ((line = in.readLine()) != null) {
      list.add(line);
    }
   
    return list;
  }

  /**
   * outでlines配列を全て出力する
   */
  public static void writeLines(PrintWriter out, String[] lines) {
    for (int i = 0; i < lines.length; i++) {
      out.println(lines[i]);
    }
  }

  /**
   * 引数dirPathで指定されたディレクトリ配下のファイル一覧を返す
   */
  public static FileList getFileList(String dirPath)
    throws FileNotFoundException, IOException {
      
    ArrayList fileList = new ArrayList();
    ArrayList dirList = new ArrayList();
    
    searchDir(new File(dirPath), fileList, dirList);
    
    FileList result = new FileList();

    File[] files = new File[fileList.size()];
    fileList.toArray(files);
    result.setFiles(files);

    File[] dirs = new File[dirList.size()];
    dirList.toArray(dirs);
    result.setDirectorys(dirs);
    
    return result;
  }

  /**
   * dir配下のファイルをfileListに、ディレクトリをdirListに格納する
   */
  private static void searchDir(
    File dir, ArrayList fileList, ArrayList dirList)
    throws FileNotFoundException, IOException {

    File[] files = dir.listFiles();
    if (files == null) {
      return;
    }
    for (int i = 0; i < files.length; i++) {
      File file = files[i];
      if (file.isDirectory()) {
        dirList.add(file);
        searchDir(file, fileList, dirList);
      } else {
        fileList.add(file);
      }
    }
  }

  /**
   * filesから、ファイルパスを取得して配列で返す
   */
  public static String[] getFilePaths(File[] files) {
    String[] filePaths = new String[files.length];
    for (int i = 0; i < files.length; i++) {
      filePaths[i] = files[i].getPath();
    } 
    return filePaths;
  }
}

/** ファイル一覧を格納するオブジェクト **/
class FileList {
  private File[] files = null;
  private File[] directorys = null;

  public File[] getFiles() {
    return this.files;
  } 

  public File[] getDirectorys() {
    return this.directorys;
  } 

  public void setFiles(File[] value) {
    this.files = value;
  }

  public void setDirectorys(File[] value) {
    this.directorys = value;
  }
}

Mainクラスを見てみましょう!処理内容はコメントの通りです。

それでは実行しようぜー。
このメルマガをFileUtil.javaという名前で保存してください。
javac -d . FileUtil.java
java yamarou.util.Main FileUtil.java .

実行結果

FileUtil.javaの中身ずらずら(省略)
.\FileUtil.java
.\yamarou\util\FileList.class
.\yamarou\util\FileUtil.class
.\yamarou\util\Main.class

第1引数にFileUtil.java(全行出力するファイル名)
第2引数に.(ファイル一覧を取得するディレクトリ)(.はカレントディレクトリ)
を渡して実行したわけです。

FileUtil.javaの中身がコンソールに出力されたと思います。(なげー)
そしてカレントディレクトリのファイル一覧も出力。
短いプログラムですが、けっこういろいろな事してます。
便利でっしゃろ、FileUtil。良ければ使ってちよ!

ところで、ファイル処理でついついしてしまうミスがファイルのcloseを
し忘れるってやつ。今回も最初mainの中でwriter.close();を書き忘れて
あれ?なんも出力されないなーってなことなってしまいました。
試しにmainの中のwriter.close();を消して実行してみてください。
なーんも出力されません。PrintWriterはバッファリングしてるって
わけだね。

そこで、次回はcloseをし忘れない方法、というか自動的にcloseさせる
方法をご紹介したいと思います。finalizeメソッドを使うわけでは
ありません。フレームワーク的なものです。お楽しみに!!

んじゃぁねぇーーーーーー!!
やまろう

スポンサーリンク

-Java

Copyright© やまろうのプログラミングTips , 2022 AllRights Reserved Powered by AFFINGER4.