Java の入出力

  1. 入出力
    1. 基本型の出力
  2. ファイル I/O
    1. 入力ストリーム
    2. 出力ストリーム
    3. File クラス
  3. ストリームの積み重ね
    1. フィルタ付き入力ストリーム
    2. フィルタ付き出力ストリーム
    3. フィルタについて
    4. Reader と Writer
    5. IOException について
  4. java からプログラムを実行する

  1. 入出力
  2. java には UNIX で導入された標準入力(InputStream)、標準出力(PrintStream)、 標準エラー(PrintStream)の概念があります。
    System クラスには、以下の InputStream/PrintStream オブジェクトが含まれています。

       System.in   System.out   System.err
    

    in、out、err のストリームは、ほとんどのプログラムで使われるので、 コンパイル時に自動的にインポートされるパッケージ java.lang の System クラスにありますが、
    他の I/O 関連のものはパッケージ io にあるので、 明示的にインポートしなければなりません。

       import java.io.*;
    

    1. 基本型の出力
    2. 基本型の出力は、以下のように書きます。

         System.out.println("Value of int "+i);
      

      この引数には、ほとんどどんなものでもかけます。 PrintStream クラスの println メソッドは、 ふつう引数を String に変えて出力します。

  3. ファイル I/O
  4. java の I/O は、データの流れであるストリーム (stream) という概念に基づいています。
    たとえばファイルシステムのファイルは、 これをプログラムに流れこませたり、 プログラムから流れ出させたりするために、 ストリームオブジェクトを使います。 ストリームオブジェクトは、インスタンシエイトするとすぐに I/O で使えます。

    ストリームはデバイス独立です。

    またストリームは一方向にしか流れません。あるストリームから読むことも、 あるストリームに書くこともできますが、読み書きしたい場合は、 2つの別のストリームを使わなければなりません。

    java の I/O パッケージは java.ioにあり、 これらを使うためには、 このパッケージを明示的に import する必要があります。

    1. 入力ストリーム
    2. java.io パッケージには、以下の基本的な入力ストリームがあります。

      FileInputStream ファイルからバイト列を取得する
      StrinBufferInputStream StrinBuffer からバイト列を取得する
      ByteArrayInputStream byte の配列からバイト列を取得する
      PipedInputStream パイプからバイト列を取得する
      Reader 文字ストリームから文字列を取得する

      import java.io.*;
      
      public class read {
         public static void main(String argv[]) {
            try {
                FileInputStream f = new FileInputStream("read.java");
                int b;
            
                while((b=f.read()) != -1) {
                   System.out.print((char) b);
                }
                System.out.flush();
            } catch (IOException e) {  e.printStackTrace(); }
         }
      }
      

      上記のプログラムを作って実行してみましょう。

    3. 出力ストリーム
    4. java.io パッケージには、以下の基本的な出力ストリームがあります。

      FileOutputStream バイト列をファイルに書き出す
      ByteArrayOutputStream バイト列を一時的な内部領域に書き出す
      PipedOutputStream バイト列をパイプに書き出す
      Writer 文字列をストリームに書き出す

      出力用クラスは、すでに見た入力用クラスの反対で、read()メソッドの代わりに、 write() メソッドがあります。

      write は、すべてブロッキング I/O なので、I/O が完了するまで戻りません。

      import java.io.*;
      public class write {
         public static void main(String argv[]) {
            byte data[]={'w','r','i','t','e','.','j','a','v','a','\n'};
      
            try {
                FileOutputStream f = new FileOutputStream(argv[0]);
                f.write(data);
                f.close();
            } catch (IOException e) {  e.printStackTrace();}
         }
      }
      

      上記のプログラムを作って実行してみましょう。

    5. File クラス
    6. File クラスには、ファイルやディレクトリに関する情報を提供する、 たくさんのメソッドがあります。

      機能 コンストラクタとメソッド
      コンストラクタpublic File(String path)
      public File(String path,String name)
      public File(File dir,String name)
      ファイルの削除public boolean delete()
      ファイル名関連public String getName()
      public String getPath()
      public String getAbsolutePath()
      public String getCanonicalPath()
      public String getParent()
      public boolean renameTo(File dest)
      ファイル属性の取得public boolean exists()
      public boolean canWrite()
      public boolean canRead()
      public boolean isFile()
      public native boolean isAbsolute()
      public long lastModified()
      public long length()
      public boolean equals(Object obj)
      ディレクトリ関連public boolean mkdir()
      public String[] list()
      public String[] list(FilenameFilter filter)
      その他public static final char pathSeparatorChar
      public int hashCode()
      public String toString()

      java Core API の java.io の File を見てみましょう。

  5. ストリームの積み重ね
  6. ストリームは、互いにつなぎ合わせて別のストリームを作ることができます。 つながれるそれぞれのストリームでは、通り過ぎていくデータを加工することや、 洗練されたメソッドを提供できます。

    ストリームを他のストリーム上にプッシュし、 フィルタ処理させることもできます。

    1. フィルタ付き入力ストリーム
    2. java.io パッケージには、以下の基本的なフィルタ付き入力ストリームがあります。

      DataInputStream すべての基本形のバイナリ形式を読みこむ方法を与える
      BufferReader 文字型入力ストリームから読みこむ方法を与える
      BufferedInputStream 入力のバッファリングをサポートする
      LineNumberInputStream 読みこまれた行数を覚えておくメソッドを提供する
      PushbackInputStream 一度読みこんだ文字を入力ストリームに戻し、 次に読めるようにする機能を提供する

    3. フィルタ付き出力ストリーム
    4. java.io パッケージには、以下の基本的なフィルタ付き出力ストリームがあります。

      PrintStream すべての基本形を印刷可能な形式で出力する方法を与える
      このオブジェクトによる出力は synchronized である。
      PrintWriter すべての基本形を印刷可能な形式で出力する方法を与える
      このオブジェクトによる出力は synchronized である。
      DataOutputStream すべての基本形をバイナリ形式で出力する方法を与える
      BufferedOutputStream 出力のバッファリングをサポートする

      import java.io.*;
      public class write2 {
      
          public static void main(String argv[]) {
      
              try {
                  FileOutputStream f = new FileOutputStream( argv[0] );
                  PrintWriter      p = new PrintWriter( f );
      
                  float fl = 3.1415f;
                  p.println( "your float value is: " + fl );
                  p.close();
              } catch(IOException ioe) {}
          }
      }
      

      説明 このようにすると、float や boolean や int などの型も、Unicode ファイルに 書きこむことができます。PrintWriter を使わないで FileOutputStream で float の値を書くとバイナリで書き出されます。

      上記のプログラムを作って実行してみましょう。

    5. フィルタについて
    6. フィルタとは、標準入力から読みこみ、何らかの変換を行い、 結果を標準出力に書くようなソフトウェアのことです。

      次の例は、入力ファィル中のすべての+文字を改行に変換するフィルタです。

      import java.io.*;
      public class filt {
       
         public static void main(String args[]) {
            FileInputStream fis=null;
            try {
               fis = new FileInputStream("example.txt"); 
            } catch(FileNotFoundException fnf){
      	 System.out.println(fnf); 
            }
      
            Censor c = new Censor((OutputStream)System.out, (int)'+', (int)'\n');     
               int i=0;
               try {
                  while( (i=fis.read() )!= -1 )
                      c.write(i);
               } catch(IOException ioe){System.err.println(ioe); 
            }
         }
      }
             
      class Censor extends FilterOutputStream {
            
          int saved_remove=0;
          int saved_replace=0;
          OutputStream saved_out=out;
       
          Censor(OutputStream out, int remove, int replace) {
             super(out);
             saved_remove=remove;
             saved_replace=replace;
          }
       
          public void write(int b) throws IOException {
             if (b==saved_remove) b=saved_replace;
             saved_out.write(b);
          }
      }
      

    7. ReaderWriter
    8. JDK(Java Destribution Kit) 1.1 から、 InputStream/OutputStream に加えて、 Reader と Writer に関するクラスが追加されました。 InputStream/OutputStream が基本的に byte の入出力を行うのに対して、 Reader/Writerchar の入出力を行い、 java の内部コードである Unicode を扱います。

      InputStream/OutputStream が OS などの下位のレイヤに直接アクセスするのに対して、 Reader/Writer は InputStream/OutputStream を介してアクセスします。 このように分離した目的は、国際化のためです。

      InputStream/OutputStream が対象とする byte ストリームは、 OS に依存したエンコーディングが行われます。 他方 Reader/Writer が扱う char ストリームでのエンコーディングは、 Unicode であることを保証します。 このようにレイヤに分離することで、 上位のレイヤでは下位のレイヤのコーディングを意識する必要がなくなります。

      コード変換には ByteToCharConverter と CharToByteConverter が使われています。 システムプロパティや環境を参照して、適切なコンバータクラスを使って変換します。 もちろん EUC、シフト JIS、JIS などに対応したクラスもあります。

      注意 DataInputStream はバイナリデータを読みこむクラスのため、 このクラスにあるメソッド readLine() が deprecated(非難される)になりました。 このメソッドを含むプログラムをコンパイルすると以下のような警告が出ます。

       > javac test.java
      
      注意: test.java は推奨されない API を使用しています。
      詳細については、"javac -deprecation" コマンドを使用してください。
      警告 1個
      

      DataInputStream はバイナリデータを読みこむクラスなので、 行のようにテキストデータでしか定義できない概念を含むものは取り除かれました。 このかわりに BufferedReader の readLine() を使えます。

      そのためには、バイトストリームを文字ストリームに変換する InputStreamReader を仲介者として使います。

      static DataInputStream dis = new DataInputStream(System.in);
      
          ==>
      
      static BufferedReader dis = new BufferedReader(
                                          new InputStreamReader(System.in);
      

    9. IOException について
    10. 基本 I/O に関する例外についてまとめます。

      FileNotFoundException指定したファイルがなかった
      InterrupedIOExceptionI/O の途中で割り込みがあった
      UTFDataFormatException 間違った UTF-8 コードがある
      EOFException プログラマが指定した量の入力を読み終わる前に、 ファイルが終わってしまった場合に生じるもので、 通常の状態で end of file に遭遇しても、この例外は発生しない。

  7. java からプログラムを実行する
  8. java からプログラムを実行するには、次の3つのステップが必要です。

    1. 現在の実行環境を示すオブジェクトを取得する。
      クラス java.lang.Runtime にそのメソッドがあります。

    2. Runtime オブジェクトの exec メソッドを、 コマンド名を引数にして呼び出すことで、
      Processオブジェクトを作る。

    3. Process の出力をプログラムの入力ストリームにつないで読む。

    import java.io.*;
    
    public class Who {
    
        public static void main(String args[]) {
          int  ret;
          try {
              Runtime rt = Runtime.getRuntime();       // step 1
    
              Process prcs = rt.exec("/bin/who");      // step 2
    
              BufferedReader d = new BufferedReader(
                 new InputStreamReader(prcs.getInputStream())); // step 3.
              BufferedReader e = new BufferedReader(
                 new InputStreamReader(prcs.getErrorStream())); // step 3.
    
              String line;
              while  ((line = d.readLine()) != null)
                   System.out.println(line);
              while  ((line = e.readLine()) != null)
                   System.out.println(line);
              ret = prcs.exitValue();                 // get exit code
              prcs.destroy();                         // stop /bin/who
              System.exit(ret);
          } catch(IOException ioe) { System.out.println(ioe); }
       }
    }
    

    上記のプログラムを作って実行してみましょう。





java.io クラスのまとめ

java.io にあるクラスとインタフェースについてまとめました。

インタフェース 抽象クラス クラス と色分けしました。

java.io のストリームクラス
カテゴリ バイトストリーム 文字型ストリーム 分     類
基本系 InputStream Reader ストリーム入出力の抽象クラス
OutputStream Writer
DataInput
データ入出力インタフェース
DataOutput
ObjectInput
オブジェクト入出力インタフェース
ObjectOutput
FilterInputStream FilterReader フィルタ入出力クラス
FilterOutputStream FilterWriter
生成系 FileInputStream FileReader ファイル入出力クラス
FileOutputStream FileWriter
ByteArrayInputStream CharArrayReader 配列入出力クラス
ByteArrayOutputStream CharArrayWriter

InputStreamReader バイトストリームを文字型ストリームに変換するクラス

OutputStreamWriter
PipedInputStream PipedReader パイプ入出力クラス
PipedOutputStream PipedWriter
SequenceInputStream
シーケンス入力クラス

StringReader 文字列入出力クラス

StringWriter
付加
機能
DataInputStream
ストリーム入出力クラス
DataOutputStream
ObjectInputStream
オブジェクト入出力クラス
ObjectOutputStream
BufferedInputStream BufferedReader バッファ入出力クラス
BufferedOutputStream BufferedWriter

LineNumberReader 行入力クラス
PrintStream PrintWriter コンソール出力クラス
PushbackInputStream PushbackReader プッシュバック入力クラス

ストリームは java.io に定義されている以下のクラスが基礎になっています。

java.io のユーティリティクラス
種類 クラス 分     類
直列化 Serializable 直列化宣言インタフェース
Externalizable 外部化宣言インタフェース
ObjectInputValidation オブジェクト検証コールバックインタフェース
ObjectStreamClass 直列化オブジェクト管理クラス
ファイル File ファイルクラス
FileDescriptor ファイル記述子クラス
FilenameFilter ファイル選択インタフェース
RandomAccessFile ランダムアクセスクラス
その他 StreamTokenizer トークン解析クラス