• ベストアンサー

クラス 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(); } ・ ・

  • mune
  • お礼率13% (21/151)
  • Java
  • 回答数11
  • ありがとう数6

質問者が選んだベストアンサー

  • ベストアンサー
  • xinman
  • ベストアンサー率30% (25/83)
回答No.11

xinmanです。 >文字列操作関数(?)のtrim()って文字列両端の空白文字を削除する関数ですか?? そのとおりです。 少しは、お役に立てたでしょうか?

mune
質問者

お礼

かなり役に立ちました。 実際にプログラムまで書いていただいて・・・ いろいろとありがとうございました。

その他の回答 (10)

  • xinman
  • ベストアンサー率30% (25/83)
回答No.10

xinmanです。 こんなのもありかな? moji2[n2]=" "; の方を使って String[] moji = {"AAA"," ","CCC"}; とある時に String str = "AAA, ,CCC"; をつくり StringTokenizer analy = new StringTokenizer(str,","); analy.nextToken().trim(); で "AAA" "" "CCC" を取得することは出来ます。 プログラムで空白を付け足しても、trim()で削除することで空の文字列を作れます。 この場合は、最初から入っていた空白も削除されますんで、その辺は注意が必要です。

mune
質問者

補足

ありがとうございます。 ちなみに、文字列操作関数(?)のtrim()って文字列両端の空白文字を削除する関数ですか?? 他の言語でlefttrim()、righttrim()っていうのは使ったことがあるのですが・・・ ボクのjavaの参考書にはtrim()関数の説明がのっていない!!

  • xinman
  • ベストアンサー率30% (25/83)
回答No.9

>でも、もしかして配列に空文字""が入っていたら、同じことの繰り返しになってしまうのでしょうか!? そのとおりです。 ただし、" "のように空白が一つでもあれば文字列として認識されます。 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)
回答No.8

>この状態(つまり、","を格納していない状態)で、またStringTokenizerのanalyに戻すことってできるのでしょうか? >配列を指定して文字列を取得するのではなく、できればanaly.nextToken()を使って文字列を所得したいのですが・・・ これって String[] moji = {"AAA","BBB","CCC"}; とある時に String str = "AAA,BBB,CCC"; をつくり StringTokenizer analy = new StringTokenizer(str,","); analy.nextToken(); として使いたいということですか? わたしの読解力が足らん性でしょうが質問の意図が半分くらいしか理解できてぬ故、補足してくだされ。

mune
質問者

補足

なるほど。 String[] moji = {"AAA","BBB","CCC"}; 配列をつなげるプログラム; String str = "AAA,BBB,CCC"; StringTokenizer analy = new StringTokenizer(str,","); そうすればできますね。 でも、もしかして配列に空文字""が入っていたら、同じことの繰り返しになってしまうのでしょうか!?

  • xinman
  • ベストアンサー率30% (25/83)
回答No.7

xinmanです。 ばらばらと、まとまりの無い回答で申し訳ありません。m(__)m StringTokenizerについての補足です。 原則的にStringTokenizerは一度読み込んだら終わり的な、使い捨てのClassです。プログラムで使用するときも再利用は出来ないのでそのつもりで使いましょう。 (宣言したクラス変数は新しいStringTokenizerオブジェクトを割り当てることで利用できます) 先答の訂正:StriongはStringの誤りです。ゴメンナサイ。

  • xinman
  • ベストアンサー率30% (25/83)
回答No.6

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)
回答No.5

xinman先答の補足です。 とりあえずカンマとカンマの間の文字列は moji2[n2]=null; としてnullを格納しておきましたが 長さ0の文字列の方が都合がよければ moji2[n2]=""; としてください。 書き換える場合は、2箇所に記述してあるので忘れ無いように。

mune
質問者

お礼

試してみました。完璧です!ありがとうございました。 下のもう一つの質問はいかがでしょうか・・・

  • xinman
  • ベストアンサー率30% (25/83)
回答No.4

xinmanです。 間違いました。 下の回答は自信ありでお願いします。

  • xinman
  • ベストアンサー率30% (25/83)
回答No.3

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に結果が格納されます。

mune
質問者

お礼

ありがとうございます。 まだ試してはいないのですが、これでできそうです。 ついでにもう一つ質問させてください。 この状態(つまり、","を格納していない状態)で、またStringTokenizerのanalyに戻すことってできるのでしょうか? 配列を指定して文字列を取得するのではなく、できればanaly.nextToken()を使って文字列を所得したいのですが・・・

  • xinman
  • ベストアンサー率30% (25/83)
回答No.2

>第1トークンaaa >第2トークン >第3トークンbbb >といった具合にするには、やはり独自に細かいプログラムを作成しなければいけないのでしょうか・・・ 作成しなければならないでしょうね。 作成のしかたはわかりますか? わからなければ、お手伝いいたしますので補足してください。

mune
質問者

補足

ちょっとわからないので、あまえてもよろしいでしょうか?

  • stardust
  • ベストアンサー率44% (8/18)
回答No.1

java.util.StringTokenizer ですよね? インスタンスを作成するときに以下のコンストラクタを使ってみて下さい。 public StringTokenizer(String str,String delim,boolean returnTokens) 第3引数の returnTokens に true を指定すると、区切り文字自身も一つのトークンとして取得できます。 例) コンマ区切り aaa,,bbb 第1トークン aaa 第2トークン , 第3トークン , 第4トークン bbb この方法を使えば、件の目的は果たせるのでは無いでしょうか?

参考URL:
http://java.sun.com/j2se/1.3/docs/api/java/util/StringTokenizer.html
mune
質問者

お礼

早速ありがとうございます。 trueを指定して試してみたのですが、区切り文字も入ってしまうのですね。 第1トークンaaa 第2トークン 第3トークンbbb といった具合にするには、やはり独自に細かいプログラムを作成しなければいけないのでしょうか・・・

関連するQ&A

  • StringTokenizerについて

    JAVAの勉強をしているのですが、StringTokenizerの役割がよく分かりません。検索サイトを使って色々調べてみたのですが、「トークンを区切る」だとかよく分からない言葉が出てきて全く理解できません。以下はあるデータから項目を抽出するプログラムらしいのですが、参考としてこの例でStringTokenizerがどのような役割を果たしているのか教えて下さい。複雑で説明しにくければStringTokenizerそのものの説明でも十分です。よろしくお願いします。 BufferedReader reader=new BufferedReader(new InputStreamReader(System.in)); String line=""; try { int i=0; while ((line = reader.readLine()) != null) { int fcount=1; StringTokenizer st = new StringTokenizer(line); while (st.hasMoreTokens()) { switch (fcount) { case 2: //項目2:被説明変数Y data[i][0]=Integer.parseInt(st.nextToken()); break; case 4: //項目4:説明変数X data[i][1]=Integer.parseInt(st.nextToken()); break; default: // その他の項目 String dummy=st.nextToken(); break; } fcount++; } i++; } NofData=i;

    • ベストアンサー
    • Java
  • StringTokenizerについて(エラー)

     java初心者です。この度、突貫工事でjavaのネットワークプログラムを作らねばならず、本などを参考にしながら独学でサーバーとクライアントを作成しています。 クライアントは正常に稼働するようなのですが、サーバーにはStringTokenizerの使い方に問題があるらしく、NullPointerExceptionというエラーが出て受信がうまくできません。(以下、エラーが検出される個所を抜粋) …………… ////runメソッド //クライアント処理スレッドの本体です public void run(){ try{ //logout受信まで繰り返します while(true){ //クライアントからのコマンドを読み取ります String line = in.readLine(); //nameが空の場合にはログインコマンドのみを受け付けます。 if(name == null){ StringTokenizer st= new StringTokenizer(line);////エラー箇所 String cmd = st.nextToken(); if("login".equalsIgnoreCase(cmd)){ name = st.nextToken(); server.loginUser(name);//loginメソッドへ } }else{ //nameが空でない場合はログイン済みなのでコマンドを受け付けます。 StringTokenizer st = new StringTokenizer(line); String cmd=st.nextToken();//コマンドの取り出し if("logout".equalsIgnoreCase(cmd)){ server.logoutUser(name);//logoutメソッドへ break;//logoutの場合にはループを終了します。 } } } ……………… 提出期限が迫っており、また、周囲にjavaの心得がある人がいないので困っています。不勉強で申し訳ありませんが、どなたか回答宜しくお願いします。 追伸:プログラムに関する知識が乏しいので用語の使い方が間違っているかもしれませんがご容赦ください。。。

  • ファイルから複数行のトークンを文字列検索。

    input.txt から "," で区切られた文字列をトークンで分け、 左がパターン、右が検索する文字列になります。 一行の場合は while((line = brInput.readLine())!= null ) { StringTokenizer st = new StringTokenizer(line, ","); if(st.hasMoreTokens()){ pattern = st.nextToken(); text = st.nextToken(); } これでマッチするだけなのですが、複数行の場合はどうでしょうか?

    • ベストアンサー
    • Java
  • StringTokenizerクラスでのエラーについて

    仕事で一人で組んでいるので、尋ねる相手がいません。 どなたか教えて下さいm(__)m かなり長い文字列を読込んで、その文字列を"!"を条件に分割したいので、以下のようなソースを書きました。 実行すると、NullPointerExceptionが発生します。 public class Split2 { public static void main(String args[]) throws IOException { //サンプルファイルの読込み BufferedReader red = new BufferedReader(new FileReader("getRoute_ResultSample_1.txt")); String line; while ((line = red.readLine()) != null) { System.out.println(line); } red.close(); StringTokenizer strToken = new StringTokenizer(line, "!"); int cnt = strToken.countTokens(); 文字列分割処理の一番最初の処理として"1"で区切り、その数をまず取得したいのです。 私は結構初心者PGです。 よろしくお願い致しますm(__)m

    • ベストアンサー
    • Java
  • StringTokenizerについて

    ファイルの読み込みをStringTokenizerを使ってやりたいのですが、 使い方がいまいち理解できません。今自分で作っているプログラムでは効率が悪いです。 プログラムの一部を載せるのでアドバイスお願いします。 <プログラム> InputStreamReader fisr = new InputStreamReader(client. getInputStream()); BufferedReader fin = new BufferedReader(fisr); String name = fin.readLine(); System.out.println(name); while(n!=10){ FileInputStream objFis = new FileInputStream("eitango"+rand[n]+".txt"); InputStreamReader objlsr = new InputStreamReader(objFis,"Shift_jis"); BufferedReader objBr = new BufferedReader(objlsr); PrintWriter out = new PrintWriter(client.getOutputStream(),true); //1行ずつファイルを読み込む if (n==0){ out.println("Hello,clientNo:" + number +"\n"); } for(a=0;a!=6;a++){ if(a==5){ String ans = objBr.readLine(); ans2 = ans.length(); System.out.println("ans2 = "+ans2); } if(a!=5){ out.println(objBr.readLine()); } }

    • ベストアンサー
    • Java
  • javaを用いて,a列,b列の空白数を数えたい.

    javaを使って,a列,b列の空白数を数えるプログラムを教えてください. 自分なりに色々と考えてみましたが全くわかりません… おカぞえ,どうぞよろしくお願いいたします. 初心者のため,具体的に教えていただけるとありがたいです. 以下に途中まで考えたコードを添付いたします. 自分としましては,空白に-9を代入し,後でそれを数えるというような方法を考えました. import java.io.*; import java.util.*; public class PTMain { public static void main(String[] args) { try{ BufferedReader fin = new BufferedReader(new FileReader("test.csv")); String ss ; String a; String b; fin.readLine(); while((ss=fin.readLine())!=null){ StringTokenizer st =new StringTokenizer(ss,","); a = st.nextToken(); b = st.nextToken(); if (a.equals(null)){ a="-9" ; //もし空白があるなら-9を代入したい } if (b.equals(null)){ b="-9" ; } System.out.println("a = " + a); System.out.println("b = " + b); } } } } /* test.csv a,b,c,d 5,6,3, 4,,8,1 ,6,7, 5,7,8,8 9,1,45,1 6,6,, ,1,8,5 5,4,5, */

  • カンマで区切られたメールアドレスを配列に格納したい場合

    いつもお世話になっております。 下記のようなStringのデータを配列に格納したいのですが、 private static final String MAILS = "test1@test.com,tes,t2@tes,t.net,test3@te,st.jp"; 普通にカンマで分割するとメールアドレスの形式はめちゃくちゃで配列に格納されてしまいます。 StringTokenizer st = new StringTokenizer(MAILS, ","); String [] mailList = new String[st.countTokens()]; int i = 0; while (st.hasMoreTokens()) { mailList[i] = st.nextToken(); i++; } test1@test.com tes,t2@tes,t.net test3@te,st.jp 上記のようにちゃんとしたメールの形式で配列に格納するにはどうすればいいでしょうか? ご教授頂ければ幸いです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • C言語での文字列ソート動作について

    任意の文字列を入力し、その文字列を昇順にソートするプログラムを作ったのですが、入力する文字の文字数が大きく異なると期待した結果が得られません。 文字数が少なくなったり、他の配列の文字が混ざったりと言う結果に成ってしまっています。 何が原因か分からない状態です。 以下にサンプルを記載させて頂きますので、助言よろしくお願いします。 /*----------------------------------------- 入力例 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC BBBBBBBBBBBBBBBB AAAAAA -----------------------------------------*/ #include <stdio.h> #include <string.h> #include <stdlib.h> void swapc(char *cx , char *cy){ char tmp[100]; strcpy(tmp, cx); strcpy(cx, cy); strcpy(cy, tmp); } int main(){ char *num[100]; char str_tmp[100]; //文字列一時格納 int moji_cnt; //入力した文字列のカウント int n , m; // 文字列入力処理開始 printf("文字列を入力してください\n"); for( moji_cnt = 0 ; moji_cnt != 3 ; moji_cnt++){ scanf("%s", str_tmp); *(num+moji_cnt) = (char *)malloc(sizeof(char) * (strlen(str_tmp)+1)); //メモリ確保 strcpy(*(num+moji_cnt), str_tmp); } puts("\n"); // 文字数ソート処理 for(n = 0 ; n < moji_cnt-1 ; n++){ for(m = 1 ; m < moji_cnt-n ; m++){ if(strcmp(*(num+n) , *(num+n+m)) > 0){ swapc(*(num+n) , *(num+n+m)); // 文字列入れ替え } } } puts("\n"); for(n = 0;n != moji_cnt;n++){ printf("%s\n" , *(num+n)); } free(num); }

  • readLineとStringTokenizerで一行ずつ計算するプログラムでエラーが出る

    初めに行数があり、次に6つのスペースで区切られた数字を一行ずつ計算していくというプログラムが作りたいのですが、実行後 Exception in thread "main" java.lang.NullPointerException at java.util.StringTokenizer.<init>(StringTokenizer.java:182) at java.util.StringTokenizer.<init>(StringTokenizer.java:219) at example.main(example.java:36) のようなエラーが出てきます。下記がそのプログラムですが、stのコンストラクタがループの中に入っているせいだと思い、ループの外でコンストラクトしようと考えたのですがうまくいかずいきづまってしまいました。 どなたかご教示いただけませんでしょうか。よろしくお願いいたします。 int c=0; String line ; int ln = Integer.parseInt(br.readLine()); for(int i = 0; i < ln; i++) { line=br.readLine(); StringTokenizer st = new StringTokenizer(line); for(j = 0; j <= 5; j++) { c=Integer.parseInt(st.nextToken()); intArray[j]=c; } (計算) }

    • ベストアンサー
    • Java
  • C# ジェネリックメソッドでCSVの読み込み

    以下のメソッドをジェネリックメソッドにしたいのですが、 Double.Parseメソッドの部分をどう変更したらいいのかわかりません。 どなたか方法を教えてください! //CSVデータをdouble配列に格納する public static void readCSV(double[] a, string filePath) { int i = 0; char delimiter = ','; //区切り文字はカンマ string line = ""; using (StreamReader r = new StreamReader(filePath)) { while ((line = r.ReadLine()) != null) // 1行ずつ読み出し。 { //分割した結果を文字列の配列で受け取る string[] splittedResult = line.Split(delimiter); a[i] = (Double.Parse(splittedResult[0])); i++; } } } //ジェネリックバージョン public static void readCSV<Type>(Type[] a, string filePath) { int i = 0; char delimiter = ','; //区切り文字はカンマ string line = ""; using (StreamReader r = new StreamReader(filePath)) { while ((line = r.ReadLine()) != null) // 1行ずつ読み出し。 { //分割した結果を文字列の配列で受け取る string[] splittedResult = line.Split(delimiter); //Double.ParseをTypeを用いてどう記述していいかわからない a[i] = (Double.Parse(splittedResult[0])); i++; } } }

専門家に質問してみよう