- ベストアンサー
クラス StringTokenizerのコンストラクタ
あるCSVファイルから行を読み込んで、以下のように文字列を配列に格納しようとしたのですが、カンマとカンマの間の文字列がNULLの時に、次のカンマにある文字列がずれて格納されてしまいます。 例外処理(if文)で処理を振り分けるなどとして、NULLもきちんと配列におさめるにはどのようにすればよろしいのでしょうか? ・ ・ line = csvfile.readLine(); StringTokenizer analy = StringTokenizer(line,","); String[] moji = new String[analy.countTokens()]; for (int n=0; n<moji.length; n++){ moji[n] = analy.nextToken(); } ・ ・
- みんなの回答 (11)
- 専門家の回答
質問者が選んだベストアンサー
xinmanです。 >文字列操作関数(?)のtrim()って文字列両端の空白文字を削除する関数ですか?? そのとおりです。 少しは、お役に立てたでしょうか?
その他の回答 (10)
- xinman
- ベストアンサー率30% (25/83)
xinmanです。 こんなのもありかな? moji2[n2]=" "; の方を使って String[] moji = {"AAA"," ","CCC"}; とある時に String str = "AAA, ,CCC"; をつくり StringTokenizer analy = new StringTokenizer(str,","); analy.nextToken().trim(); で "AAA" "" "CCC" を取得することは出来ます。 プログラムで空白を付け足しても、trim()で削除することで空の文字列を作れます。 この場合は、最初から入っていた空白も削除されますんで、その辺は注意が必要です。
補足
ありがとうございます。 ちなみに、文字列操作関数(?)のtrim()って文字列両端の空白文字を削除する関数ですか?? 他の言語でlefttrim()、righttrim()っていうのは使ったことがあるのですが・・・ ボクのjavaの参考書にはtrim()関数の説明がのっていない!!
- xinman
- ベストアンサー率30% (25/83)
>でも、もしかして配列に空文字""が入っていたら、同じことの繰り返しになってしまうのでしょうか!? そのとおりです。 ただし、" "のように空白が一つでもあれば文字列として認識されます。 String[] moji = {"AAA"," ","CCC"}; とある時に String str = "AAA, ,CCC"; をつくり StringTokenizer analy = new StringTokenizer(str,","); analy.nextToken(); で "AAA" " " "CCC" を取得することは出来ます。 したがって、最初のプログラムで moji2[n2]=null; 若しくは、moji2[n2]=""; としたところを moji2[n2]=" "; とすれば文字列として明示的に取得することが出来ますがいかがでしょうか?
- xinman
- ベストアンサー率30% (25/83)
>この状態(つまり、","を格納していない状態)で、またStringTokenizerのanalyに戻すことってできるのでしょうか? >配列を指定して文字列を取得するのではなく、できればanaly.nextToken()を使って文字列を所得したいのですが・・・ これって String[] moji = {"AAA","BBB","CCC"}; とある時に String str = "AAA,BBB,CCC"; をつくり StringTokenizer analy = new StringTokenizer(str,","); analy.nextToken(); として使いたいということですか? わたしの読解力が足らん性でしょうが質問の意図が半分くらいしか理解できてぬ故、補足してくだされ。
補足
なるほど。 String[] moji = {"AAA","BBB","CCC"}; 配列をつなげるプログラム; String str = "AAA,BBB,CCC"; StringTokenizer analy = new StringTokenizer(str,","); そうすればできますね。 でも、もしかして配列に空文字""が入っていたら、同じことの繰り返しになってしまうのでしょうか!?
- xinman
- ベストアンサー率30% (25/83)
xinmanです。 ばらばらと、まとまりの無い回答で申し訳ありません。m(__)m StringTokenizerについての補足です。 原則的にStringTokenizerは一度読み込んだら終わり的な、使い捨てのClassです。プログラムで使用するときも再利用は出来ないのでそのつもりで使いましょう。 (宣言したクラス変数は新しいStringTokenizerオブジェクトを割り当てることで利用できます) 先答の訂正:StriongはStringの誤りです。ゴメンナサイ。
- xinman
- ベストアンサー率30% (25/83)
xinmanです。お礼拝見しました。 >この状態(つまり、","を格納していない状態)で、またStringTokenizerのanalyに戻すことってできるのでしょうか? Striong str = 配列を","つきで編集したもの; analay = new StringTokenizer(str,",",true); とすることで再度StringTokenizerを生成することが出来ますが… 必要ですか? >配列を指定して文字列を取得するのではなく、できればanaly.nextToken()を使って文字列を所得したいのですが・・・ これはmoji1、moji2、2つも配列を使うなということですか? であれば再度ロジックを考えます(以下は配列の使用を1つにするための話です)。 ただし、StringTokenizerの仕様上与えられた文字列は先頭から順次評価されていきますが、一度評価されたものは再度評価されない構造になっています。 例えば、 new StringTokenizer("AAA,BBB,CCC",","); とあった場合、nextToken()を使用することで "AAA" "BBB" "CCC" と取得できますが、StringTokenizer自体はnextToken()により"AAA"を取得した時点で再度"AAA"を取得することが不可能な状態になります。 この時点では、 new StringTokenizer("BBB,CCC",","); と記述した場合と同等のStringTokenizerになっています。 また、カンマ(区切り文字)が並んで記述されている文字列に対して、カンマとカンマの間にnull若しくはそれに準ずるものを生成する機能はStringTokenizerには用意されていないので必要な場合はプログラムを記述しなければなりません。 muneさんが考えているのはStringTokenizerから直接配列に取り込む方法だと思いますが、この場合は少なくともカンマの数を数えておくことと、カンマが連続していることを識別することが必要になりますので、純粋にStringTokenizerから配列にすることは不可能だと思います。 また、カンマを数えるためには、もとの文字列 line かStringTokenizer(line,",",true)のどちらかは利用しないと難しいと思いますがいかがでしょうか? line に対してカンマの数を数え、StringTokenizer(line,",",true)を使用するのと 1度目のStringTokenizer(line,",",true)でカンマの数を数え、2度目のStringTokenizer(line,",",true)を使用するのとるのと どちらが宜しいですか?
- xinman
- ベストアンサー率30% (25/83)
xinman先答の補足です。 とりあえずカンマとカンマの間の文字列は moji2[n2]=null; としてnullを格納しておきましたが 長さ0の文字列の方が都合がよければ moji2[n2]=""; としてください。 書き換える場合は、2箇所に記述してあるので忘れ無いように。
お礼
試してみました。完璧です!ありがとうございました。 下のもう一つの質問はいかがでしょうか・・・
- xinman
- ベストアンサー率30% (25/83)
xinmanです。 間違いました。 下の回答は自信ありでお願いします。
- xinman
- ベストアンサー率30% (25/83)
xinman再びです。 補足、拝見しました。こんなんでどう? ・ ・ line = csvfile.readLine(); StringTokenizer analy = new StringTokenizer(line,",",true); String[] moji1 = null; String[] moji2 = null; int analy_count = analy.countTokens(); int moji_count = 1; moji1 = new String[ analy_count ]; for (int n=0; n<moji1.length; n++){ moji1[n] = analy.nextToken(); if(moji1[n].equals(","))moji_count++; } moji2 = new String[ moji_count ]; for (int n1=0,n2=0; n2<moji_count; n2++){ if(n1>=moji1.length){ moji2[n2] = null; }else if(moji1[n1].equals(",")){ moji2[n2] = null; }else { moji2[n2] = moji1[n1]; n1++; } n1++; } ・ ・ この場合、moji2に結果が格納されます。
お礼
ありがとうございます。 まだ試してはいないのですが、これでできそうです。 ついでにもう一つ質問させてください。 この状態(つまり、","を格納していない状態)で、またStringTokenizerのanalyに戻すことってできるのでしょうか? 配列を指定して文字列を取得するのではなく、できればanaly.nextToken()を使って文字列を所得したいのですが・・・
- xinman
- ベストアンサー率30% (25/83)
>第1トークンaaa >第2トークン >第3トークンbbb >といった具合にするには、やはり独自に細かいプログラムを作成しなければいけないのでしょうか・・・ 作成しなければならないでしょうね。 作成のしかたはわかりますか? わからなければ、お手伝いいたしますので補足してください。
補足
ちょっとわからないので、あまえてもよろしいでしょうか?
- stardust
- ベストアンサー率44% (8/18)
java.util.StringTokenizer ですよね? インスタンスを作成するときに以下のコンストラクタを使ってみて下さい。 public StringTokenizer(String str,String delim,boolean returnTokens) 第3引数の returnTokens に true を指定すると、区切り文字自身も一つのトークンとして取得できます。 例) コンマ区切り aaa,,bbb 第1トークン aaa 第2トークン , 第3トークン , 第4トークン bbb この方法を使えば、件の目的は果たせるのでは無いでしょうか?
お礼
早速ありがとうございます。 trueを指定して試してみたのですが、区切り文字も入ってしまうのですね。 第1トークンaaa 第2トークン 第3トークンbbb といった具合にするには、やはり独自に細かいプログラムを作成しなければいけないのでしょうか・・・
お礼
かなり役に立ちました。 実際にプログラムまで書いていただいて・・・ いろいろとありがとうございました。