Javaプログラムを作成しています.
標準入力で入力された文字列を表示し,exitが入力されるまで繰り返すプログラムです.
エラーが出ますが,対策方法がわかりません.
ソースコード,実行結果,エラーは以下の通りです.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {

/**
* @param args
*/
public static void main(String[] args) {

System.out.println("Program starts.");
while (true) {
String input = null;

input = getInputLine();
System.out.println("echo:" + input);

if (input.equals("exit")) {
break;
}
}
System.out.println("Program exits.");
}

private static String getInputLine() {
String input = null;
BufferedReader br = null;

try {
br = new BufferedReader(new InputStreamReader(System.in));
input = br.readLine();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

return input;
}

}


Program starts.
test
echo:test
echo:null
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:145)
at java.io.BufferedInputStream.read(BufferedInputStream.java:308)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at kadai1.Test.getInputLine(Test.java:34)
at kadai1.Test.main(Test.java:18)
Exception in thread "main" java.lang.NullPointerException
at kadai1.Test.main(Test.java:21)

このQ&Aに関連する最新のQ&A

A 回答 (2件)

getInputLineメソッド中に br.close(); という箇所があるのですが、マズイです。

実行開始して1回目の br.readLine(); は上手く実行されるのですが、その後、br.close(); にて標準入力である System.in までリソースを開放してしまいます。そして2回目に br.readLine() が実行されると、標準入力に関連した静的なSystem.inが既に開放されてしまっているので、例外処理となります。
標準入力はJavaアプリケーションを実行した時点で暗黙のうちに静的(static)に生成されます。mainメソッドと同様です。それをclose()にて開放してしまうのが原因です。BufferedReaderとInputStreamReaderは2回目以降もオブジェクトが作成されますが、System.inは一旦開放されるとダメっす。

手直ししましたので、ご参考まで。
--------------------------
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class TestBuf {

/**
* @param args
*/
static BufferedReader br = null;

public static void main(String[] args) {

br = new BufferedReader(new InputStreamReader(System.in));

System.out.println("Program starts.");
while (true) {
String input = null;

input = getInputLine();
System.out.println("echo:" + input);

if (input.equals("exit")) {
break;
}
}
System.out.println("Program exits.");

try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

private static String getInputLine() {
String input = null;

try {
input = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}

return input;
}

}
--------------------------
余談ですが、JDK6(1.6)から、キーボード入力を簡単にできます。
private static String getInputLine() {
return System.console().readLine();
}
ご参考まで。
    • good
    • 0
この回答へのお礼

System.inがstaticのことや,br.closeで一緒にリソース開放されるとは
知りませんでした.ご指摘,手直しありがとうございました.

お礼日時:2009/05/16 17:07

標準入力の「System.in」をcloseしちゃってたりしませんか?

    • good
    • 0
この回答へのお礼

しているつもりはありませんでしたが,
br.closeによって間接的にしちゃってました・・・.

お礼日時:2009/05/16 17:08

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QIOException ってどういうときに起こるのでしょうか?

IOException ってどういうときに起こるのでしょうか?

http://www.atmarkit.co.jp/fjava/rensai2/javaent12/javaent12.html
を見て勉強しています。

  catch ( IOException e) {
    System.out.println( "キーボードが故障しているのかもしれません" );
  }

と書いてあります。
ハード(キーボード)が故障しているのを Java のプログラムのレベル(ソフトウェア)で感知できるというのがよくわかりません。「

NumberFormatException の方はわかるのですが・・・

Aベストアンサー

現実的には、キーボードからの入力でIOExceptionが発生することは、
ほとんどあり得ないと思います。
そもそも、キーボードが故障していたとしても、
IOExceptionは投げられないでしょう。
「キーボードが故障しているのかもしれません」というのは、
その記事の著者が冗談で書いたのだと思います。

ではなぜ、try-catchを書かなくてはいけないのか?
InputStreamやBufferedReaderは、
データ入力を抽象化したものだからです。
実際の入力元はキーボードだったり、ファイルだったり、
ネットワーク接続だったりするわけですけど、
InputStreamは、その入力元の情報を持っていないので、
データを読み取る際は常に
IOExceptionをキャッチするコードを書かなくてはいけません。
たとえ、絶対にIOエラーが発生しないストリームだとしても。

さらに付け加えるなら、
そもそも「標準入力=キーボード」であるとは限りません。
(一般的にはキーボードであることが多いですが。)
Javaでは、
System.setIn(InputStream)
を呼び出して、標準入力を変えてしまうことができますし、
標準入力を指定してプログラムを実行することができるOSもあります。

追伸1:
例外をキャッチしたときは、
スタックトレースをプリントすることをおすすめします。
catch (IOException e) {
e.printStackTrace();
}

追伸2:
そのプログラムでIOExceptionを発生させる最も簡単な方法は、
readLine()を呼び出す前に
標準入力(System.in)を閉じてしまうことです。
System.in.close();

現実的には、キーボードからの入力でIOExceptionが発生することは、
ほとんどあり得ないと思います。
そもそも、キーボードが故障していたとしても、
IOExceptionは投げられないでしょう。
「キーボードが故障しているのかもしれません」というのは、
その記事の著者が冗談で書いたのだと思います。

ではなぜ、try-catchを書かなくてはいけないのか?
InputStreamやBufferedReaderは、
データ入力を抽象化したものだからです。
実際の入力元はキーボードだったり、ファイルだったり、
ネットワーク接...続きを読む

Qflush()とclose()について

Javaを独習Javaで独習しています。現在、入出力の所まできたのですが、Writerクラスのclose()とflush()の違いがわかりません。それぞれのメソッドの意味はわかるのですがそれらを使う目的がわかりません。flush()は「バッファ付けデータをそのストリームで表されている物理デバイスに書き込む」とあるのですが、サンプルには(バッファ付け文字ストリームの単元にも)flush()は一度も出てこずclose()のみで書き込みが行われています。探したのですが独習Javaのサンプルの中には結局flush()は一度も出てきませんでした。この二つの違いはなんなのでしょうか?初心者のためわかりにくい質問かとは思いますがよろしくお願いします。

Aベストアンサー

フラッシュすれば、ファイルやその他物理デバイスに強制的にバッファの内容が出力されるということは、理解されていると考えてよいですね?

で、なかなかストリームをクローズできない(またはしない)場合には、いつまで経ってもバッファの内容が物理デバイスに出力されないかも知れませんよね?でも、適当なタイミングで定期的にフラッシュすれば、その時点でバッファに溜まっている内容が物理デバイスに出力されます。

そのサンプルの場合は、書き出してすぐ?クローズしちゃうため、明示的なフラッシュは必要なかったんだと思いますが、

・フラッシュは、(ストリームを閉じずに)バッファの内容を強制的に物理デバイスに出力する。
・クローズは、(フラッシュされていなければフラッシュしてから)そのストリームを閉じる。

とまぁ、目的も内容も全然違うわけです。

Qシンボルが見つかりませんというエラーが理解できません。

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Image[3];
Thread t;
int index1 = 0;
int index2 = 0;
String msg = "";
String msg1 = "";

boolean state = false;
Button b1 = new Button("ぐー");
Button b2 = new Button("ちょき");
Button b3 = new Button("ぱー");

public void init(){
for(int i = 0; i<=2; i++){
img[i] = getImage(getDocumentBase(),"hanabi" + (i+1) + ".JPG");
}
add(b1);
add(b2);
add(b3);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
msg1 = "結果は・・";

}

public void paint(Graphics g){
g.drawImage(img[index1],350,30,this);
g.drawImage(img[index2],695,30,this);
g.drawString("コンピューター",420,300);
g.drawString("あなた",800,300);
g.drawString(msg,630,320);
g.drawString(msg1,550,320);
}

public void start(){
state = true;
t = new Thread(this);
t.start();

}

public void run(){
while(state){
index1++;
if(index1 == 3){
index1 = 0;
}
index2++;
if(index2 == 3){
index2 = 0;
}
repaint();
try {
Thread.sleep(60);
}catch(InterruptedException e) { }
}
}

public void actionPerformed(ActionEvent e){
if(state == false) {
start();
return;

}
state = false;
if(e.getSource() == b1) {
msg = "ぐー";
index2 = 0;
}

else if(e.getSource() == b2){
msg = "ちょき";
index2 = 1;
}

else if(e.getSource() == b3){
msg = "ぱー";
index2 = 2;
}
check();
repaint();
}

public void check() {
if(index1 == index2) msg ="あいこ";


else if (index1 == 0) {
if(index2 == 2) msg="あなたの勝ち";
else msg ="あなたの負け";
}

else if(index1 == 1) {
if(index2 == 0) msg="あなたの勝ち";
else msg="あなたの負け";
}

else if(index1 == 2) {
if(index2 == 1) msg="あなたの勝ち";
else msg="あなたの負け";
}

}
}

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Imag...続きを読む

Aベストアンサー

「シンボルを見つけられません。」というエラーの下に何か表示がありませんでしたか?そこにヒントがあると考えられます。
シンボルを見つけられませんといエラーが表示される主な理由は4つあります。
(1)クラス、メソッド、変数などの綴りミスや定義していない変数を使用している可能性がある。
(2)コンストラクタを呼び出すときに、newを忘れている可能性がある。(3)公開されていないメンバーを呼び出している可能性がある。
(4)必要なimport文を記述し忘れている可能性がある。
ここでのあなたのエラーは(1)番ではないでしょうか?上記ではimageとなっている変数がimgになっていますね。
これはエラー表示をよく見ることで意外と簡単に解決できるのです。
ゆっくり丁寧にエラー表示を見るように心がけることが大事ですよ。

Qprivate static という変数の修飾

お世話になります。

private static final String HOGE = "hoge";

という変数(finalなので定数ですが)があるとします。このような、privateでstaticな変数というのは、どのような使われ方を意図しているのでしょうか?privateな変数がstaticである必要は、どのようなときに生じるのでしょうか?

よろしくご教授ください。

Aベストアンサー

 その private な変数が所属するクラス自身がいくつも定義された場合に、プログラム全体で1つのメモリしか確保されなくなります。
 なんで、メモリ量がものすげー切羽詰ってるときとか、ほんの数バイトでも節約した方がいい気がするときに有効です。

QJAVA  ArrayListからArrayListへのコピー

java で、ArrayListからArrayListへコピーはできるのでしょうか?
clone()というメソッドがありましたが、よくわからず、コピーできてないようなので伺いました。

ベーシックではできるようですが、JAVAでもできるのでしょうか?
どなたか教えていただけませんでしょうか?

Aベストアンサー

ArrayList li = new ArrayList(list);
でよいでのでは?

Qequalsの逆

javaで、文字列の場合は比較演算子の「==」は用いずに

if ((str1.getText()).equals(str2)){
(※…str1,2は文字列)

と書きますよね?
この逆で、文字列str1とstr2は等しくないとき、にはif以下の条件文をどのように書けばよいでしょうか?

Aベストアンサー

>if !((str1.getText()).equals(str2)){

あくまで
if(){
}


!(str1.getText()).equals(str2)
が入っているので
if !((str1.getText()).equals(str2)){
じゃなくて
if (!(str1.getText()).equals(str2)){
こう。

Qcsvファイルを2次元配列に格納

Javaの勉強をしています。
csvファイルを読み込んで2次元配列に格納する方法を教えて下さい。
1次元の配列なら下記のようにして出来たのですが、2次元の配列に格納する方法が分かりません。

------------------------------
try {
File csv = new File("xxx.csv");
BufferedReader brf = new BufferedReader(new FileReader(csv));
while(brf.ready()) {
String line = brf.readLine();
String[] data = line.split(",");
for(int j=0; j<data.length; j++) {
System.out.print(data[j] + "\t");
}
System.out.println();
}
brf.close();
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
---------------------------
一度はできないのかと思い、上記の1次元配列のdata[j]を2次元配列のarray[i][j]に代入してみたのですが出来ませんでした。
回答宜しくお願い致します。

Javaの勉強をしています。
csvファイルを読み込んで2次元配列に格納する方法を教えて下さい。
1次元の配列なら下記のようにして出来たのですが、2次元の配列に格納する方法が分かりません。

------------------------------
try {
File csv = new File("xxx.csv");
BufferedReader brf = new BufferedReader(new FileReader(csv));
while(brf.ready()) {
String line = brf.readLine();
String[] data = line.split(",");
for(int j=0; j<data.length; j++) {
System.out.pr...続きを読む

Aベストアンサー

#1です。

> ファイル全体の行数はファイルを読み終わってからでないとわからないのですが、その場合どうすればよいのでしょう??

#2の方が書いておられるように、ArrayListなど適当なコレクションクラスにファイルを読み込み、行数が分かってから配列をnewすればいいでしょう。

import java.util.ArrayList;

ArrayList<String[]> al = new ArrayList<String[]>();
while (...) {
String line = brf.readLine();
al.add(line.split(",")); /* ArrayListへ読み込み */
}

String[][] array = new String[al.size()][];
for (i = 0; i < al.size(); i++) {
array[i] = al.get(i); /* ArrayListから配列へ */
}

勉強頑張ってください。

QSystem.inをClose()すると例外が発生する。

こんにちは、tokopokoといいます。

■次のプログラムを実行すると、エラーになります。
なぜエラーになるのか、ご存知の方はいらっしゃいませんか。

import java.io.*;

class TestInput {
public static void main(String[] args) {
System.out.println("first = \"" + getInputValue("first?") + "\"");
System.out.println("second = \"" + getInputValue("second?") + "\"");
}

public static String getInputValue(String message) {
String returnString = "";
System.out.print(message);
BufferedReader input = null;
try {
input = new BufferedReader(new InputStreamReader(System.in));
returnString = input.readLine();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return returnString;
}
}

■実行例
D:\>javac TestInput.java

D:\>java TestInput
first?100
first = "100"
second?java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:145
)
at java.io.BufferedInputStream.read(BufferedInputStream.java:308)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at TestInput.getInputValue(TestInput.java:14)
at TestInput.main(TestInput.java:5)
second = ""

■私の環境は以下の通りです。
OS: Microsoft Windows XP Professional SP2
java: java version "1.6.0_03"

こんにちは、tokopokoといいます。

■次のプログラムを実行すると、エラーになります。
なぜエラーになるのか、ご存知の方はいらっしゃいませんか。

import java.io.*;

class TestInput {
public static void main(String[] args) {
System.out.println("first = \"" + getInputValue("first?") + "\"");
System.out.println("second = \"" + getInputValue("second?") + "\"");
}

public static String getInputValue(String message) {
String returnStri...続きを読む

Aベストアンサー

メソッドの最初の呼び出しでSystem.inをclose()したので、それを再openしないかぎり次以降の呼び出しはIOExceptionになります。われわれ一般のプログラマがSystem.inを再生成/再オープンすることはできないので、close()しないほうがいいですね。

QCSVファイルの特定の行だけを読み込みたいです。

例えば以下のようなCSV形式のデータが10000行あるとします。
 1,10,15,3
 2,1,5,1
 70,2,4,2
 2,4,5,6
 11,1,9,9
 ・・・

上記ファイルから、例えば9999行目を取得したい場合、
現在は以下のような手順で9998行をループで読み込んでから、
9999行目を取得しています。(エラー処理などは省いています)
 BufferedReader br = new BufferedReader(new FileReader("hoge.csv"));
 for( int i=0; i<9998; i++ ){ br.readLine(); }
 System.out.println("9999行目="+br.readLine());

ただし、上記の通りループを9998回まわし、
データを1行ずつ読み込むのは非常に効率が悪いです。
できれば、br.readLine(9999); といった感じで行数を直接指定できる方法があるならば、
無駄な処理を省けて見栄えも速度も良くなると思うのですが、
Javaの標準のクラスではこういったことは可能なのでしょうか?

私なりに調べてみたのですが調べ方が悪いのか知識が及ばないため、
こちらで質問させていただきました。
もしご存知の方がおられましたらアドバイスいただけますと助かります。
よろしくお願いします。

例えば以下のようなCSV形式のデータが10000行あるとします。
 1,10,15,3
 2,1,5,1
 70,2,4,2
 2,4,5,6
 11,1,9,9
 ・・・

上記ファイルから、例えば9999行目を取得したい場合、
現在は以下のような手順で9998行をループで読み込んでから、
9999行目を取得しています。(エラー処理などは省いています)
 BufferedReader br = new BufferedReader(new FileReader("hoge.csv"));
 for( int i=0; i<9998; i++ ){ br.readLine(); }
 System.out.println("9999行目="+br.readLine());

ただし、上記の通りル...続きを読む

Aベストアンサー

Javaはしばらくいじってないのであれですが・・・

仮にreadline(9999)というような関数があるとしても内部的には
for(int i=0;i<9998);i++){
br.readline()
}
と同じことをしていて スペック的にはほとんど変わらないはずです。
9999行目を読み込むためには 1行目から順に最初からファイルを読んでいって改行の数を数えてやる必要があるので・・・


見栄えがというのであれば自分でBufferedReader を継承して独自のクラスを作ってしまったらいかがでしょう?
readline(int line)だけ書いてやるだけだから5分とかからないし・・・


なおJavaは最近いじってないので標準関数でご希望のものがあるかはわかりませんが
自分だったらそんなことで悩んでる暇があったら自分で書いちゃいます。

QJavaで改行などが出来ないのです。

 Java の事で質問です。 
 

 System.out.println("このようにしても\n");

 改行できません。
 
 このようにしても\n   

 と表示されてしまいます。どうしてでしょう。ちなみにOSはMacOS9.1です。なにか関係があるのでしょうか?

Aベストアンサー

> class amigo{
> public static void main(String args[]) {
> System.out.print("aaaaaaaa");
> System.getProperty("line.separator");
> System.out.print("bbbbbbbb");
> }
> }
> のような使い方でしょうか?

String line_sep = System.getProperty("line.separator");
System.out.println("あいうえお" + line_sep + "かきくけこ");

こうです。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報