- - PR -
ファイル入力時の項目切出しについて
1|2|3
次のページへ»
| 投稿者 | 投稿内容 | ||||||||
|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2002-05-23 21:05
ファイル読込みの質問です.
うまく言葉で説明できないので,ソースを書きます. 入力ファイルである tmp.txt は下記のように5桁数字列+3桁数字列で 固定だと仮定します.2レコードあります. 12345123 54321321 これを読込んで,5桁数字列と3桁数字列を取得するために, substring を用いれば,もちろん取得できることは理解できます. <ソース> BufferedReader fin = new BufferedReader(new FileReader("tmp.txt")); String str; while ((str = fin.readLine()) != null) { Tmp tmp = new Tmp(); tmp.no1 = str.substring(0, 5); tmp.no2 = str.substring(5, System.out.println("no1 : " + tmp.no1 + ", no2 : " + tmp.no2); } class Tmp { String no1; // 必ず5桁 String no2; // 必ず3桁 } ただ,substring の上記の書き方だと,5桁数字列が6桁になれば, tmpTmp.no1 = str.substring(0, 6); tmpTmp.no2 = str.substring(6, 9); という具合に変更が入ってしまいます. C言語の場合だと,fread 関数で1レコードを固定長バイト (ここなら改行:LFで9バイト)で読込む際に, fread (&st_tmp, 1, sizeof (st_tmp), fin); (※ st_tmp を Tmp クラスと同等の定義と仮定してください. もちろん,String ではなくて char ですが.) などとやれば,構造体 st_tmp に no1, no2 が自動で設定されますよね. これなら,no1 の桁数が5桁→6桁でも,構造体定義の変更だけで済みます. COBOL言語でも同様ですよね.こっちの方がもっと扱いが簡単ですが. 同等のことをJAVA言語でやるには,どうすれば良いのでしょうか. きっと簡単な質問で,「調べろよ!」と言われそうですが,ちょっと 困っていますので、どうかよろしくお願いします. | ||||||||
|
投稿日時: 2002-05-24 00:51
ほげほげInputStream(Readerでもいいけど)かまして頭からかじっていくのじゃだめでしょか。
| ||||||||
|
投稿日時: 2002-05-24 06:52
として、
とやればレコードの桁数が変わっても、Tmpクラス内の static final int SIZE_OF_NO1 = 5; static final int SIZE_OF_NO2 = 3; を直せばいいだけです。・・・でも再コンパイルしないと駄目ですが。 コンパイル無しでですか? | ||||||||
|
投稿日時: 2002-05-24 08:40
そのテキストファイルの先頭に、
s1バイト目からe1バイト目までが1つ目のトークン、 s2バイト目からe2バイト目までが2つ目のトークン・・・・ と言うような定義を入れるとかは駄目ですか? あとは.propertiesファイルに持たせるとか、サーブレットなら 初期化パラメタから渡すとか・・・ 後は取得した定義を使ってString#substring()で分けるしかないですかね・・・。 | ||||||||
|
投稿日時: 2002-05-24 10:28
class Tmp {
static final int SIZE_OF_NO1 = 5; static final int SIZE_OF_NO2 = 3; private String no1; private String no2; public Tmp(String str){ this.no1 = str.substring(0,SIZE_OF_NO1); this.no2 = str.substring(SIZE_OF_NO1,SIZE_OF_NO2); } /* setter/getter */ } とかして、 Tmp tmp = new Tmp(str); とやれば、呼び出しもとの修正はいらなくなりますね。 コンストラクタでやるのが嫌なら同じ内容のメソッドを定義して、 それを呼ぶと。 public Tmp load(String str){ /* 上のコンストラクタと同じ */ } で、 Tmp tmp = new Tmp(); tmp.load(str); と使う。 [ メッセージ編集済み 編集者: まりり 編集日時 2002-05-24 10:30 ] | ||||||||
|
投稿日時: 2002-05-24 11:29
文字列の切り出し部分に正規表現パッケージが使えませんか。
"([0-9]{6})([0-9]{3})"のようなパターンを使って2つに分けるのです。 | ||||||||
|
投稿日時: 2002-05-24 12:18
こんなのどうでしょ?
import java.io.*; public class Test { private char no1[] = new char[5]; private char no2[] = new char[3]; public Test(String buf) { char array[] = buf.toCharArray(); int i = copy(array,no1,0); copy(array,no2,i); } public String getNo1() { return new String(no1); } public String getNo2() { return new String(no2); } static int copy(char src[],char dst[],int offset) { for ( int i = 0; i < dst.length; i++ ) dst[i] = src[offset+i]; return offset+dst.length; } public static void main(String args[]) throws FileNotFoundException,IOException { BufferedReader in = new BufferedReader(new FileReader("test.txt")); String buf; while ( (buf = in.readLine()) != null ) { Test test = new Test(buf); System.out.println(test.getNo1()+","+test.getNo2()); } } } | ||||||||
|
投稿日時: 2002-05-24 22:58
みなさん,ありがとうございます.
ちょっと私の説明で舌足らずの所もあってすみません. 項目が2つだけとは限らないこと,中途に項目が追加,削除されたときでも 対応が少なくて済ませたいな,と思ってたわけです. 現状は,とりあえずH2さんの言われる形に近くて String str; int beginIx = 0; while ((str = fin.readLine()) != null) { Tmp tmp = new Tmp(); tmp.no1 = str.substring(beginIx, beginIx += Tmp.no1Len); tmp.no2 = str.substring(beginIx, beginIx += Tmp.no2Len); <略:no3, no4 と継続> } という切り出し方を Tmp クラスの引数 str のコンストラクタで 実装していました. これでもいいかなとも思ってたんですが,個人的にはへげもんさんのを 使ってみようか,と考えています. ちょっと話題は違うのですが,miki さん,ご指摘の java 正規表現 パッケージは perl の正規表現の記述法みたく柔軟に記述できるものなんですか? 今回の業務開発では使わなくて済むのですが,今後勉強してみます. みなさん,ありがとうございました. | ||||||||
1|2|3
次のページへ»
