page5(update:2016/11/01)


[ prev | next | index ]

5.制御構造

 実行制御の構文はC言語に似ていますが、javaの条件判断はboolean型の値で行われます。さらに、breakやcontinueでは対応する繰り返し構文をラベル を用いて指定できます。

※java5以降では拡張for文が使えます。しかし、この紹介は後のCollectionFrameworkで行います。

C言語に無い新しい構文として、java言語には例外処理が有ります。今回はこの例外処理をぜひ理解してください。

目次

[目次]

5.1 処理の分岐

普通は書かれた順番に命令を実行するので、そのプログラムの処理の流れは1本になっています。しかし、条件に応じて処理を分けたい場合もあります。そこで、処理の流れを分岐させる為の構文としてif 文が用意されています。

5.1.1 if文 

if(条件式) 文A ;else 文B;

文Bが無い場合はelseの部分を省略して書くことができます。

if(条件式) 文A 

動作:
条件式の値がtrueなら文Aを実行、falseなら文Bを実行し次の命令に進む。条件式が戻す値はboolean型でなければいけません。

※boolean型の値をプログラム中に直接記述するリテラルにはtruefalseを使います。

文Aや文Bの部分で複数の文を入れたいなら次の様に複文(compound statement/ブロックblock)を使います。

if(条件式) {文A1;文A2;文A3;文A4;} else {文B1;文B2;}

{ }で囲まれた部分が複文です。 (elseの前には;が無いので注意)

論理演算子と関係演算子

条件式を書く為に論理演算子や関係演算子、等価演算子が用意されています。これは暗記して下さい

C言語と外見上同じに見えますが戻り値がboolean型である点が異なります。

論理演算子 一般形 意味
&& e1 && e2 論理AND:e1、e2がともにtrueなら戻り値true、異なる場合にfalse
(注)e1がfalseならe2を評価せずにfalseを戻す

|| e1 || e2 論理OR:e1、e2が何れかtrueなら戻り値true、異なる場合にfalse
(注)e1がtrueならe2を評価せずにtrueを戻す

! ! e 論理NOT: eがtrueなら戻り値false、 eがfalseなら戻り値true
関係演算子
   
< e1 < e2 e1<e2なら戻り値true、異なる場合にfalse
<= e1 <= e2 e1≦e2なら戻り値true、異なる場合にfalse
> e1 > e2 e1>e2なら戻り値true、異なる場合にfalse
>= e1 >= e2 e1≧e2なら戻り値true、異なる場合にfalse
等価演算子    
== e1 == e2 等号:  値が等しいなら戻り値true、異なる場合にfalse
!= e1 != e2 不等号: 値が等しいなら戻り値false、異なる場合にtrue

等価演算子 == の注意点

等価演算子は変数の値が等しいときにtrueとなります。基本データ型ならばこのことで混乱は生じませんが、参照データ型の場合は注意が必要です。

C言語では2つのポインター変数p,qに同じアドレスが格納してあればp==qはtrueとなりいます。同様にjavaの参照変数p,qも同じインスタンスを参照している場合にp==qはtrueとなります。

※この場合、同じインスタンスなので中身に違いが出る筈がありません。

異なるインスタンスの中身が同じかどうかを判定するにはどうすればいいのでしょう。複雑なインスタンスになると中身が同じと判定する基準も定義が難しくなりそうです。例えば2つのウインドウに同じ文字列が表示されていれば同じなのか?文字の大きさが違えば違うのか?といったことが考えられます。

java言語ではインスタンスの中身が同じか否かを返す演算子は在りません。代わりにメソッドequals()が用意されています。equals()は既定値では同じインスタンスの場合にtrueを返しますが、文字列Stringのequals()は文字列の中身が等しい場合にtrueを戻すように上書きされています。

 ※equals()はメソッドなので、クラスごとに上書きして動作を変更することが許されています。

public class TestEq
{
    public static void main(String args[])
    {
        int a=12,b=12;
        System.out.println("a=12,b=12;");
        System.out.println("a==b :" + (a==b) );
        System.out.println();
        //
        String c="ABC123",d="ABC",e="123",f=d+e;
        System.out.println("String c=\"ABC123\",d=\"ABC\",e=\"123\",f=d+e;");
        System.out.println("c=\""+c+"\"");
        System.out.println("f=\""+f+"\"");
        System.out.println("c==f :" + (c==f) );
        System.out.println("c.equals(f) :" + (c.equals(f)) );
    }
}
/*実行結果
a=12,b=12;
a==b :true

String c="ABC123",d="ABC",e="123",f=d+e;
c="ABC123"
f="ABC123"
c==f :false
c.equals(f) :true
*

5.1.2 多重分岐

入れ子のif文で多重分岐を記述できます。3個に分岐する場合は次の様に書きます。

if(条件式1文A;else if(条件式2文B;else 文C

これはif文のelse以下がさらにif文になった形です。上記の場合は条件に応じて文A〜Cの何れか1つが必ず実行されます。

ソースプログラムはフリーフォーマットなので、改行や空白はコンパイルにおいては区切りとしての意味しか持ちません。プログラマはプログラム構造が解かり易い様に自由に改行や空白を入れることができます。上記の if 文も下記の様に改行を入れて記述することが多いでしょう。

if(条件式1)   文A;
else if(条件式2文B;
else        文C

上の文Cをさらにif文にすればいくらでも分岐の数を増やせます。

条件式の真偽で多重分岐するので、一般的な多重分岐を記述できます。

5.1.3 switch文

整数値や文字型のデータ値で多重分岐する場合によく使われる形です。下記に構文の形を示しますが式の値と等しいcase文に処理が跳びます。その後はbreak文にぶつかるまで上から下へ順番に実行します。C言語のswitch文と同様です。

switch(){
        case 定数式1://式の値が定数式1に等しければここから始める
                ....
                break;//ここでswitch構文の外へ
        case 定数式2:
        case 定数式3:
                //この様に重ねると式の値が定数式2or3でここに来る
                ....
                break;//ここでswitch構文の外へ
        default://該当するcase文がない場合はここから始める(不要なら省略できる)
                ....
}

java7の新機能

定数式の部分に今まではint型の値しか使えませんでした。しかし、java7からはStringが使えます。

switch(文字列を与える式){
        case "文字列1":
                ....
                break;
        case "文字列2":
                ....
                break;
        case "文字列3":
                ....
                break;
        default:
                ....
}

[目次]

5.2 繰り返しの構文

 構文はC/C++言語とほとんど同じです。

5.2.1 while文

もっとも一般的な繰り返しの構文はwhile文で

while(条件式) 文 

動作:
条件式の値がtrueなら文を実行し再び条件式の判定を行う。結果的に条件式の値がfalseになるまで文を繰り返し実行する。

(注)文を実行することで条件式の値が変化しない場合は無限ループになる可能性がある。

下記の様に文を複文にすることでまとまったプログラムを繰り返し実行できる。

while(条件式){文1; 文2;... }

5.2.2 for文

繰り返しの回数があらかじめ決まっている場合にはfor文を使います 。

※C/C++やjava言語では、forとwhileの使い分けに決りがあるわけではない。whileで書ける繰り返しはforでも書けるし、逆も同様です。

for(初期設定式;条件式;再設定式) 文 

動作:
初期設定式を実行後、条件式の値がtrueなら文を実行する。再設定式を実行後、再び条件式の判定を行う。文を複文にすることでまとまったプログラムを繰り返し実行できる。

多くの場合次の様な形で使われる。

.....
int sum=0;
for(int n=0; n<100 ; n++ ){/*繰り返しの初期設定条件再設定がまとまっている*/
        sum=sum+1.0/n;
}

(注)java言語ではfor文の繰り返しの回数を数える変数はfor文の初期設定式で宣言することもよく行われます。
for(
int n=0 ; n<10 ; n++){....

 ※初期設定式と再設定式のところはカンマで区切って複数の式を書くことができます。 これはC言語のカンマ演算子ではなくjavaのfor文の書式です。
for(i=0,k=10 ; i<k ; i++,k--){...

5.2.3 do while文

繰り返しの文を実行後条件判定をする場合の構文です。

do 文; while(条件式);

あるいは

do {文1;文2;...} while(条件式);

while文やfor文は繰り返しの文を実行する前に条件判定を行うのに対してこの構文は繰り返しの文の後で条件を判定します。

5.2.4 break文

繰り返しの構文から脱出する命令で基本的にはC言語と同じですが、ラベルを使うことで入れ子の繰り返し構文から一度に抜け出すことも可能です。

.....
loop://ラベルの宣言、直後のfor文を指す名前loopを宣言している
for(int i=0;i<10;i++){
    for(int j=0;j<10;j++){
        ....
        if(error)break loop;//ラベルで示された繰り返し構文から脱出し文Aに移動
        ....
    }
    ....
}
文A;
...
 

5.2.5 continue文

これはループからの脱出ではなくて、whileやdo while文なら次の処理を条件式へ移す命令です。for文の場合は再設定式へ処理を移します。こちらもbreak文と同様にラベル名を使うことが可能です。

[目次]

5.3 例外処理

プログラムの実行中に例外的な状況になってプログラムの実行順番を変えたい場合が在ります。しかし、例外が起きる可能性のあるところに、いちいち条件分岐のプログラムを書くと、プログラムの流れがとても解りにくくなります。めったに使われることの無い、プログラムの本流ではない処理が頻繁にプログラムの中に出てくると、本来の流れが把握できなくなるのです。さらに、例外に対応するには関数呼び出しを遡って処理する必要が出てきたりしますから大変です。

C言語のプログラムであれば、例外が起きるところでは例外の有無をチェックして処理部へgoto文で跳ぶ形のプログラムを書くことになるでしょう。しかしgotoでは自由度が在りすぎて例外処理のパターンが定まりません。そこで、java言語には例外処理の手順が構文として用意されています。

java言語の例外処理では指定された範囲で例外が起きたら決められた場所に飛ぶ構文が用意されました。tryとcatchの構文です。tryのブロック内で例外が起きたらcatchブロックへ抜け出します。catchでは処理できる例外の種類を引数で示します。 

下の模式図のように例外が起きなければtryブロックを実行するだけでcatchブロックは実行されません。しかし、tryのブロック内で例外が起きると直後のcatchブロックから対応するものへ処理が飛び、catchブロックの処理終了でtry-catch構文を抜けます。例外が2種類あれば下記のように2つのcatchブロックを書きます。

1) 例外の起きる場所は1か所とは限りません。そこで例外が起きたら例外インスタンスを生成し例外の情報を記録してcatchブロックに飛ぶ仕組みになっています。catchの後の( )で囲われた部分はこの例外インスタンスを参照する変数を示す部分です。関数の引数と同じような表現になっています。例外処理に必要な情報はこの例外インスタンスから得ることができます。

2) 例外の種類も一つとは限りません。例外の種類は例外インスタンスの型(クラス)で区別します。catchの後の( )内に書かれた変数型と例外インスタンスの型が一致するcatchブロックが例外に対応する処理として実行されます。 catchは例外の型に応じて複数書くことができます。

5.3.1 例外を投げる

java言語では例外処理に抜け出すために例外(Exception)投げ(throw)ます。 

例外を投げるには、まず例外インスタンスを作らなければいけません。例外インスタンスはExceptionクラス、あるいはExceptionを継承したクラスのインスタンスです。次に、このインスタンスをthrowで投げると例外が発生する仕組みになっています。

....
if(例外が発生したか?){
    Excetption ex;
    ex=new Exception("何かメッセージがあればここに");
    throw ex;
}
....
//もう少し簡潔に書くことにすれば
if(例外が発生したか?)throw new Exception("何かのメッセージ");
....

投げた例外をメソッド(関数)の中で処理せずに、メソッドを呼び出した側に投げ上げることが可能です。

この場合はメソッドの定義で、例外を投げることを明記する必要があります。例外が発生するとメソッドの途中から脱出して呼び出し側のプログラムに例外を投げます。doSomthingメソッドがException型の例外を投げるかもしれないときは次のようにメソッドの頭部でthrowsで投げる例外を明記します。

※数種類の例外を投げる可能性がある関数ではthrowsの後にカンマ区切りで複数の例外のクラスを記述します。

static public double doSomthing(double x) throws Exception
{
    if(x<0)throw new Exception("負の数の平方根は計算できない");//メッセージ付きのExceptionを投げる
    return Math.sqrt(x);
}

もし上の関数doSomthingを次の関数function1が呼んでいる場合、function1は渡された例外を自分で処理するか、さらにfunction1を呼んでいる関数に投げるかのいずれかの処理を行 う必要があります。自分で処理しない場合は次のプログラムの様になります。この場合はdoSomthingが投げた例外をそのままfunction1を 呼んでいる関数に投げます。

static public void function1() throws Exception
{
    for(double x=10;-2<x;x--)
    {  
        double s=doSomthing(x);//doSomthing()で例外発生の可能性あり
        System.out.printf("%f %f%n",x,s);
    }
}

もしmain関数でも次の様に例外を投げてしまえば、プログラムはそこで終了することになります。

static public void main(String args[])throws Exception
{
    function1();
}

★例外を投げる可能性のある関数を呼ぶ場合、投げられた例外を受け取るか、さらに上に例外を渡すかです。どちらかの処理をしないとコンパイルエラーになってしまいます。

例外は関数呼び出しの順番をさかのぼることができます。

public class ThrowsException
{
    static public void main(String args[])throws Exception
    {
        function1();
    }
    //例外を投げる関数は必ず投げる例外の種類を宣言する
    static public void function1() throws Exception
    {
        for(double x=10;-2<x;x--){
            double s=doSomthing(x);//doSomthing()で例外発生の可能性あり
            System.out.printf("%f %f%n",x,s);
        }
    }
    //
    static public double doSomthing(double x) throws Exception
    {
        if(x<0)throw new Exception("負の数の平方根は計算できない");//メッセージ付きのExceptionを投げる
        return Math.sqrt(x);
    }
}
/* 実行結果
10.000000 3.162278
9.000000 3.000000
8.000000 2.828427
7.000000 2.645751
6.000000 2.449490
5.000000 2.236068
4.000000 2.000000
3.000000 1.732051
2.000000 1.414214
1.000000 1.000000
0.000000 0.000000
Exception in thread "main" java.lang.Exception: 負の数の平方根は計算できない
at ThrowsException.doSomthing(ThrowsException.java:18)
at ThrowsException.function1(ThrowsException.java:11)
at ThrowsException.main(ThrowsException.java:5)
*/

finally

finallyはreturnやthrowでメソッドから戻るときに必ずこれだけは実行してほしい処理がある場合に用います。記述は

finally{メソッドから戻る時に実行したい処理プログラム} 

例外を投げて戻る場合でもこのfinally部分は必ず戻る前に実行されます。メソッドを終わるときに後始末が必要な場合に重宝します。

5.3.2 例外を受け取る

例外を受け取る場合、Javaではtry catchの構文を使って捕捉します。 次のページで説明する入出力に用いるライブラリには例外を発生させる関数が多く、この様な関数を使う場合は必ず例外を処理する必要が有ります

try{
        ...
        //ここで例外:Exceptionが発生するとcatch(Exception e)へ処理が跳ぶ
        ...

}catch(Exception e){ //例外がExceptionならここで処理
        e.printStackTrace();//とりあえずこう書いておく
}

例外インスタンスのメソッドprintStackTrace()は簡単な出力フォーマットで、
例外の型、例外メッセージ、例外の発生までの 関数呼び出し経路」を書き出します。

投げられた例外クラス名:例外のメッセージ文字列
	at 例外が発生したメソッド名(ソースファイル名:行番号)
	at 上を呼び出したメソッド名(ソースファイル名:行番号)
	---- 以下同様に例外を受け取ったメソッドまで遡る ----

とりあえずこれで例外が発生するまでのメソッド呼び出しの流れを知ることができます。

例題5

例外を投げるメソッドtest、test2を作りmainから呼び出して発生した例外をmainメソッド内で受けとる。受けとった例外のprintStackTrace()メソッドを呼 んで、例外の種類 と、例外が投げられるまでの関数呼び出しの経路を書き出します。実行結果で例外の発生場所等を確認してください。

/*
ExceptionTest.java 
以下は説明のために行番号を付けていますのでコンパイルできません
*/

01:public class ExceptionTest{
02:        static public void main(String arg[]){
03:                int data[]={-1,0,1};
04:                for(int i=0;i<data.length;i++){
05:                        try{
06:                                test(data[i]);//例外を発生する関数を呼ぶ        
07:                                
08:                        //例外やエラーを分けて捕まえる事が可能  
09:                        }catch(Exception e){
10:                                System.err.println("例外処理");
11:                                e.printStackTrace();
12:                        }catch(Error e){
13:                                System.err.println("エラー処理");
14:                                e.printStackTrace();
15:                                //エラーを捕まえるとも可能
16:                        }
17:                }
18:                System.err.println("\n mainを終了します \n");
19:        }
20:        
21:        static void test(int data) throws Exception//投げる例外を明記
22:        {
23:                if(0<=data)test2(data);
24:                else throw new Exception("DATAが負");
25:        }
26:        
27:        static void test2(int data) throws Exception//Errorはthrowsに書く必要がない
28:        {
29:                if(data==0)throw new Exception("DATAが0");
30:                throw new Error("DATAが正");//例外の他にエラーも投げることが可能
31:        }
32:        
33:}
実行結果を見ると発生した例外、発生した場所、発生したときの関数の呼び出し状況が表示されます。
以下が実行結果
例外処理
java.lang.Exception: DATAが負
        at ExceptionTest.test(ExceptionTest.java:24) 
        at ExceptionTest.main(ExceptionTest.java:6)
これはmain関数内のプログラムの6行目からtestが呼ばれ、そのプログラムの24行目で
 Exception("DATAが負") が投げられたことを示している。

例外処理
java.lang.Exception: DATAが0
        at ExceptionTest.test2(ExceptionTest.java:29) ※main>test>test2と呼んだところで発生
        at ExceptionTest.test(ExceptionTest.java:23)
        at ExceptionTest.main(ExceptionTest.java:6)
エラー処理
java.lang.Error: DATAが正
        at ExceptionTest.test2(ExceptionTest.java:30) main>test>test2と呼んだところで発生
        at ExceptionTest.test(ExceptionTest.java:23)
        at ExceptionTest.main(ExceptionTest.java:6)

 mainを終了します ※エラーを捕まえて処理したのでプログラムは正常終了します

★java言語では実行時エラーが検出されるとErrorクラスのインスタンスを作成して例外と同じように投げます。エラーは例外と違ってtry-catchの構文で処理する義務が有りませんが、try-catch構文で捕まえてエラーを処理を行う事も可能です。

5.3.3 assertion(表明) −−jdk1.4以降の機能です−−

Error(エラー)もthrowで投げる事が可能です。これを利用してプログラム中に実行時条件チェック(assertion:表明)を書き込めます。例えば

if(条件==false)throw new Error("XXXで条件が満たされませんでした...");

をプログラムに挿入してテスト実行すれば、条件が満たされないとプログラムが止まりエラーメッセージで詳しい状況を知ることができます。Errorはcatchの義務が無く、メソッドでthrowsを書く必要もないのでプログラムにErrorを投げる文を挟むことは容易です。

しかし、この書き方では条件チェックをやめるにはソースを元に戻すしかありません。 テスト用と出荷用で2つのソースファイルを管理することにもなってプログラムの更新等で問題が起きるでしょう。

jdk1.4から新しく表明と呼ばれる機能が加えられました。これはAssertionErrorを投げる機能です。実行時の条件チェックに使いますが、エラーなのでいちいちcatchやthrows等の記述を必要としません。また実行時にこの機能をON/OFFでき、既定値はOFFです。

jdk1.4からサポートされる。実行時の条件チェック(assertion)
書式1: assert  ;
書式2: assert  : 式2 ; 

falseのときAssertionErrorを投げる
ここで式2はAssertionErrorの生成に使われる文字列等の値。

コンパイルでは

javac -source 1.4 XXX.java

-source 1.4のオプションが必要で、実行では

java -ea ClassName

 -eaのオプションが必要です。オプション無しか-daなら動作チェックは無効 となる。
コンパイル済みの運用クラスファイルが起動オプションでテストモードで実行できます。

[目次]

5.4 課題4(EditerFrame.javaText.java、初期ファイルP4.java

ファイル入出力を実装したテキストエディターのサンプルです。このプログラムの一部分を写経して完成させてください。

課題2を書き直し、ファイルとの入出力部分を別クラスに切り離したのものです。ソースファイルも3つに分けています。初期ファイルP4.javaEditerFrame.javaText.javaを同じフォルダ内に置いてP4.javaを編集で開いて写経しコンパイルすれば実行可能です。

※ファイルを置くまでのフォルダ名に日本語など倍角の文字を使うのは避けてください。JReport.jarから見つけられないことが在ります。

今回の例外処理構文が使われています。写経するのはgetTextsetTextメソッドのみです。コメントは省いてください。ちょっと長めです。※コメントは間違いのもとになるので写経から省くこと

※字下げは重要なので行の書き出し位置は手本のように必ず下げること。tryとcatchの対応が取れているか確認してください。 IEで見ると手本の字下げが正しく表示されないことがあります。Firefoxで見てください。

レポート送信ではファイルの読み書きを行って、正常に動作することを確認すること(完成品P4.jar
※読み書きテストにP4.javaを使わないでください、書き換えてしまうと不正なファイルになり、元に戻せません。

/*P4.java*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
public class P4
{
    public static void main(String args[]){
        JFrame window=new EditorFrame();
        window.setSize(600,300); 
        window.setVisible(true); 
    }
}
//ファイルを相手にテキストの読み書きができるTextインターフェースを実装したクラス
//入出力関係のライブラリーでは例外を投げるメソッドが多いため try catch の構文が多くなる
class TextFile implements Text
{
    //
    // クラスのメンバーを利用してファイル選択機能を実装
    //
    static private JFileChooser chooser = new JFileChooser();
    static private File chooseFile(boolean createFile)
    {
        File sfile=null;
        synchronized(chooser){//一つのものを使いまわすので同時に2つは開かないように制限
            int ret;
            if(createFile)ret=chooser.showSaveDialog(null);
            else ret=chooser.showOpenDialog(null);
            if(ret!= JFileChooser.APPROVE_OPTION) return null;

            sfile=chooser.getSelectedFile();
            if(sfile==null || sfile.isDirectory())return null;
            //ファイルがまだ作られていないときは新規に作成
            if( ! sfile.exists()){
                try{
                    sfile.createNewFile();
                }catch(IOException e){
                    e.printStackTrace();
                    return null;
                }
            }
            chooser.setSelectedFile(sfile);//次回同じファイルが選択された状況で始めたい
        }
        return sfile;
    }

    //
    //以下はインスタンスのメンバー
    //
    private File file=null;//非公開なのでクラス外からは参照できない
    public String getName()
    {
        if(file!=null)return file.getName();
        else return "TextFile.file=null";
    }
    //===========================ここから===========================
    public String getText()
    {
        if(file==null){
            file=chooseFile(false);
            if(file==null)return null;
        }
        StringBuffer buffer=new StringBuffer();
        BufferedReader input=null;
        try{
            input=new BufferedReader(
                new InputStreamReader(new FileInputStream(file),"JISAutoDetect")
            );
            boolean newLine=false;
            while(input.ready()){
                int c=input.read();
                if(c==-1)break;//ストリームの終端では-1が戻る
                if((char)c=='\r'){ //文字列の改行は\r,\n,\r\nなど複数の基準がある
                    buffer.append("\n");
                    newLine=true;
                }else if((char)c=='\n'){
                    if(newLine)newLine=false;
                    else buffer.append("\n");
                }else{
                    if(newLine)newLine=false;
                    buffer.append((char)c);
                } 
            }
            input.close();input=null;
        }catch(Exception ex){
            //ファイルからのテキストの読み取りで例外が起きたら
            ex.printStackTrace();
            System.out.println("エラー:ファイル["+file.getName()+"]からデータを読めません");
            try{
                //閉じていないストリームは閉じる
                if(input!=null)input.close();
            }catch(Exception e2){
                //閉じることに失敗したら打つ手なし
                e2.printStackTrace();
                System.exit(-1);//java仮想機械を戻り値-1で終了
            }
            return null; 
        }
        System.out.println("getText():OK "+file);
        return buffer.toString();
    }
    
    public boolean setText(String str)
    {
        if(file==null){
            file=chooseFile(true);
            if(file==null)return false;
        }else{
            int ret=JOptionPane.showConfirmDialog(/*引数が長いので改行しています*/
                null,
                "既存ファイルを上書きしますか?\n;実行確認をお願いします",
                "上書きによるクリアの確認",
                JOptionPane.OK_CANCEL_OPTION,
                JOptionPane.WARNING_MESSAGE
                );
            if(ret==JOptionPane.CANCEL_OPTION){
                return false;
            }
        }
        PrintWriter output=null;
        ByteArrayInputStream raw_input=null;
        BufferedReader input=null;
        try{
            //改行コードが異なるために少し面倒な処理になっている
            output=
                new PrintWriter(new OutputStreamWriter(new FileOutputStream(file),"Windows-31J"));
            raw_input=new ByteArrayInputStream(str.getBytes());
            input=new BufferedReader(new InputStreamReader(raw_input));
            while(input.ready()){
                int n=input.read();
                if(n==-1)break;//ストリームの終端では-1が戻る
                if((char)n=='\n'){//文字列の改行はjavaでは\nだが
                    output.print("\r\n");//Windowsのテキストでは改行は\r\n
                }else{
                    output.write(n);
                }
            }
            input.close();input=null;
            raw_input.close();raw_input=null;
            output.close();output=null;
        }catch(Exception ex){
            //テキストのファイルへの書き込みで例外が起きたら
            ex.printStackTrace();
            System.out.println("エラー:ファイル["+file.getName()+"]へデータを保存できません");
            try{
                //閉じていないストリームはすべて閉じる
                if(input!=null)input.close();
                if(raw_input!=null)raw_input.close();
                if(output!=null)output.close();
            }catch(Exception e2){
                //閉じることに失敗したら打つ手なし
                e2.printStackTrace();
                System.exit(-1);//java仮想機械を戻り値-1で終了
            }
            return false;
        }
        System.out.println("setText():OK "+file);
        return true;
    }
    //=====================ここまで========================
}

[ prev | next | index ]