7.ファイルの取り扱い

Copyright(C) 13Sep2013 coskx

このページではJavaプログラムでファイルを取り扱う。
ここで修得してほしい内容は以下の通りである。
1.printfを用いたコンソール画面への出力と同じように,printfを使用してファイルへの出力が出来る。
2.文字単位,行単位でのファイルからの入力が出来る。
3.行単位でのファイル入力から,行を分解して数値データ列の処理が出来る
4.コマンドラインの取り込みと,引数を取り出すことが出来る
5.バイナリファイルの入出力が出来る

内容は以下を含んでいる。
7.1 ファイルへの書き出し
   コンソール画面への出力をそのままファイルへ書き出す 
7.2 テキストファイルの構造を理解する
7.3 ファイルからの文字単位読み込み
   キーボード入力の替わりに,ファイルからデータを読み込む
7.4 ファイルからの行単位読み込み
7.5 ファイルからの数値データの読み込み
7.6 コマンドラインの取り込み
7.7 バイナリファイルの処理

Javaには様々なファイル操作の方法(クラスライブラリ)が用意されている。基本的には○○reader(読み込み,ファイル入力)と○○writer(書き込み,ファイル出力)という名前である。ここでは代表的なReader,Writerを紹介する。


ファイルからの読み込み
(ファイル入力)
ファイルへの書き込み
(ファイル出力)
テキストファイル 文字単位の操作
FileReaderのread()
PrintWriterのprintfなど
テキストファイル 行単位の操作 FileReader BufferedReaderのreadLine()
PrintWriterのprintfなど
テキストファイル 数値データの操作 FileReader BufferedReaderのreadLine()
Stringのsplit()
PrintWriterのprintfなど
バイナリファイル
FileInputStreamのread()
FileOutputStreamのwrite()
演習における注意 ここでのプログラムの実行においては,実行形式ファイルおよび書き出すファイル,読み込み用ファイルはすべて同一ディレクトリに存在するものとし,実行はコンソール画面から行なう。

7.1 ファイルへの書き出し

コンソール画面に文字を表示する時にはSystem.out.printf,System.out.print,System.out.printlnを使った。
ファイルに文字を出力するには似たようなprintf,
print,printlnを使う。

次 のような内容を画面に表示する場合とファイルに書き出す場合のプログラムを並べて書いて比較してみよう。「(A)画面出力」ではコンソール画面に文字が書 き出され,「(B)ファイル出力」ではコンソール画面にはなにも出力されないがファイルmyfile.txtが出来る。テキストエディタでファイル myfile.txtを開いてみると「(A)画面出力」でコンソール画面に表示された内容が書いてあることが確認でき,ファイルへの書き出しが成功してい るはずである。

各自で実行してみなさい。

Hello. How are you?
Fine, thanks. And You?
So so.

List7.1.1 文字出力プログラムの比較

(A)画面出力

(B)ファイル出力(ファイル名はmyfile.txt)

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }
 
    XXXX() {
        System.out.printf("Hello. How are you?\n");
        System.out.printf("Fine, thanks. And You?\n");
        System.out.printf("So so.\n");
    }
}

import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }
 
    XXXX() {
        try {
            PrintWriter mywriter = new PrintWriter("myfile.txt"); /*準備*/

            mywriter.printf("Hello. How are you?\n");
            mywriter.printf("Fine, thanks. And You?\n");
            mywriter.printf("So so.\n");

            mywriter.close(); /*閉じる*/
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}


ファイルの入出力では,ファイルが存在しなくてそれ以上読み込み作業が継続できないとか,
存在しないドライブに対してファイルを書き込もうとしてそれ以上書き込み作業が継続できないといった
ことが起こる。
そのため,エラーが起きたらその後をどうするかプログラムにあらかじめ書いておかなければならない。
この記述方法が

try{
    A
} catch( B ) {
   C
}
という記述である。Aを実行して途中で何かエラーが起こったらCを実行しなさいという意味になる。
Bのところにはエラーを受け取る記述を行い,Cのところにはたとえばエラー内容を表示する記述を行う。

この記述はすでにキーボード入力のためのメソッドgetInt,getDouble,getStringなどの中で用いていた。
たとえばgetIntの中で数値以外のキーが入力され,エラーが生じても大丈夫ようになっていた。

ファイルへ書き出すためのプログラムを検討しよう。全部で3つの部分に分かれている。

項目

プログラムでの記述

1.ファイル名を指定してファイル出力の準備を行なう。
  Fileは型名(実はクラス名)
  myfile,
mywriterは変数名なので別の名前でもよい。
  この後,ファイルはファイル名ではなく,
  mywriterで扱われる
  ファイル名"myfile.txt"の場合はプログラムが置かれたフォルダに
  myfile.txtが作られる。
  ファイル名にはドライブ名,フォルダ名も記述できる。

   
PrintWriter mywriter = new PrintWriter("myfile.txt");

初期値を持つ変数の宣言あるいは配列の宣言に似ている
と考えておこう。
例えば次のx,aryは変数名であった。
int x= 100;
int[] ary= new int[100]
この変数名のところがmywriterになっていると考えよう。
種明かしは「クラス」のところで。
2.書きたいことはここでprintfで書く。
  いくらでも書ける。
  print,printlnも使える。
mywriter.printf(fp,"Hello. How are you?\n");
mywriter.printf(fp,"Fine, thanks. And You?\n");
mywriter.printf(fp,"So so.\n");
3.書くことがなくなったらファイルをクローズする。
  クローズしてしまったらもう書けない。
mywriter.close();

ファイル出力時の改行に関する補足

OSによってファイル内の改行コードが異なっている。
UNIXOS系 : \n (0x0a)      WindowsOS : \r\n (0x0d,0x0a)
(B)のプログラムは,UNIX系のOSに対応した改行のプログラムである。
厳密には
WindowsOSに対応していないことになる。しかしエディタによってはそのまま読めたり,改行コードを変換して
再保存できたりするものもあるので,当面は気にしないことにする。
もし,windowsに対応するなら次の例のように変更すればよい。
mywriter.printf("Hello. How are you?\r\n");

ファイル名を実行時に決めることも出来る。次の例は出力ファイル名を実行時に決め,1000までの素数を書き出すものである。
List7.1.2 素数表(1000まで)のファイル出力

import java.util.*;  // StringTokenizer
import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }
 
    XXXX() {
        int k;/*素数候補*/
        int max=1000;/*検査対象の最大値*/
        int n;/*約数候補*/
        int count=0;/*見つかった素数の個数*/
        System.out.printf("%dまでの素数を求めファイルに書き出します\n",max);
        String fname=getString("出力ファイル名を入力してください →");
        try {
            PrintWriter mywriter = new PrintWriter(fname);               /*準備*/

            mywriter.printf("              %d までの素数\n",max);
            for (k=2;k<=max;k++) {
                n=2;/*約数候補の初期値*/
                while (k%n!=0) n++;
                if (n==k) { /*最初に見つかった約数が素数候補に等しい時*/
                    mywriter.printf("%4d ",k);
                    count++;
                    if (count%10==0) {
                        mywriter.printf("\n");
                    }
                }
            }
            mywriter.printf("\n");
            mywriter.printf("素数は%d個見つかりました。\n",count);

            mywriter.close();                                          /*閉じる*/
            System.out.printf("素数は%d個見つかりました。\n",count);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    private String getString(String prompt){
        BufferedReader bffrd = new BufferedReader(new InputStreamReader(System.in));
        String ret=new String();
        System.out.print(prompt);
        try {
            ret = bffrd.readLine();
        }
        catch(IOException e) {
            System.out.println("IO Error");
            System.exit(1);
        }
        return ret;
    }
}

/*****************コンソール出力********************
1000までの素数を求めファイルに書き出します
出力ファイル名を入力してください →primenumber.txt
素数は168個見つかりました。
****************************************************/

書き出された「primenumber.txt」
              1000 までの素数
   2    3    5    7   11   13   17   19   23   29
  31   37   41   43   47   53   59   61   67   71
  73   79   83   89   97  101  103  107  109  113
 127  131  137  139  149  151  157  163  167  173
 179  181  191  193  197  199  211  223  227  229
 233  239  241  251  257  263  269  271  277  281
 283  293  307  311  313  317  331  337  347  349
 353  359  367  373  379  383  389  397  401  409
 419  421  431  433  439  443  449  457  461  463
 467  479  487  491  499  503  509  521  523  541
 547  557  563  569  571  577  587  593  599  601
 607  613  617  619  631  641  643  647  653  659
 661  673  677  683  691  701  709  719  727  733
 739  743  751  757  761  769  773  787  797  809
 811  821  823  827  829  839  853  857  859  863
 877  881  883  887  907  911  919  929  937  941
 947  953  967  971  977  983  991  997
素数は168個見つかりました。

 課題7 その1


(1)x,x2,x3の表を1≦x≦100でファイル出力するプログラムを作りなさい。  (p07ex01.java)
出力されたファイルの内容を実行結果として扱いなさい。

  x  x^2     x^3  
  1    1       1
  2    4       8
  3    9      27
  4   16      64
  5   25     125
  :    :       :



7.2 テキストファイルの構造

テキストエディタ (例えばterapadなど)で編集することの出来るファイルはテキストファイルと呼ばれる。Javaのプログラムソースファイルもテキストファイルの1つであ る。もともとテキストファイルは,文字と改行コードが一列に並んでいるファイルである。これをテキストエディタなどのアプリケーションが改行コードのとこ ろで改行して人間に見せているので,ふだん見慣れたテキストとして見えるようになっている。例えばテキストエディタで
ABCD
EDG
HIJKLMN
 
のように3行に見えるファイルは
ABCD[改行]EDG[改行]HIJKLMN[改行]

のように一列の文字列で構成されている。
文字コードの説明は「A.変数 (A.4 文字コード) (APPENDIX 2 文字コードに関する補足)」を参照のこと

kskdump.exeで見たファイルの内容表示([改行]は0d 0aで保存されているのがわかる)
 kskdump.exeのダウンロード先

 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f 0123456789abcdef
0000000 :
0000010 :
 41 42 43 44 0d 0a 45 44 47 0d 0a 48 49 4a 4b 4c
 4d 4e 0d 0a
ABCD..EDG..HIJKL
MN..

同様に

ABCD
EDG
HIJKLMN
のように3行に見えるファイルでも(上との違いはHIJKLMNの後に改行がないことである)
ABCD[改行]EDG[改行]HIJKLMN

のように最後の改行がない場合もある。この場合には次のようなファイルになっている。

kskdump.exeで見たファイルの内容表示([改行]は0d 0aで保存されているのがわかる)
 kskdump.exeのダウンロード先

 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f 0123456789abcdef
0000000 :
0000010 :
 41 42 43 44 0d 0a 45 44 47 0d 0a 48 49 4a 4b 4c
 4d 4e
ABCD..EDG..HIJKL
MN

また,エディタで作成した

public class Hello {
    public static void main(String[] args) {
       
Hello mainprg = new Hello();
    }
 
   
Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}

のようなプログラムソースファイルもテキストファイルなので,

public class Hello {[改行]     public static void main(String[] args) {[改行]        Hello mainprg = new Hello();[改行]    }[改行][改行]    Hello() {[改行]        System.out.println("Hello. How are you?");[改行]
        System.out.println("Fine, thanks. And You?");
[改行]         System.out.println("So so.");[改行]     }[改行] }[改行]

のように一列の文字列で構成されている。

kskdump.exeで見たファイルの内容表示([改行]は0d 0aで保存されているのがわかる)
 kskdump.exeのダウンロード先

 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f 
0123456789abcdef
0000000 :
0000010 :
0000020 :
0000030 :
0000040 :
0000050 :
0000060 :
0000070 :
0000080 :
0000090 :
00000a0 :
00000b0 :
00000c0 :
00000d0 :
00000e0 :
00000f0 :
0000100 :
0000110 :
 70 75 62 6c 69 63 20 63 6c 61 73 73 20 48 65 6c
 6c 6f 20 7b 0d 0a 20 20 20 20 70 75 62 6c 69 63
 20 73 74 61 74 69 63 20 76 6f 69 64 20 6d 61 69
 6e 28 53 74 72 69 6e 67 5b 5d 20 61 72 67 73 29
 20 7b
0d 0a 20 20 20 20 20 20 20 20 48 65 6c 6c
 6f 20 6d 61 69 6e 70 72 67 20 3d 20 6e 65 77 20
 48 65 6c 6c 6f 28 29 3b
0d 0a 20 20 20 20 7d 0d
 0a 20
0d 0a 20 20 20 20 48 65 6c 6c 6f 28 29 20
 7b
0d 0a 20 20 20 20 20 20 20 20 53 79 73 74 65
 6d 2e 6f 75 74 2e 70 72 69 6e 74 6c 6e 28 22 48
 65 6c 6c 6f 2e 20 48 6f 77 20 61 72 65 20 79 6f
 75 3f 22 29 3b
0d 0a 20 20 20 20 20 20 20 20 53
 79 73 74 65 6d 2e 6f 75 74 2e 70 72 69 6e 74 6c
 6e 28 22 46 69 6e 65 2c 20 74 68 61 6e 6b 73 2e
 20 41 6e 64 20 59 6f 75 3f 22 29 3b
0d 0a 20 20
 20 20 20 20 20 20 53 79 73 74 65 6d 2e 6f 75 74
 2e 70 72 69 6e 74 6c 6e 28 22 53 6f 20 73 6f 2e
 22 29 3b
0d 0a 20 20 20 20 7d 0d 0a 7d        
public class Hel
lo {..    public
 static void mai
n(String[] args)
 {..        Hell
o mainprg = new
Hello();..    }.
. ..    Hello()
{..        Syste
m.out.println("H
ello. How are yo
u?");..        S
ystem.out.printl
n("Fine, thanks.
 And You?");..
      System.out
.println("So so.
");..    }..}  


ただし,テキストファイルの形式はWindowsOSとUNIXOSでは[改行]のコードの取り扱いが異なっている。
      WindowsOS : 0d 0a   (\r\n)
      UNIXOS    : 0a      (\n)


7.3 テキストファイルの文字単位処理

テキストファイルを一文字ごとに読み込んで処理してみよう。

例1

テキストファイルから1文字読み込みで,ファイルの先頭の10文字を読み込み,画面に書き出すプログラム
ファイルから1文字ずつ読みだす場合は,FileReaderのread()を用いる。読み出し準備に2つの作業が必要である。

読み込み対象ファイル「Peter.txt」
Peter ran straight away to Mr. McGregor's garden,
and squeezed under the gate!
First he ate some French beans;
and then he ate some radishes.

List 7.3.1 テキストファイルから1文字読み込みで,先頭10文字を読み込み,画面に書き出すプログラム 

import java.io.*;    // FileReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }
 
    XXXX() {
        int i,ch;
        try {
            FileReader myfilereader = new FileReader("Peter.txt");     //ファイル読み出し準備

            for (i=0; i<10; i++) { /*ファイル先頭の10文字読み込む*/
                ch=myfilereader.read();
                System.out.printf("%d文字目 [%c(%3d %02xH)]\n",i,(char)ch,ch,ch);
            }

            myfilereader.close();                                 //閉じる
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

実行結果(画面表示)「Peter ran 」までが読み込まれ表示されている。
0文字目 [P( 80 50H)]
1文字目 [e(101 65H)]
2文字目 [t(116 74H)]
3文字目 [e(101 65H)]
4文字目 [r(114 72H)]
5文字目 [ ( 32 20H)]
6文字目 [r(114 72H)]
7文字目 [a( 97 61H)]
8文字目 [n(110 6eH)]
9文字目 [ ( 32 20H)]


例2

  
テキストファイルのコピープログラム
テキストファイルをオープンし,「1文字入力して1文字出力」を繰返し,ファイルの終端まで繰り返す。

FileReader myfilereaderを使ってch=myfilereader.read();で文字を読み込んでいるとき,chには読み込んだ文字のコードが返されるが,ファイル終端に達した場合は-1が返される。

List 7.3.2 テキストファイルのコピー(1文字入力1文字出力)

実行時にコピー元ファイル名とコピー先ファイル名を聞かれるので,
「コピー元ファイル名」を聞かれた時に実在するテキストファイル名
「コピー先ファイル名」を聞かれた時に実在しないファイル名を答えること。

あらかじめチェック用テキストファイル「a.txt」をテキストエディタでつくってから実行し,
「b.txt」が出来たことを確認して,テキストエディタで「b.txt」を見るとよい。

import java.io.*;    // FileReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }
 
    XXXX() {
        int ch;
        String fname0=getString("コピー元のファイル名 : ");
        String fname1=getString("コピー先のファイル名 : ");
        try {
            FileReader myfilereader = new FileReader(fname0);   /*準備*/
            PrintWriter mywriter = new PrintWriter(fname1);     /*準備*/

            ch=myfilereader.read();
            while (ch!=-1) {                  /* -1を読み込んだときはファイル終端に達したと判断できる*/
                mywriter.printf("%c",(char)ch);
                ch=myfilereader.read();
            }

            myfilereader.close();      /*閉じる*/
            mywriter.close();
         /*閉じる*/
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    private String getString(String prompt){
        BufferedReader bffrd = new BufferedReader(new InputStreamReader(System.in));
        String ret=new String();
        System.out.print(prompt);
        try {
            ret = bffrd.readLine();
        }
        catch(IOException e) {
            System.out.println("IO Error");
            System.exit(1);
        }
        return ret;
    }
}


/*********実行時のコンソール画面**************
コピー元のファイル名 :
a.txt
コピー先のファイル名 : b.txt
********************************************/

a.txt
Fish is easy to prepare and quick to cook and is a healthy options for a wide range of tastes and ages, including semi-vegetarians. It is low in calories and fat and provides protein, vitamins and minerals.
b.txt
Fish is easy to prepare and quick to cook and is a healthy options for a wide range of tastes and ages, including semi-vegetarians. It is low in calories and fat and provides protein, vitamins and minerals.

式が値を持つことを利用するとwhileの部分をスマートに記述できる。    

例3

テキストファイルを読み込んで,文字コードを適当に変換して別のテキストファイルに書き出す
1文字読み込んで,書き出すまでに,文字をある規則に従って別の文字に変換すると,ファイルの書き換えを行なう事になる。

List 7.3.3 テキストファイルの小文字大文字変換(1文字入力1文字出力)

メソッド
Character.toUpperCase()を用いて,小文字を大文字に変換する。List 7.3.2と1か所のみ変更する。

あらかじめチェック用テキストファイル「a.txt」をテキストエディタでつくってから実行し,
「b.txt」が出来たことを確認して,テキストエディタで「b.txt」を見るとよい。

もし,ファイル内のアルファベットをすべて小文字にしたかったら
どのようなプログラムになるだろうか考えなさい    

例4

ファイルを1文字ずつ読み込み,ある規則に従って,コード変換して,別なファイルに出力することで,暗号化できる。
例えば,見自コードでは,0x20から0x7eまではアルファベット,数字,記号である。
ある文字コードがこの範囲の値だったら,3文字前にずらすことを考えよう。例えば 'D'→'A','E'→'B','F'→'C',のようにする。
これは,ある文字のコードから3を引くことによって実現できる。ただし,引いた結果が0x20未満になったら,0x5fを加えて,変換結果が0x20から0x7eの範囲を保つことを保証することとする。また暗号化したものを元に戻すにはこの逆の操作を行なえばよい。

List 7.3.4 ソースファイルの暗号化

import java.io.*;    // FileReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        int ch;
        int direction;
        String fname0=getString("コピー元のファイル名 : ");
        String fname1=getString("コピー先のファイル名 : ");
        do {
            direction=getInt("(1)暗号にする (2)復号する    ( 1 or 2 ) :");
        } while (direction!=1&&direction!=2);
        try {
            FileReader myfilereader = new FileReader(fname0);   /*準備*/
            PrintWriter mywriter = new PrintWriter(fname1);     /*準備*/

            ch=myfilereader.read();
            while (ch!=-1) {
                if (direction==1) ch=encodeChar(ch);
                else ch=decodeChar(ch);
                mywriter.printf("%c",(char)ch);
                ch=myfilereader.read();
            }

            myfilereader.close();       /*閉じる*/
            mywriter.close();           /*閉じる*/
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    private int getInt(String prompt){
        BufferedReader bffrd = new BufferedReader(new InputStreamReader(System.in));
        int ret=0;
        System.out.print(prompt);
        try {
            ret = Integer.valueOf(bffrd.readLine()).intValue();
        }
        catch(IOException e) {
            System.out.println("IO Error");
            System.exit(1);
        }
        return ret;
    }

    private String getString(String prompt){
        BufferedReader bffrd = new BufferedReader(new InputStreamReader(System.in));
        String ret=new String();
        System.out.print(prompt);
        try {
            ret = bffrd.readLine();
        }
        catch(IOException e) {
            System.out.println("IO Error");
            System.exit(1);
        }
        return ret;
    }

    /*暗号化メソッド*/
    private int encodeChar(int ch)
    {
        if (0x20<=ch && ch<=0x7e) {
            ch-=3;
            if (ch<0x20) ch+=0x5f;
        }
        return ch;
    }

    /*復号化メソッド*/
    private int decodeChar(int ch)
    {
        if (0x20<=ch && ch<=0x7e) {
            ch+=3;
            if (0x7e<ch) ch-=0x5f;
        }
        return ch;
    }
}

   =====================暗号化の際のコンソール画面の様子=====================

読み込みファイル名 : Hello.java
書き出しファイル名 : Hello.txt
(1)暗号にする (2)復号する    ( 1 or 2 ) :1

Hello.java

public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}


Hello.txt

mr_if`|`i^pp|Ebiil|x
||||mr_if`|pq^qf`|slfa|j^fk%PqofkdXZ|^odp&|x
||||||||Ebiil|j^fkmod|:|kbt|Ebiil%&8
||||z

||||Ebiil%&|x
||||||||Pvpqbj+lrq+mofkqik%~Ebiil+|Elt|^ob|vlr<~&8
||||||||Pvpqbj+lrq+mofkqik%~Cfkb)|qe^khp+|>ka|Vlr<~&8
||||||||Pvpqbj+lrq+mofkqik%~Pl|pl+~&8
||||z
z

    =====================復号化の際のコンソール画面の様子=====================

読み込みファイル名 :
Hello.txt
書き出しファイル名 :
result.txt
(1)暗号にする (2)復号する    ( 1 or 2 ) :2


result.txt

public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}




7.4 テキストファイルの行単位処理


テキストファイルから一行を文字列として読み込んで処理する。
ファイルから1行ずつ読みだす場合は,BufferedReaderreadLine()を用いる。読み出し準備に3つの作業が必要である。

例1


7.3の例1で使ったテキストファイル「Peter.txt」を1行ずつ読み込んで最初の3行を表示してみよう。

List 7.4.1 テキストファイルから1行ずつ読み込んで最初の3行を表示する

import java.io.*;    // FileReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        int i;
        String str;
        try {
            FileReader myFreader = new FileReader(
"Peter.txt");        //ファイル読み出し準備
            BufferedReader myBreader = new BufferedReader(myFreader);  //ファイル読み出し準備

            for (i=0; i<3; i++) { /*ファイル先頭の3行読み込む*/
                str=myBreader.readLine();
                System.out.printf("%d行目 [%s]\n",i,str);
            }
            myBreader.close();                                 //閉じる(準備の逆順)
            myFreader.close();                                 //閉じる
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

実行結果(画面表示)
0行目 [Peter ran straight away to Mr. McGregor's garden,]
1行目 [and squeezed under the gate!]
2行目 [First he ate some French beans;]


ファイルのオープンを簡略化してプログラムを短く表現した場合は次のようになる。

List 7.4.1-A テキストファイルから1行ずつ読み込んで最初の3行を表示する
             別表現(ファイルのオープン作業を1行で表した。myFreaderの宣言を省略した)

import java.io.*;    // FileReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        int i;
        String str;
        try {
            BufferedReader myBreader = new BufferedReader(new FileReader("Peter.txt"));  //ファイル読み出し準備

            for (i=0; i<3; i++) { /*ファイル先頭の3行読み込む*/
                str=myBreader.readLine();
                System.out.printf("%d行目 [%s]\n",i,str);
            }
            myBreader.close();                                 //閉じる
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

実行結果(画面表示)
0行目 [Peter ran straight away to Mr. McGregor's garden,]
1行目 [and squeezed under the gate!]
2行目 [First he ate some French beans;]





例2


プログラムソースファイルを行ごとに読み込んで,行頭に行番号をつけて,テキストファイルに書き出す。

BufferedReader myBreaderを使ってstr=myBreader.readLine();で文字列を読み込んでいるとき,
strには読み込んだ1行の文字列が返されるが,ファイル終端に達した場合はnullが返される。

List 7.4.2 プログラムソースファイルを読み込んで,行頭に行番号をつけて,テキストファイルに書き出す。

import java.io.*;    // FileReader

public class AddNumber {

    public static void main(String[] args) {
        AddNumber mainprg = new AddNumber();
    }

    AddNumber() {
        int i=0;
        String str;
        String fname0=getString("読み込みファイル名 : ");
        String fname1=getString("書き出しファイル名 : ");
        try {
            FileReader myFreader0 = new FileReader(fname0);              //ファイル読み出し準備
            BufferedReader myBreader0 = new BufferedReader(myFreader0);  //ファイル読み出し準備
            PrintWriter mywriter1 = new PrintWriter(fname1);             //ファイル書き出し準備

            str=myBreader0.readLine();
            while (str!=null) { /*ファイルの終端でなかったら*/
                mywriter1.printf("%04d %s\n",++i,str);
                str=myBreader0.readLine();
            }
            myBreader0.close();                                 //閉じる(準備の逆順)
            myFreader0.close();                                 //閉じる
            mywriter1.close();                                  //閉じる
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    private String getString(String prompt){
        BufferedReader bffrd = new BufferedReader(new InputStreamReader(System.in));
        String ret=new String();
        System.out.print(prompt);
        try {
            ret = bffrd.readLine();
        }
        catch(IOException e) {
            System.out.println("IO Error");
            System.exit(1);
        }
        return ret;
    }
}


/*********実行時のコンソール画面**************
読み込みファイル名 :
AddNumber.java
書き出しファイル名 : AddNumber.txt
********************************************/

AddNumber.java
このプログラム
AddNumber.txt
0001 import java.io.*;    // FileReader
0002
0003 public class AddNumber {
0004
0005     public static void main(String[] args) {
0006         AddNumber mainprg = new AddNumber();
0007     }
0008
0009     AddNumber() {
0010         int i=0;
0011         String str;
0012         String fname0=getString("読み込みファイル名 : ");
0013         String fname1=getString("書き出しファイル名 : ");
0014         try {
0015             FileReader myFreader0 = new FileReader(fname0);              //ファイル読み出し準備
0016             BufferedReader myBreader0 = new BufferedReader(myFreader0);  //ファイル読み出し準備
0017             PrintWriter mywriter1 = new PrintWriter(fname1);             //ファイル書き出し準備
0018
0019             str=myBreader0.readLine();
0020             while (str!=null) { /*ファイルの終端でなかったら*/
0021                 mywriter1.printf("%04d %s\n",++i,str);
0022                 str=myBreader0.readLine();
0023             }
0024             myBreader0.close();                                 //閉じる(準備の逆順)
0025             myFreader0.close();                                 //閉じる
0026             mywriter1.close();                                  //閉じる
0027         } catch (Exception e) {
0028             System.out.println(e);
0029         }
0030     }
0031
0032     private String getString(String prompt){
0033         BufferedReader bffrd = new BufferedReader(new InputStreamReader(System.in));
0034         String ret=new String();
0035         System.out.print(prompt);
0036         try {
0037             ret = bffrd.readLine();
0038         }
0039         catch(IOException e) {
0040             System.out.println("IO Error");
0041             System.exit(1);
0042         }
0043         return ret;
0044     }
0045 }

 


 課題7 その2

(2)ソースプログラムファイルを読み込み,何行で構成されていたか,何文字(リターンコードなどの 制御コードも含む)で構成されていたかをカウントするプログラムを作成しなさい。なお,検査対象ソースプログラムファイル名は,実行時にキーボードから読み込むものとする。出力はコンソール画面とする。(ファイルの最終文字がリターンコードである場合,ない場合に対応しているかどうか確認すること) (p07ex02.java)
厄介なヒント 行数を数える場合,「'\n'」を数えればよいと思いますか?
ファイルによっては最終行の終わりに,「'\n'」が付いていないものもあります。
提出実行結果は,ソースファイルの内容および画面表示とします。

(3)ソースプログラムファイルを読み込み,行ごとに,逆順ならびにして,別のファイル名で保存しなさい。なお,ソースプログラムファイル名は,実行時にキーボードから読み込むものとする。逆順ならびとは次のようなものである。(p07ex03.java)
提出実行結果は,出力されたファイルの内容とします。

public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}


{ olleH ssalc cilbup
{ )sgra ][gnirtS(niam diov citats cilbup   
;)(olleH wen = grpniam olleH       
}   

{ )(olleH   
;)"?uoy era woH .olleH"(nltnirp.tuo.metsyS       
;)"?uoY dnA .sknaht ,eniF"(nltnirp.tuo.metsyS       
;)".os oS"(nltnirp.tuo.metsyS       
}   
}

のようになる。

プログラミングにおいてメソッドのところで作成したprivate String strcpyrvs(String str)を用いなさい。
private String strcpyrvs(String str)は与えられた文字列sを逆順にして返すメソッドであった。
なお,実行の検査には次のファイル
Hello.javaを用いなさい。

Hello.java

public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}


(4)入力ファイル中の単語を抜き出し出力ファイルへ書き出すプログラムを作成しなさい。単語とはアル ファベットで始まり,アルファベットと数字とアンダーバー(_)のみでできている文字列である。単語の書き出しにおいては,単語ごとにスペースで区切っ て,8つごとに改行するものとする.例えば何かのプログラムを入力ファイルとした時,次のようなファイルができるでしょう。なお,ファイル名は,実行時に キーボードから読み込むものとす る。                                            (p07ex04.java)

 参考 Cプログラム(単語を抜き出して画面に表示している。課題とは異なる)


Hello.javaを抜き出した結果は次のようになる。
Hello.java

public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}

抜き出した結果
public class Hello public static void main String
args Hello mainprg new Hello Hello System out
println Hello How are you System out println
Fine thanks And You System out println So
so

次のファイルについて検証しなさい。(12qwe は数字で始まるため単語ではないので抽出されてはならない)

test.txt

1234 ..wer qwe123+wer456
sw_qwe,q12_12,12qwe,A123B123
wsed_123


(5)「(4)」で入力ファイル中の単語を抜き出し,出力ファイルへ書き出したが,下のようにそれぞれの単語の出現回数を数えてその結果を出力ファイルに書き出しなさい。(文字列配列とカウンタ変数の配列が必要です。) (p07ex05.java)

hello.javaを使って動作を動作を検証しなさい。

Hello.java
public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}
次のような結果が得られれば正解
public                 2
class                  1
Hello                  5
static                 1
void                   1
main                   1
String                 1
args                   1
mainprg                1
new                    1
System                 3
out                    3
println                3
How                    1
are                    1
you                    1
Fine                   1
thanks                 1
And                    1
You                    1
So                     1
so                     1



7.5 ファイルからの数値データの読み込み


Javaには数値データを便利に取り込む機能がない。データの取り込みには,エラーや失敗がつきものであるため,
自分で何とかプログラムしなければならない。

ファイルから数値データを読み込む前に,文字列 "128, 256, 512" から3つの値を切り出して,3つの変数に保存することを考えよう。
手順は次のようになる。
(1)与えられた文字列について「,」を区切りと考えて分割し,それぞれを文字列配列に保存する。
(2)後でエラーが起きないように,文字列配列には数字だけが入っているようにする。
 (ここでは前後の空白文字を取り除いている)
(3)文字列に数字以外のものが入っていてエラーが起こるかもしれないので,try-catchで守り
  ながら,各文字列をint型変数に変換する

List7.5.1 数値が記述されている文字列から数値を読み取る
import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        int i,num;
        int[] data= new int[3];
        String str="128, 256, 512";
        System.out.printf("%s\n",str);

        /*文字列strを「,」で区切って複数の文字列に分解し,文字列配列に保存する*/
        String[] strary=str.split(",");
        num=strary.length;
       
/*取り出した文字列の個数表示*/
        System.out.printf("num=%d\n",num);

        for (i=0; i<num; i++) {
            System.out.printf("strary[%d] [%s]\n",i,strary[i]);
        }
        for (i=0; i<num; i++) {
            /*文字列の前後にあるスペース文字を取り除く*/
            strary[i]=strary[i].trim();
        }
        for (i=0; i<num; i++) {
            System.out.printf("strary[%d] [%s]\n",i,strary[i]);
        }

        for (i=0; i<num; i++) {
            try {
                /*数字文字列を整数値に変換してint型配列に保存*/
                data[i] = Integer.valueOf(strary[i]).intValue();
            }
            catch(Exception e) {
                System.out.println("Conversion Error");
                System.exit(1);
            }
        }

        for (i=0; i<num; i++) {
            System.out.printf("data[%d] %d\n",i,data[i]);
        }
    }
}

/*****実行結果************
128, 256, 512
num=3
strary[0] [128]
strary[1] [ 256]
strary[2] [ 512]
strary[0] [128]
strary[1] [256]
strary[2] [512]
data[0] 128
data[1] 256
data[2] 512
**************************/

複数の値が記述された文字列から数値を切り出す方法がわかったので,数値データの記述されたファイルから数値データを読み込んでみよう。
次のようなファイルmydata.txtから3つの変数に値を読み込むことを考えよう。
文字列に
ファイルから1行読み込む方法は,7.4で行ったので,それと合わせればファイルから数値データ読み込みが可能となる。
mydata.txt
128, 256, 512

List7.5.2 ファイルからの数値データ読み込み
import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        int i,num=0;
        int[] data= new int[3];
        String str;
        try {
            FileReader myFreader = new FileReader(
"mydata.txt");       //ファイル読み出し準備
            BufferedReader myBreader = new BufferedReader(myFreader);  //ファイル読み出し準備

            /*ファイル先頭の1行を読み込む*/
            str=myBreader.readLine();

            System.out.printf("%s\n",str);
            String[] strary=str.split(",");
            num=strary.length;
            for (i=0; i<num; i++) {
                strary[i]=strary[i].trim();
                data[i] = Integer.valueOf(strary[i]).intValue();
            }
            myBreader.close();                                 //閉じる
(準備の逆順)
            myFreader.close();                                 //閉じる
        } catch (Exception e) {
            System.out.println(e);
        }
        for (i=0; i<num; i++) {
            System.out.printf("data[%d] %d\n",i,data[i]);
        }
    }
}


/*****実行結果************
128, 256, 512
data[0] 128
data[1] 256
data[2] 512
**************************/

次の例題として,複数の学生(100人未満)の英語・数学・国語のテストの点(0~100)の処理を考えよう。学生番号を0~9とし,英語・数学・国語の科目 番号を0,1,2とする。科目ごとの平均と各学生の3科目合計点を求める事にする。例えば,学生番号4の英語・数学・国語の得点をscore[4] [0],score[4][1],score[4][2]とし,合計点はscore[4][3]にしまうことにする。下に示す得点ファイルから読み込むこととする。人数はプログラミング時点では不明で,得点ファイルにデータが存在するだけの人数がいることにする。
処理内容は,個人の3科目の合計点,各科目の平均点および個人合計点の平均点の算出とする。

List7.5.3 ファイル中の成績データの処理

import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        int[][] score= new int[100][4];
        int i,j;
        int num=0,numStudents=0;;
        String str;
        try {
            FileReader myFreader = new FileReader(
"mydata2.txt");      //ファイル読み出し準備
            BufferedReader myBreader = new BufferedReader(myFreader);  //ファイル読み出し準備

            str=myBreader.readLine();
            while (str!=null) {
                System.out.printf("%s\n",str);
                String[] strary=str.split(",");
                num=strary.length;
                for (i=0; i<num; i++) {
                    strary[i]=strary[i].trim();
                    score[numStudents][i] = Integer.valueOf(strary[i]).intValue();
                }
                numStudents++;
                str=myBreader.readLine();
            }
            myBreader.close();                                 //閉じる
(準備の逆順)
            myFreader.close();                                 //閉じる
        } catch (Exception e) {
            System.out.println(e);
        }

        int[] sum= new int[4];
        double[] average=new double[4]; /*英・数・国・(合計)の順の平均値*/
        for (i=0;i<numStudents;i++) {
            score[i][3]=0;
            for (j=0;j<3;j++) {
                score[i][3]+=score[i][j];
            }
        }
        for (j=0;j<4;j++) {
            sum[j]=0;
            for (i=0;i<numStudents;i++) {
                sum[j]+=score[i][j];
            }
            average[j]=sum[j]/(double)numStudents;
        }
        System.out.printf("学生番号 英語 数学 国語 合計\n");
        for (i=0;i<numStudents;i++) {
            System.out.printf("%6d    %3d   %3d   %3d   %3d\n",
                i+1,score[i][0],score[i][1],score[i][2],score[i][3]);
        }
        System.out.printf("   平均    %.1f  %.1f  %.1f %.1f\n",
            average[0],average[1],average[2],average[3]);
    }
}

テキストファイルmydata2.txt (実行前に作っておく)
 86, 75, 60
 75, 68, 81
 84, 98,100
 87, 76, 48
 82, 58, 73
100, 87, 98
 64, 72, 70
 87, 68, 99
 98, 87, 68
 87, 72, 84
実行時のコンソール出力
 86, 75, 60
 75, 68, 81
 84, 98,100
 87, 76, 48
 82, 58, 73
100, 87, 98
 64, 72, 70
 87, 68, 99
 98, 87, 68
 87, 72, 84
学生番号 英語 数学 国語 合計
     0     86    75    60   221
     1     75    68    81   224
     2     84    98   100   282
     3     87    76    48   211
     4     82    58    73   213
     5    100    87    98   285
     6     64    72    70   206
     7     87    68    99   254
     8     98    87    68   253
     9     87    72    84   243
   平均    85.0  76.1  78.1 239.2




 課題7 その3

(6)次の枠内は,あるクラスの英語,数学,理科,国語の試験の得点一覧である。テキストエディタにコ ピー&ペーストして,marks.txtというファイルを作成しなさい。次に,このファイルを読み込み,各科目の平均点,学生ごとの総点,総点の平均を求め,新たに一覧表ファイルmarks1.txtを作成するプログラムを作成しなさい。(p07ex06.java)
出力されたファイルの内容を実行結果として扱いなさい。

  70,  59,  56,  66
 100, 100, 100, 100
  68,  90,  96,  94
  79,  92,  85,  75
  64,  66,  72,  50
 100, 100, 100, 100
  81,  92,  86,  97
  95,  88,  88,  79
  78,  74,  75,  74
  75,  80,  92,  75
  87,  76,  77,  63
  90,  90,  99, 100
  68,  68,  67,  75
  66,  66,  69,  71
  71,  69,  73,  80
  98,  81,  98,  97
 100, 100, 100, 100
  91, 100,  94,  92
  89,  87,  73,  68
  89, 100, 100,  94
  21,  27,  26,  25
 100, 100, 100, 100
  36,  53,  32,  31
  97,  74,  72,  85
  86,  85,  81,  79
  75,  71,  63,  72
  88,  94,  87,  84
  62,  68,  72,  60
  62,  68,  62,  70
  92,  88,  86,  70
  57,  64,  69,  64
  55,  77,  51,  73
  58,  74,  80,  71
  97,  91,  79, 100
  69,  58,  72,  69
  38,  54,  35,  19
  31,  23,  34,  37
  94,  85,  71,  63
  64,  90,  71,  73
  55,  51,  50,  48
  97, 100, 100, 100
  87,  83, 100,  85



7.6 コマンドラインの取り込み

UNIXのコンソール,Windowsのコマンドプロンプト,Windowsのファイルのドロップに対応した内容
興味があったらここを読むこと

興味があったらここを読むこと   


7.7 バイナリファイルの処理

テキストファイルは文字コードと改行などの制御コードで出来ている。そのためエディタと呼ばれる種類のアプリケーションで内容を見たり,変更することが容易である。
これに対して,画像やサウンドを保存するファイルは,データのコンピュータ内部表現をそのまま保存しているファイルである。
例えば音を表現する時は,1/8000秒ごとの8ビットの数値の連続で音の波形データを表わすことがある。
例えば,グラフで音の波形を表すと次のようになるが,

これを数値であらわすと,
0,31,56,68,66,50,25,-2,-24,-36,-33,-16,11,41,68,86,89,77,53,23,-6,-27,-36,-31,-12,13,40,....
の ようになる。データをこのままテキストファイルとして保存してもよいが,1ポイントあたり4文字程度(4バイト)必要となる。しかし,各データは8ビット であることが約束されているため,コンピュータ内部表現では,1バイトである。これをそのまま保存すると1ポイントあたり1バイトとなり,テキストファイ ルで保存するのに比べ1/4のサイズのファイルとなる。
(実際のサウンドファイルや画像ファイルではファイルサイズを小さくするための工夫がなされ,ファイルの先頭にはヘッダーブロックと呼ばれる必要な一連のデータが保存されている部分がある。)

テキストファイルとバイナリファイルの書き出しと読み込みを比較してみよう。
テキストファイルの書き出しと読み込み バイナリファイルの書き出しと読み込み

/*テキストファイル"sample.txt"の書き出し*/
import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        byte[] data={
            (byte)120, (byte)23, (byte)102, (byte)(-120),
            (byte)(-94), (byte)5, (byte)98, (byte)(-100),
            (byte)109, (byte)23, (byte)117, (byte)122,
            (byte)(-112), (byte)23, (byte)11, (byte)(-22),
            (byte)120, (byte)123, (byte)(-11), (byte)100
        };
        int i;
        int num=data.length;
        try {
            PrintWriter mywriter = new PrintWriter("sample.txt");

            for (i=0; i<num; i++) {
                mywriter.printf("%d\n",data[i]);
            }

            mywriter.close(); /*閉じる*/
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

/*バイナリファイル"sample.bin"の書き出し*/
import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        byte[] data={
            (byte)120, (byte)23, (byte)102, (byte)(-120),
            (byte)(-94), (byte)5, (byte)98, (byte)(-100),
            (byte)109, (byte)23, (byte)117, (byte)122,
            (byte)(-112), (byte)23, (byte)11, (byte)(-22),
            (byte)120, (byte)123, (byte)(-11), (byte)100
        };
        int i;
        int num=data.length;
        try {
            FileOutputStream Fstream=new FileOutputStream("sample.bin");

            Fstream.write(data,0,num); /*byteブロックの書き込み*/

            Fstream.close(); /*閉じる*/
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

説明
byte型変数は8bit,値の範囲は-128~127
説明
Fstream.write(data,0,num)はbyte配列dataの第0要素からnum個出力する

/*テキストファイル"sample.txt"の読み込み*/
import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        byte[] data= new byte[1024];
        int i=0;
        int num=0;
        String str;
        try {
            FileReader myFreader = new FileReader("sample.txt");
            BufferedReader myBreader = new BufferedReader(myFreader);

            str=myBreader.readLine();
            while (str!=null) {
                str=str.trim();
                data[i] = (byte)Integer.valueOf(str).intValue();
                i++;
                str=myBreader.readLine();
            }

            myBreader.close();
            myFreader.close();
        } catch (Exception e) {
            System.out.println(e);
        }
        num=i;
        for (i=0; i<num; i++) {
            System.out.printf("(%02d) %4d\n",i,data[i]);
        }
    }
}

/****実行結果****
(00)  120
(01)   23
(02)  102
(03) -120
(04)  -94
(05)    5
(06)   98
(07) -100
(08)  109
(09)   23
(10)  117
(11)  122
(12) -112
(13)   23
(14)   11
(15)  -22
(16)  120
(17)  123
(18)  -11
(19)  100
********************/

/*バイナリファイル"sample.bin"の読み込み*/
import java.io.*;    // BufferedReader

public class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }

    XXXX() {
        byte[] data= new byte[1024];
        int num=0;
        String str;
        int i;
        try {
            FileInputStream Fstream=new FileInputStream("sample.bin");

            num=Fstream.read(data);

            Fstream.close();
        } catch (Exception e) {
            System.out.println(e);
        }
        for (i=0; i<num; i++) {
            System.out.printf("(%02d) %4d\n",i,data[i]);
        }
    }
}

/****実行結果****
(00)  120
(01)   23
(02)  102
(03) -120
(04)  -94
(05)    5
(06)   98
(07) -100
(08)  109
(09)   23
(10)  117
(11)  122
(12) -112
(13)   23
(14)   11
(15)  -22
(16)  120
(17)  123
(18)  -11
(19)  100

********************/

  説明
num=Fstream.read(data);
は,byte配列dataにファイルからbyteデータを読み込み,
numには読み込んだbyte数を保存する。
Windows PCでの
テキストファイル"sample.txt"の内容
Windows PCでの
バイナリファイル"sample.bin"の内容
sample.txt
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f
00 : 31 32 30 0a 32 33 0a 31 30 32 0a 2d 31 32 30 0a
10 : 2d 39 34 0a 35 0a 39 38 0a 2d 31 30 30 0a 31 30
20 : 39 0a 32 33 0a 31 31 37 0a 31 32 32 0a 2d 31 31
30 : 32 0a 32 33 0a 31 31 0a 2d 32 32 0a 31 32 30 0a
40 : 31 32 33 0a 2d 31 31 0a 31 30 30 0a            
     0123456789abcdef
00 : 120.23.102.-120.
10 : -94.5.98.-100.10
20 : 9.23.117.122.-11
30 : 2.23.11.-22.120.
40 : 123.-11.100.
sample.bin
          +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f
0000000 : 78 17 66 88 a2 05 62 9c 6d 17 75 7a 90 17 0b ea
0000010 : 78 7b f5 64                                    
          0123456789abcdef
0000000 : x.f...b.m.uz....
0000010 : x{.d  

説明
「31」は16進数で,「1」の文字コード
「0d」は'\r'「0a」は'\n'

 (UNIXでは'\r'がない)

説明
バイナリファイルの大きさが小さいことがわかる。





7.8 ファイル操作のまとめ

Javaには様々なファイル操作の方法(クラスライブラリ)が用意されている。基本的には ○○reader(読み込み,ファイル入力)と○○writer(書き込み,ファイル出力)という名前である。ここでは代表的な Reader,Writerを紹介してきたのでまとめておく。


ファイルからの読み込み
(ファイル入力)
ファイルへの書き込み
(ファイル出力)
テキストファイル 文字単位の操作
FileReaderのread() PrintWriterのprintfなど
テキストファイル 行単位の操作 FileReader BufferedReaderのreadLine() PrintWriterのprintfなど
テキストファイル 数値データの操作 FileReader BufferedReaderのreadLine()
Stringのsplit()
PrintWriterのprintfなど
バイナリファイル
FileInputStreamのread() FileOutputStreamのwrite()
ここに取り上げた方法以外にも特徴を持ったreaderやwriterがあるので,自分で調べて用途に適したものをりようするとよい。


 課題7


(1)x,x2,x3の表を1≦x≦100でファイル出力するプログラムを作りなさい。  (p07ex01.java) (再掲)
出力されたファイルの内容を実行結果として扱いなさい。

  x  x^2     x^3  
  1    1       1
  2    4       8
  3    9      27
  4   16      64
  5   25     125
  :    :       :


(2)ソースプログラムファイルを読み込み,何行で構成されていたか,何文字(リターンコードなどの 制御コードも含む)で構成されていたかをカウントするプログラムを作成しなさい。なお,検査対象ソースプログラムファイル名は,実行時にキーボードから読み込むものとする。出力はコンソール画面とする。(ファイルの最終文字がリターンコードである場合,ない場合に対応しているかどうか確認すること) (p07ex02.java)
厄介なヒント 行数を数える場合,「'\n'」を数えればよいと思いますか?
ファイルによっては最終行の終わりに,「'\n'」が付いていないものもあります。
提出実行結果は,ソースファイルの内容および画面表示とします。

(3)ソースプログラムファイルを読み込み,行ごとに,逆順ならびにして,別のファイル名で保存しなさい。なお,ソースプログラムファイル名は,実行時にキーボードから読み込むものとする。逆順ならびとは次のようなものである。(p07ex03.java)
提出実行結果は,出力されたファイルの内容とします。

public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}


{ olleH ssalc cilbup
{ )sgra ][gnirtS(niam diov citats cilbup   
;)(olleH wen = grpniam olleH       
}   

{ )(olleH   
;)"?uoy era woH .olleH"(nltnirp.tuo.metsyS       
;)"?uoY dnA .sknaht ,eniF"(nltnirp.tuo.metsyS       
;)".os oS"(nltnirp.tuo.metsyS       
}   
}

のようになる。

プログラミングにおいてメソッドのところで作成したprivate String strcpyrvs(String str)を用いなさい。
private String strcpyrvs(String str)は与えられた文字列sを逆順にして返すメソッドであった。
なお,実行の検査には次のファイルHello.javaを用いなさい。

Hello.java

public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}


(4)入力ファイル中の単語を抜き出し出力ファイルへ書き出すプログラムを作成しなさい。単語とはアル ファベットで始まり,アルファベットと数字とアンダーバー(_)のみでできている文字列である。単語の書き出しにおいては,単語ごとにスペースで区切っ て,8つごとに改行するものとする.例えば何かのプログラムを入力ファイルとした時,次のようなファイルができるでしょう。なお,ファイル名は,実行時に キーボードから読み込むものとす る。                                            (p07ex04.java)

 参考 Cプログラム(単語を抜き出して画面に表示している。課題とは異なる)

Hello.javaを抜き出した結果は次のようになる。

Hello.java

public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}

抜き出した結果
public class Hello public static void main String
args Hello mainprg new Hello Hello System out
println Hello How are you System out println
Fine thanks And You System out println So
so

次のファイルについて検証しなさい。(12qwe は数字で始まるため単語ではないので抽出されてはならない)

test.txt

1234 ..wer qwe123+wer456
sw_qwe,q12_12,12qwe,A123B123
wsed_123


(5)「(4)」で入力ファイル中の単語を抜き出し,出力ファイルへ書き出したが,下のようにそれぞれの単語の出現回数を数えてその結果を出力ファイルに書き出しなさい。(文字列配列とカウンタ変数の配列が必要です。) (p07ex05.java)

hello.javaを使って動作を動作を検証しなさい。

Hello.java
public class Hello {
    public static void main(String[] args) {
        Hello mainprg = new Hello();
    }

    Hello() {
        System.out.println("Hello. How are you?");
        System.out.println("Fine, thanks. And You?");
        System.out.println("So so.");
    }
}
次のような結果が得られれば正解
public                 2
class                  1
Hello                  5
static                 1
void                   1
main                   1
String                 1
args                   1
mainprg                1
new                    1
System                 3
out                    3
println                3
How                    1
are                    1
you                    1
Fine                   1
thanks                 1
And                    1
You                    1
So                     1
so                     1


(6)次の枠内は,あるクラスの英語,数学,理科,国語の試験の得点一覧である。テキストエディタにコ ピー&ペーストして,marks.txtというファイルを作成しなさい。次に,このファイルを読み込み,各科目の平均点,学生ごとの総点,総点の平均を求め,新たに一覧表ファイルmarks1.txtを作成するプログラムを作成しなさい。(p07ex06.java)
出力されたファイルの内容を実行結果として扱いなさい。

  70,  59,  56,  66
 100, 100, 100, 100
  68,  90,  96,  94
  79,  92,  85,  75
  64,  66,  72,  50
 100, 100, 100, 100
  81,  92,  86,  97
  95,  88,  88,  79
  78,  74,  75,  74
  75,  80,  92,  75
  87,  76,  77,  63
  90,  90,  99, 100
  68,  68,  67,  75
  66,  66,  69,  71
  71,  69,  73,  80
  98,  81,  98,  97
 100, 100, 100, 100
  91, 100,  94,  92
  89,  87,  73,  68
  89, 100, 100,  94
  21,  27,  26,  25
 100, 100, 100, 100
  36,  53,  32,  31
  97,  74,  72,  85
  86,  85,  81,  79
  75,  71,  63,  72
  88,  94,  87,  84
  62,  68,  72,  60
  62,  68,  62,  70
  92,  88,  86,  70
  57,  64,  69,  64
  55,  77,  51,  73
  58,  74,  80,  71
  97,  91,  79, 100
  69,  58,  72,  69
  38,  54,  35,  19
  31,  23,  34,  37
  94,  85,  71,  63
  64,  90,  71,  73
  55,  51,  50,  48
  97, 100, 100, 100
  87,  83, 100,  85


(7)double型配列をバイナリファイルに格納し,もう一度読み出して,もとのデータが復元されることを確認しなさい。(p07ex07.java)
テストするデータは次のとおりとする。
double ddata[10]={
    1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0
};