Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

多次元配列 〜一覧の行数値

お世話になります。
お暇な時で結構ですので、ご回答頂ければ幸いです。

1.一覧の取得(列数は固定値5,行数は200〜300程度)
※1.AUキー(数値) 2.ファイル名(文字列) 3.AUキー(数値) 4.DUキー(数値) 5.メモ(文字列)

2.必要な列は2,3,4です。1と5は必要ありません。

3.一覧の行数の取得

4.取得した一覧を2次元配列に格納していく。

5.条件文で、階層構造を作成する。

というような流れをイメージしているのですが、
とりあえず、4までをやってみました。
その結果NullPointerExceptionが発生します。

一覧取得→2次元配列格納処理がぬるってるので、
出力処理の箇所でぬるぽがでるのかと思うのです。

brは2回呼び出せないのでしょうか。
一度読み込むと、空っぽになるのでしょうか。

どうすれば、回避できるかご教示ください。
もしくは、行数の取得方法を変更する事で解決できるのでしょうか?

以下ソース
import java.io.*;

class Test{
    public static void main(String args[]){
        
        BufferedReader br = null;
        String tmp = null;
        String[] arr = null;
        String[][] array = null;
        StringBuilder sb = new StringBuilder();
        int x = 0;
        
        try{
            br = new BufferedReader(new InputStreamReader(new FileInputStream("test.csv")));
            
            //row取得
            while((tmp=br.readLine())!=null){x++;}
            
            //一覧取得→2次元配列格納処理
            for(int i=0;(tmp=br.readLine())!=null;i++){
                arr = tmp.split(",");
                for(int j=0;j<arr.length;j++){
                    array = new String[x][];
                    array[i][j] = (sb.append(arr[j] + "\r\n")).toString();
                }
            }
            
            //出力処理・・・・ぬるぽ(;;)
            for(String[] s : array){
                for(String ss : s){
                    System.out.println(ss);
                }
            }
            
        }catch(IOException e){e.printStackTrace();
        }finally{
            try{
                br.close();
            }catch(IOException e){e.printStackTrace();}
        }
    }
}

よろしくお願い致します。

21

回答

8231

閲覧

21件の回答

評価

0

>array = new String[x][];
なんで毎回二次元配列を作ってるの?

評価

0

申し訳ありません。
外に出してみましたが、以前NullPoがでます。

評価

0

この x は、「x行目」の意味か?

そんなら、右側じゃなくて左側で指定するべきものでしょ。

評価

0

array = new String[x][]の箇所ですか?
array = new String[][x]とするのでしょうか?

評価

0

全然違う。

array[]を初期化してるのはどこよ。


主題とは関係ないけど

>sb.append(arr[j] + "\r\n")

これ最悪。StringBuilder使ってる意味ない。

評価

0

おっと、これは俺の勘違いか。失礼。m(_ _;m

つか、んなこと、ループの一番底でやるんじゃないよ。
ループの外でやれ。xが確定した直後がいいよ。

>一度読み込むと、空っぽになるのでしょうか。

配列を作って値を格納して、
さらに、新しい配列を作って値を格納して・・・

って、どんどん上書きしているのが原因だ。

・・・$氏の指摘そのまんまだな。

p.s.
行はともかく、列の配列を宣言しているところが見あたらないが、
実行時エラーにはならんの?

評価

0

解決ではないのですが、参考になりそうなページがありました
http://aostlab.blogspot.com/2010/08/bufferedreader.html

BufferedReaderは2回使わない方が良いようです。

評価

0

>brは2回呼び出せないのでしょうか。
>一度読み込むと、空っぽになるのでしょうか。

前の質問スレッドでAPIドキュメントの話が出たんだからそれはもちろん調べたんですよね?

http://java.sun.com/javase/ja/6/docs/ja/api/java/io/BufferedReader.html#readLine%28%29

戻り値のところに、
>ストリームの終わりに達している場合は null 

って書いてありますよ。
#終わりに達しちゃったなら最初に戻せばいいんじゃない?と思いますが。

評価

0

こっちの方がいいかな。

誤)行はともかく、列の配列を宣言

正)行方向はともかく、列方向の配列を宣言

評価

0

それと、行数が分からない場合は無理に配列を使わないで、Listを使うんだよ。

評価

0

あれ、ループにも入ってなかったのか。(汗
なので、実行時エラーにはならなかったと。

原因と書いたのは、今回のエラーについてはパスね。
でも、このままじゃ(ry

評価

0

Listを使う事は調べていて薄々感づいていたのですが、
まだ勉強していないのです。

APIドキュメントもダウンロードして、常にみるようにしております。null到達後の再利用はreset()を使うのでしょうか?それとも一旦close()して新たに定義しなおすのでしょうか。難しいですね。

Listを使って書き直してみます。
ちなみに、行数と列数を指定して処理すると、2次元配列に格納する事ができました。
なぜ、xだとだめなのか。うーん。

            String[][] array = new String[274][5];
            for(int i=0;(tmp=br.readLine())!=null;i++){
                arr = tmp.split(",");
                for(int j=0;j<arr.length;j++){
                    array[i][j] = arr[j];
                }
            } 

評価

0

そもそも、ループに入れなくて、
その箇所に到達していないんだから、ダメも何もないよ。

評価

0

ちなみに
//row取得

//一覧取得→2次元配列格納処理
の間で
br = new BufferedReader(〜
をすると1つめのループには入れます。

ただ
array[i][j] = (sb.append(arr[j] + "\r\n")).toString();
でやっぱりエラーですが…

もしEclipseとか使ってるのであれば、デバッグ実行してみてください。
どこでエラーが起こってるかわかります。

評価

0

ああ。

>array[]を初期化してるのはどこよ。

これ忘れて…。

Stringを突っ込んでるだけだから初期要らないや…。

評価

0

ん?いや、サイズ決めてないんだからやっぱり要るよな…。

row取得した後に
array = new String[x][];

arrが決まった後に
array[i] = new String[arr.length];

しなきゃ格納できないか。

評価

0

5桁と決まってるならrowを取得した後に
array = new String[x][5];
だけでいいか。

ところでsbって何で必要なの?

評価

0

必要ないと思います。
ArrayList<String[]> al = new ArrayList<String[]>();
で、al.addしていけばいいんだよっていう、情報をどこかで見た記憶があり、Listは避けて、回りまわって、StringBuilderでappendしていけば、いいのかなーって思ったのです。

今は必要ない事に気づいております。

評価

0

array = new String[x][5];
で、欲しい結果になる事を確認しました。

ただ、Listを使用してプログラムを作成しようと思います。

後々、Mapで管理しなければならないような気もするので。

評価

0

Mapで管理するのとListを使うのとは、全然別の話に思えるけど、まあ
いいや。

評価

0

ああ。

array = new String[x][];

for(int i=0;(tmp=br.readLine())!=null;i++){
array[i] = tmp.split(",");

でもいいよね。

ただ、実際各列にはちゃんと意味があるわけで、本来はこのデータを意味する自前のクラスを用意して、その配列/リストを作るほうがいい。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。