ファイル操作と入出力、クラスの調べ方

<概要>主にファイル操作を学びます。クラスライブラリのマニュアルはもう殆ど読めますよね?

例題18-1 指定したファイルの内容を標準出力に表示する。

○プログラム

import java.io.*;

public class ShowFile1{
  public static void main(String[] args){
    if(args.length!=1){
      System.out.println("使用法:java ShowFile1 ファイル");
      System.out.println("例:java ShowFile1 ShowFile1.java");
      System.exit(0);
    }
    String filename=args[0];
    try{
      BufferedReader reader=new BufferedReader(new FileReader(filename));
      String line;
      while((line=reader.readLine())!=null){
        System.out.println(line);
      }
      reader.close();
    }catch(FileNotFoundException e){
      System.out.println(filename+"が見つかりません。");
    }catch(IOException e){
      System.out.println(e);
    }
  }
}


○実行例

D:\atsushi\Java\List18-1>java ShowFile1 test.txt
test.txtが見つかりません。

D:\atsushi\Java\List18-1>java ShowFile1 ShowFile1.java
import java.io.*;

public class ShowFile1{
  public static void main(String[] args){
    if(args.length!=1){
      System.out.println("使用法:java ShowFile1 ファイル");
      System.out.println("例:java ShowFile1 ShowFile1.java");
      System.exit(0);
    }

……省略……

D:\atsushi\Java\List18-1>

○解説

以前にもやったから分かりますね。

java.lang.Object
 |
 +--java.io.Reader
  |
  +--java.io.InputStreamReader
   |
   +--java.io.FileReader

public class FileReader extends InputStreamReader
 public FileReader(String fileName) throws FileNotFoundException

FileReader は、文字ファイルからの読み込みのための簡易クラスです。
FileReader (のインスタンス)をそのまま使ってもいいのですが、
通常はこれを元に BufferedReader というクラス(のインスタンス)を作成します。

java.lang.Object
 |
 +--java.io.Reader
  |
  +--java.io.BufferedReader

public class BufferedReader extends Reader
 public String readLine() throws IOException
 public void close() throws IOException


BufferedReader は、バッファリングを行うクラスです。
バッファの大きさを変えるには BufferedReader(Reader in,int sz) コンストラクタを使います。
バッファは大きい方が効率はいいのですが、メモリを多く必要とします。

public BufferedReader(Reader in,int sz)  //BufferedReader クラス
 指定されたサイズのバッファでバッファリングされた、文字型入力ストリームを作成します。
パラメータ: in - Reader , sz - 入力バッファのサイズ
例外: IllegalArgumentException - sz が 0 以下の場合

この BufferedReader(Reader in,int sz) は、例外 IllegalArgumentException を投げるのに、
throws 節が書かれていないのは何故でしょうか?
それは、IllegalArgumentException が実行時例外( RuntimeException )のサブクラスだからです。
実行時例外は、たくさんあり、またいろんなところで起きうるので、
いちいちコンパイラもチェックしないのでしたね。
他にもチェックされない例外に、Error (と、そのサブクラス)がありました。

new FileReader(filename) を評価した時点で、ファイルはオープンされ、
ファイルを読むための準備が整ったことになります。

ファイルの読み込みが終了したら、close メソッドを呼んで「ファイルをクローズする」必要があります。
 → reader.close();
これで、読み込みのために確保されていた資源
(メモリやファイルハンドル、ファイルディスクリプタなど)が解放されます。

クラスライブラリのマニュアルを読む

ここまで読み進んでこられた皆さんなら、もうマニュアルの殆どを読めるはずです。

java.lang.Object
 |
 +--java.io.Reader
  |
  +--java.io.InputStreamReader
   |
   +--java.io.FileReader


FileReader のクラス階層です。
個々のクラスは、属しているパッケージが分かるように、java.io.FileReader のように書かれています。
これは、java.io パッケージの中に FileReader が含まれていることを示しています。

例題18-2 標準入力の内容をファイルに書き込む。

○プログラム

import java.io.*;

public class WriteFile1{
  public static void main(String[] args){
    if(args.length!=1){
      System.out.println("使用法:java WriteFile1 作成ファイル");
      System.out.println("例:java WriteFile1 output.txt < input.txt");
      System.exit(0);
    }
    String filename=args[0];
    try{
      BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
      PrintWriter writer=new PrintWriter(new BufferedWriter(new FileWriter(filename)));
      String line;
      while((line=reader.readLine())!=null){
        writer.println(line);
      }
      reader.close();
      writer.close();
    }catch(IOException e){
      System.out.println(e);
    }
  }
}


○実行例

D:\atsushi\Java\List18-2>java WriteFile1 output.txt<WriteFile1.java

D:\atsushi\Java\List18-2>

○ output.java

import java.io.*;

public class WriteFile1{
  public static void main(String[] args){
    if(args.length!=1){
      System.out.println("使用法:java WriteFile1 作成ファイル");
      System.out.println("例:java WriteFile1 output.txt < input.txt");
      System.exit(0);
    }

……省略……

○解説

public class InputStreamReader extends Reader
 public InputStreamReader(InputStream in)

public final class System extends Object
 public static final InputStream in


new FileWriter(filename) を評価した時点で、filename で指定された名前のファイルが
大きさ 0 として(つまり空っぽのファイルとして)作成されます。
もしも、同じ名前を持つファイルが既にあった場合は、上書きします。
上書きされたファイルの内容は一瞬にして無くなってしまいますので、注意して下さい。

java.lang.Object
 |
 +--java.io.Writer
  |
  +--java.io.OutputStreamWriter
   |
   +--java.io.FileWriter

public class FileWriter extends OutputStreamWriter

 文字ファイルを書き込むための簡易クラスです。

public FileWriter(String fileName) throws IOException  //FileWriter クラス
 ファイル名を指定して FileWriter オブジェクトを構築します。
パラメータ: fileName - システムに依存するファイル名の文字列
例外: IOException - 指定したファイルが見つからない場合、または他の入出力エラーが発生した場合

FileWriter は、ファイルへの書き込みを行うクラスです。
FileWriter (のインスタンス)をそのまま使ってもいいのですが、
通常はこれを元に BufferedWriter というクラス(のインスタンス)を作成します。
BufferedReader は、書き込みの際にバッファリングを行うクラスです。

java.lang.Object
 |
 +--java.io.Writer
  |
  +--java.io.BufferedWriter

public class BufferedWriter extends Writer

 文字をバッファリングすることによって、文字、配列、
 または文字列を効率良く文字型出力ストリームに書き込みます。

public BufferedWriter(Writer out)  //BufferedWriter クラス
 デフォルトサイズの出力バッファでバッファリングされた、文字型出力ストリームを作成します。

BufferedReader クラスのインスタンスを作成したら、
更にこれを元に PrintWriter というクラス(のインスタンス)を作成します。
PrintWriter は、便利なメソッドを数多く持つクラスです。

public class PrintWriter extends Writer
 フォーマットされたオブジェクトの表現をテキスト出力ストリームに出力します。

public PrintWriter(Writer out)  //PrintWriter クラス
 自動行フラッシュは行わずに、新しい PrintWriter を作成します。
パラメータ: out - 文字出力ストリーム

public void println(String x)  //PrintWriter クラス
 String を出力して、行を終了します。
 このメソッドは、print(String) を呼び出してから println() を呼び出すのと同じように動作します。
パラメータ: x - 出力される String 値

public void close()  //PrintWriter クラス
 ストリームを閉じます。
定義: クラス Writer 内の close

BufferWriter では出力がバッファリングされますので、ファイルクローズを忘れると、
書き込んだつもりの文字列が欠けてしまったりすることがあります。

println メソッドと言えば、これまでたくさん使ってきた System.out.println を思い出します。
System.out は、標準出力を元にして作った PrintStream です
(PrintStream はバイト単位の出力を行い、PrintWriter は文字単位の出力を行います)。
ですから、System.out.println の実行結果は、標準出力に出力されるのです。
また writer は、ファイルを元にして作った PrintWriter です。
ですから、writer.println の実行結果はファイルに出力されるのです。
と言っても、PrintWriter と PrintStream にクラス階層上の関係は無いんですけどね。

public final class System extends Object

public static final PrintStream out
  //System クラス
 「標準」出力ストリームです。
 このストリームはすでに開いていて、出力データの受け取りが可能です。
 通常、このストリームはディスプレイ出力、
 またはホスト環境やユーザによって指定されるその他の出力先と一致しています。

public class PrintStream extends FilterOutputStream

public void println(String x)
  //PrintStream クラス
 String を出力して、行を終了します。
 このメソッドは、print(String) を呼び出してから println() を呼び出すのと同じように動作します。
パラメータ: x - 出力される String 値

例題18-3 ファイルを削除する。

○プログラム

import java.io.*;

public class DeleteFile1{
  public static void main(String[] args){
    if(args.length!=1){
      System.out.println("使用法:java DeleteFile1 削除ファイル");
      System.out.println("例:java DeleteFile1 trash.txt");
      System.exit(0);
    }
    String filename=args[0];
    File file=new File(filename);
    if(file.delete()){
      System.out.println(filename+"を削除しました。");
    }else{
      System.out.println(filename+"は削除できませんでした。");
    }
  }
}


○実行例

D:\atsushi\Java\List18-3>echo test>trash.txt

D:\atsushi\Java\List18-3>java DeleteFile1 trash.txt
trash.txtを削除しました。

D:\atsushi\Java\List18-3>java DeleteFile1 trash.txt
trash.txtは削除できませんでした。

D:\atsushi\Java\List18-3>

○ echo

DOSコマンド echo 本来の処理内容は気にしないとして、
echo test>trash.txt の結果として test という文字列が書き込まれたファイル trash.txt が作成されます。

○ trash.txt

test

○解説

File クラスは、ファイルやディレクトリを操作するためのものです。

public class File extends Object implements Serializable, Comparable
 ファイルおよびディレクトリのパス名の抽象表現です。

public File(String pathname)  //File クラス
 指定されたパス名文字列を抽象パス名に変換して、新しい File のインスタンスを生成します。
 指定された文字列が空の文字列の場合、結果は空の抽象パス名になります。
パラメータ: pathname - パス名文字列
例外: NullPointerException - pathname 引数が null の場合

public boolean delete()  //File クラス
 この抽象パス名が示すファイルまたはディレクトリを削除します。
 このパス名がディレクトリを示す場合、そのディレクトリが削除されるためには空である必要があります。
戻り値: ファイルまたはディレクトリが正常に削除された場合は true、そうでない場合は false
例外: SecurityException - セキュリティマネージャが存在する場合に、
 セキュリティマネージャの SecurityManager.checkDelete(java.lang.String) メソッドが
 ファイルへの削除アクセスを許可しないとき

例題18-4 ファイルの名前変更。

○プログラム

import java.io.*;

public class RenameFile1{
  public static void main(String[] args){
    if(args.length!=2){
      System.out.println("使用法:java RenameFile1 現在のファイル名 新しいファイル名");
      System.out.println("例:java RenameFile1 oud.txt new.txt");
      System.exit(0);
    }
    String oldfilename=args[0];
    String newfilename=args[1];
    File oldfile=new File(oldfilename);
    File newfile=new File(newfilename);
    if(oldfile.renameTo(newfile)){
      System.out.println(oldfilename+"を"+newfilename+"に変更しました。");
    }else{
      System.out.println(oldfilename+"を"+newfilename+"に変更できませんした。");
    }
  }
}


○実行例

D:\atsushi\Java\List18-4>echo test>oldfile.txt

D:\atsushi\Java\List18-4>java RenameFile1 oldfile.txt newfile.txt
oldfile.txtをnewfile.txtに変更しました。

D:\atsushi\Java\List18-4>echo test>oldfile.txt

D:\atsushi\Java\List18-4>java RenameFile1 oldfile.txt newfile.txt
oldfile.txtをnewfile.txtに変更できませんした。

D:\atsushi\Java\List18-4>

○解説

public boolean renameTo(File dest)  //File クラス
 この抽象パス名が示すファイルの名前を変更します。
パラメータ: dest - 指定されたファイルの新しい抽象パス名
戻り値: 名前の変更が成功した場合は true、そうでない場合は false
例外: SecurityException - セキュリティマネージャが存在する場合に、
 セキュリティマネージャの SecurityManager.checkWrite(java.lang.String) メソッドが
 古いパス名と新しいパス名のどちらかへの書き込みアクセスを許可しないとき
 NullPointerException - パラメータ dest が null の場合

ファイルの名前が変更できない原因は、
・変更元のファイルが見つからなかった
・変更先のファイルが既にあった
の両方が有り得ます。
実行例の場合、二回目の RenameFile1 実行の時には
既に newfile.txt が存在するので、名前変更が出来なくなっています。

例題18-5 ファイルの存在確認。

○プログラム

import java.io.*;

public class RenameFile2{
  public static void main(String[] args){
    if(args.length!=2){
      System.out.println("使用法:java RenameFile2 現在のファイル名 新しいファイル名");
      System.out.println("例:java RenameFile2 oud.txt new.txt");
      System.exit(0);
    }
    String oldfilename=args[0];
    String newfilename=args[1];
    File oldfile=new File(oldfilename);
    File newfile=new File(newfilename);
    if(!oldfile.exists()){
      System.out.println(oldfilename+"が見つかりません。");
    }else if(newfile.exists()){
      System.out.println(newfilename+"はすでに存在します。");
    }else if(oldfile.renameTo(newfile)){
      System.out.println(oldfilename+"を"+newfilename+"に変更しました。");
    }else{
      System.out.println(oldfilename+"を"+newfilename+"に変更できませんした。");
    }
  }
}


○実行例

D:\atsushi\Java\List18-5>java RenameFile2 oldfile.txt newfile.txt
oldfile.txtが見つかりません。

D:\atsushi\Java\List18-5>echo test>oldfile.txt

D:\atsushi\Java\List18-5>echo test>newfile.txt

D:\atsushi\Java\List18-5>java RenameFile2 oldfile.txt newfile.txt
newfile.txtはすでに存在します。

D:\atsushi\Java\List18-5>del newfile.txt

D:\atsushi\Java\List18-5>java RenameFile2 oldfile.txt newfile.txt
oldfile.txtをnewfile.txtに変更しました。

D:\atsushi\Java\List18-5>

○解説

public boolean exists()  //File クラス
 この抽象パス名が示すファイルが存在するかどうかを判定します。
戻り値: この抽象パス名が示すファイルが存在する場合は true、そうでない場合は false
例外: SecurityException - セキュリティマネージャが存在する場合に、
 セキュリティマネージャの SecurityManager.checkRead(java.lang.String) メソッドが
 ファイルへの読み込みアクセスを許可しないとき


戻る / ホーム