- PR -

ファイル入力時の項目切出しについて

投稿者投稿内容
たいき
会議室デビュー日: 2002/05/11
投稿数: 14
投稿日時: 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言語でやるには,どうすれば良いのでしょうか.
きっと簡単な質問で,「調べろよ!」と言われそうですが,ちょっと
困っていますので、どうかよろしくお願いします.
しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2002-05-24 00:51
ほげほげInputStream(Readerでもいいけど)かまして頭からかじっていくのじゃだめでしょか。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2002-05-24 06:52
コード:
class Tmp { 
    static final int SIZE_OF_NO1 = 5;
    static final int SIZE_OF_NO2 = 3;

    String no1; // 必ず5桁 
    String no2; // 必ず3桁 
}


として、

コード:
BufferedReader fin = new BufferedReader(new FileReader("tmp.txt")); 
String str; 
  while ((str = fin.readLine()) != null) { 
    Tmp tmp = new Tmp(); 
    tmp.no1 = str.substring(0, Tmp.SIZE_OF_NO1); 
    tmp.no2 = str.substring(Tmp.SIZE_OF_NO1, Tmp.SIZE_OF_NO1+Tmp.SIZE_OF_NO2); 
    System.out.println("no1 : " + tmp.no1 + ", no2 : " + tmp.no2); 
} 


とやればレコードの桁数が変わっても、Tmpクラス内の
static final int SIZE_OF_NO1 = 5;
static final int SIZE_OF_NO2 = 3;
を直せばいいだけです。・・・でも再コンパイルしないと駄目ですが。

コンパイル無しでですか?
YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2002-05-24 08:40
そのテキストファイルの先頭に、
s1バイト目からe1バイト目までが1つ目のトークン、
s2バイト目からe2バイト目までが2つ目のトークン・・・・
と言うような定義を入れるとかは駄目ですか?

あとは.propertiesファイルに持たせるとか、サーブレットなら
初期化パラメタから渡すとか・・・

後は取得した定義を使ってString#substring()で分けるしかないですかね・・・。
まりり
ぬし
会議室デビュー日: 2001/12/05
投稿数: 329
投稿日時: 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 ]
miki
大ベテラン
会議室デビュー日: 2001/09/21
投稿数: 174
お住まい・勤務地: 東京都八王子市
投稿日時: 2002-05-24 11:29
文字列の切り出し部分に正規表現パッケージが使えませんか。
"([0-9]{6})([0-9]{3})"のようなパターンを使って2つに分けるのです。


へげもん
ベテラン
会議室デビュー日: 2002/04/14
投稿数: 87
お住まい・勤務地: 埼玉県
投稿日時: 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/11
投稿数: 14
投稿日時: 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 の正規表現の記述法みたく柔軟に記述できるものなんですか?
今回の業務開発では使わなくて済むのですが,今後勉強してみます.
みなさん,ありがとうございました.

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