- PR -

JSPよりStringTokenizerを使う方法

投稿者投稿内容
みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2004-03-03 14:45
こんにちわ。
みーちくと申します。

JSPでStringTokenizerを使用しているのですが、下記のようなエラーが出てしまいました。
何度もソースを見直しているのですが、原因がつかめません。
皆様ご教授願います。

【エラーメッセージ】
java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:232)

【読込ファイル】
aaaa:1:2
bbbb:2:5
cccc:3:5

コードは長いので、ファイルを読み込んでいる部分のみ掲載させていただきます。
コード:
<%@ page import="java.io.*, java.util.*, Admin.Admin_Util" contentType="text/html; charset=Shift_JIS" %>
<%
	final String encoding 		= "SJIS";
	final String create_count 	= "/home/dtp/bin/Admin_jsp/last/create.txt";
	BufferedReader fin;
	String htmlRows = "";
	// 制作用countファイルを取得
	fin = new BufferedReader(new InputStreamReader(new FileInputStream(create_count), encoding));
	String s = "";
	while((s = fin.readLine()) != null){
		StringTokenizer st 	= new StringTokenizer(s, ":");
		String dir_name 	= st.nextToken();
		String dir_count 	= st.nextToken();
		String file_count 	= st.nextToken();
		
		htmlRows += "<tr align="right">"
			+ "<td width='30%' align='left'>○" + dir_name + "</td>"
			+ "<td width='35%'>サブディレクトリ数 = " + dir_count + "</td>"
			+ "<td width='35%'>ファイル数 = " + file_count + "</td>"
			+ "</tr>";
	}
	fin.close();
%>


おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2004-03-03 15:08
StringTokenizer#nextToken()しようとしたらトークンが無かった、ということでは?
nextToken()する前にhasMoreToken()した方が良いですよ。

# java.sun.comがなぜかアクセスできないので、Javadocを見ながら回答できません。
# メソッド名など間違っていたらご容赦を。
taro
ぬし
会議室デビュー日: 2003/10/20
投稿数: 316
投稿日時: 2004-03-03 15:12
こんにちは。

NoSuchElementExceptionは「トークナイザの文字列にトークンが残っていない場合」の
例外ですが、
コード:

String dir_name = "";
if(st.hasMoreTokens()) dir_name = st.nextToken();
String dir_count = "";
if(st.hasMoreTokens()) dir_count = st.nextToken();
String file_count = "";
if(st.hasMoreTokens()) file_count = st.nextToken();


のようにトークンが残っている場合のみ取得するようにすると、
どの時点まで取れているかなどは分かり、原因究明の参考にならないでしょうか?

# かぶってしまいました。すみません。。

[ メッセージ編集済み 編集者: taro 編集日時 2004-03-03 15:13 ]
おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2004-03-03 15:15
引用:

# かぶってしまいました。すみません。。


あ、いえいえ、こちらこそ
Javadocをちゃんと調べられて投稿されているようで、私のうろ覚え投稿より
信頼性があって良いかと。hasMoreTokens()でしたね。。。sが付くの忘れてた
みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2004-03-03 15:36
みーちくです。

おばけさん、taroさん
返信ありがとうございました。

下記のようにhasMoreTokens()を使用して、テストしてみた結果うまくいきました。
今度からはちゃんとJavaDocを調べてから投稿したいと思います。
ありがとうございました。
コード:
fin = new BufferedReader(new InputStreamReader(new FileInputStream(create_count), encoding));
String s = "";
while((s = fin.readLine()) != null){
  StringTokenizer st   = new StringTokenizer(s, ":");
  while(st.hasMoreTokens()){
    String dir_name   = st.nextToken();
    String dir_count   = st.nextToken();
    String file_count   = st.nextToken();
    create += "<tr align='right'>"
      + "<td width='30%' align='left'>○" + dir_name + "</td>"
      + "<td width='35%'>サブディレクトリ数 = " + dir_count + "</td>"
      + "<td width='35%'>ファイル数 = " + file_count + "</td>"
      + "</tr>";
  }
}
fin.close();

おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2004-03-03 15:52
引用:

下記のようにhasMoreTokens()を使用して、テストしてみた結果うまくいきました。


ちょっと違いますよ

hasMoreTokens()してtrueならば、初めてnextToken()が呼べます。
つまり、taroさんのおっしゃる様に、いちいちnextToken()する前にhasMoreTokens()して
trueかどうか調べないとダメです。
みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2004-03-03 16:21
みーちくです。

おばけさん返信ありがとうございます。
ちょっと混乱してきたので、教えてください。

引用:

hasMoreTokens()してtrueならば、初めてnextToken()が呼べます。
つまり、taroさんのおっしゃる様に、いちいちnextToken()する前にhasMoreTokens()して
trueかどうか調べないとダメです。



下記のように、hasMoreTokens()が true か false か聞いているのですが、
これでは、ダメなのでしょうか?

while(st.hasMoreTokens()){
処理
}
おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2004-03-03 16:36
引用:

下記のように、hasMoreTokens()が true か false か聞いているのですが、


これでは、whileループに入る直前のトークンの状態しかチェックしていません。
コード:

while(st.hasMoreTokens()){
String dir_name = st.nextToken();
String dir_count = st.nextToken();
String file_count = st.nextToken();
...
}


と書かれているように、一度チェックしたあと三回連続でnextToken()を呼んでいますよね?
ですが、最初にwhile文の条件判定で行ったhasMoreTokens()のチェックでは、一番上の
dir_nameに値を代入する際に実行されるnextToken()でトークンが取得できることしか
保証できていません。

例えば、用意されたファイルがたまたま
コード:

aaaa:1:2
bbbb:2:5
cccc


のように欠損していたらどうなるでしょうか?

この場合、最終行で":"で文字列をトークンに分割しても、1個しかトークンは得られません。
すると、上記のコードではdir_countに値を代入しようとして実行されるnextToken()で
トークンが見つからず、NoSuchElementExceptionが送出されてしまいます。

つまり、何度も繰り返しになりますが、nextToken()する際は、その都度直前で
hasMoreTokens()による判定を行う必要があります。つまり、taroさんが書かれた
まさにそのままの通り、
コード:

if (st.hasMoreTokens()){ token = st.nextToken(); }


という形式でhasMoreTokens()とnextToken()の呼び出しをペアにしないとダメです。

みーちくさんのコードでは、不正な形式のファイルを与えられるとコケてしまいます。


[ メッセージ編集済み 編集者: おばけ 編集日時 2004-03-03 16:46 ]

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