- PR -

JAVA言語の作法について

投稿者投稿内容
kipple
会議室デビュー日: 2005/09/20
投稿数: 6
投稿日時: 2005-09-20 23:42
返信遅くなってしまい申し訳ありません。
帰宅後修正方法を考えてたらこんな時間になってしまいました・・

>kuma 様
なるほど、ファイルの読み込みと書き込みを分断するということですね。
今回、改行処理の実装方法も変えました(java.io.BufferedWriter.newLine)。
BufferedWriterとStringBufferの結合方法がよくわからなかったため前のロジックのままとさせてもらいました。
勉強不足で申し訳ありません。
行単位処理が不要な際は是非参考にさせて頂きます。

>さる 様
参考リンクありがとうございます。
例外の発生しそうなときにtry-catchすればいいというように読み取れました。
(検討違いだったらすいません・・)
入れ子にならないように修正してみたのでご確認していただければ幸いです。

コード:
public int extractFile() throws IOException {
	BufferedReader breader;
	BufferedWriter bwriter;
	int rc;
	try{
		breader = new BufferedReader(new FileReader(inputFileName));
	}
	catch(FileNotFoundException e){//inputFileNameオープン時の例外
		System.err.println(e);
		return -1;
	}
	try{
		bwriter = new BufferedWriter(new FileWriter(outputFileName));
	}
	catch(IOException e){//outputFileNameオープン時の例外
		System.err.println(e);
		breader.close();
		return -1;
	}		
	boolean mode = false;//出力制御フラグ
	String s = new String();
	try{
		while ((s = breader.readLine()) != null) {//EOFまで読み込み
			if (mode) {//書き込みモードか?
				bwriter.write(s);
				bwriter.newLine();
				if (p2.matcher(s).find()) {//終了文字列にマッチ
					mode = false;
				}
				continue;
			}
			if (p1.matcher(s).find()) {//開始文字列にマッチ
				bwriter.write(s);
				bwriter.newLine();
				mode = true;
			}
		}
		rc = 0;
	}catch(IOException e){//読み込みもしくは書き込み時の例外
		System.err.println(e);
		rc = -1;
	}finally{
		bwriter.close();
		breader.close();
	}
	return rc;
}

武澤
常連さん
会議室デビュー日: 2004/09/27
投稿数: 31
投稿日時: 2005-09-21 00:04
そもそも作法って「オブジェクト指向言語ならこう書くべきだ!!」とか
「そんな書き方では実用に耐えられない」など色々あると思いますので、
どう書くべきなのか?は自分でも良くわかりませんが、
とりあえず、気になったところを。

もしかして、try-catch句のcatchは一つしか書けないと思っていませんか?
下記のようにtry句に対して複数のcatch句を定義できますよ。
これで少し見栄えが良くなりますよ。
※後は例外の継承関係を意識してcatchする例外の順番を考えて・・・。

try {
......
}
catch (FileNotFoundException e) {
......
}
catch (IOException e) {
......
}
c9katayama
常連さん
会議室デビュー日: 2003/02/04
投稿数: 38
投稿日時: 2005-09-21 00:16
細かい話ですが、int rcの宣言は不要です。
tryブロックでrc = 0としている所とcatchブロックでrc=-1としている所、
これはreturn 0 と return -1にそれぞれ置き換えられます。
finallyブロックは、tryおよびcatch節から抜ける時に実行されるので、
ブロック中でreturnしてしまってもちゃんと動作します。
あと、エラーコードを返す仕様なのであれば、0や-1はstatic finalの
定数宣言にすると良いと思います。
public static final int SUCCESS = 0;
とかですね。

またString s = new String()の部分は、その下のtryブロックに
いれたほうがいいでしょう。tryブロックに入れる事でスコープが1段階縮まります。
また変数名もsではなくlineなどにして、初期化はしないかもしくはnullがいいでしょう。
もちろんこのコードではtryブロックの外でも中でも動きに変わりはないですが、
極力スコープを縮める習慣をつけておくと、後々役に立つと思います。(forループに
すればもう一段縮まりますが、そこは読みやすさとのトレードオフで。)

参考になれば幸いです。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2005-09-21 00:40
引用:
kumaさんの書き込み (2005-09-20 20:12) より:
どうせなら
breader.readLine()
をStringBufferに溜め込んでwhileを抜けた後、一気に書き出すようにしたほうが
Exceptionの個所も判別つき易くなってよくないですか?



ストリーム上で処理を完結できるのに、全体をメモリ上に展開するのはあまり
よろしくないのではないでしょうか。特に連続メモリとなる場合は危険です。
基本的にストリームの長さを仮定するのはよろしくないかと。

#編集された部分がこのあたりだったらごめんなさいです。
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-09-21 01:41
なんで、メソッドが IOException を投げるように定義( throws IOException )されているの? 主要部分では IOException を握りつぶして -1 のリターンコードに置き換えてしまっているようだけど? finally 節の .close() が IOException を投げる可能性があるけど、そのために throws IOException を付けているんですか?

なんか気持ち悪いコードですね。従来の C っぽいコードを書くなら finally 節でも .close() の IOException を握りつぶして -1 を返すようにするべきだと思うし、ちゃんと Java らしいコードを書くなら、IOExceptio をメソッド内でキャッチする必要はない。(extractFile() の権限においてエラーハンドリング・復帰処理ができないのであれば、せっかくの例外を 成否 というビット情報に減らしてしまうのはもったいない。

public void extractFile() throws IOException

として、-1 に変換するだけの握り潰しキャッチははずすべきじゃないかな?
さる
ぬし
会議室デビュー日: 2005/07/14
投稿数: 276
お住まい・勤務地: 実家戻ったw
投稿日時: 2005-09-21 01:53
引用:

kippleさんの書き込み (2005-09-20 23:42) より:
参考リンクありがとうございます。
例外の発生しそうなときにtry-catchすればいいというように読み取れました。
(検討違いだったらすいません・・)
入れ子にならないように修正してみたのでご確認していただければ幸いです。



それだけではないんですけどねw
みなさん色々教えてくれてますから参考にして下さい。
色々な人が色々な考え方で手助けしてくれてますねぇ〜。
kipple
会議室デビュー日: 2005/09/20
投稿数: 6
投稿日時: 2005-09-21 02:05
>武澤 様
自分の中での作法とは、不要なことを考えずにプログラミングできる、定石のようなものだと考えています。みなさんのご指摘はそれぞれ意味があり、非常に参考になります。まだ考えないと組むことができませんが、いずれは無意識のうちにできるようになればと思います。
try-catch句ですが、一度そのように組んでみたのですが、
The local variable bwriter may not have been initialized
と初期化されていない可能性があるエラーがでてしまい、実行できません・・
また、Nullで初期化したところストリームのClose時にNullPointerExceptionが発生してしまいます。自分の考え方がおかしいのでしょうか・・

c95029 様
rc不要は目から鱗でした。
てっきりreturnしてしまうとfinallyブロックも実行されないと勘違いしておりました。
基礎知識が足りないことを再認識いたしました。
定数宣言もメンテナンス性、可読性を考えるとたしかにそのとおりですね。定数はstatic final宣言するように心掛けます。
スコープについてはこれから勉強させて頂きます。メンテする際、変更箇所だけに絞って変更できるようにする、という認識でよろしいでしょうか?

未記入 様
手探り状態でコーディングしているため、一貫性が損なわれてしまっていました。
お見苦しいコードで大変申し訳ありません。
確かにこれだとクライアントは0、および-1の判断と例外処理も行わないといけないですね。
自分の目指すところはおっしゃるJavaらしいコードなので、ご意見参考にさせて頂きます。本当にありがとうございます。
ただ、ストリームのクローズはこのメソッド内でやらないといけないので、その点ふまえて変更させて頂きました。

コード:
public void extractFile() throws IOException {
	BufferedReader reader;
	BufferedWriter writer;
	try{
		reader = new BufferedReader(new FileReader(inputFileName));
	}
	catch(FileNotFoundException e){//inputFileNameオープン時の例外
		throw e;
	}
	try{
		writer = new BufferedWriter(new FileWriter(outputFileName));
	}
	catch(IOException e){//outputFileNameオープン時の例外
		reader.close();
		throw e;
	}		
	try{
		boolean isToWrite = false;//書き出すべきか?
		String line;
		while ((line = reader.readLine()) != null) {//EOFまで読み込み
			if (isToWrite) {//書き込みモードか?
				writer.write(line);
				writer.newLine();
				if (p2.matcher(line).find()) {//終了文字列にマッチ
					isToWrite = false;
				}
				continue;
			}
			if (p1.matcher(line).find()) {//開始文字列にマッチ
				writer.write(line);
				writer.newLine();
				isToWrite = true;
			}
		}
	}catch(IOException e){//読み込みもしくは書き込み時の例外
		throw e;
	}finally{
		writer.close();
		reader.close();
	}
}

kipple
会議室デビュー日: 2005/09/20
投稿数: 6
投稿日時: 2005-09-21 02:12
>さる 様
ホントにいろんな方からのご指摘、ご指導、ありがたいです。
こんなに沢山返答がくるとは思っていなかったので、
びっくりの反面大変嬉しく思います。
いつの日かここでフィードバックできるように頑張っていきますので今後とも宜しくお願いします。

スキルアップ/キャリアアップ(JOB@IT)