- - PR -
File Structure
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2003-03-03 00:12
二つの異なるクラスからデータの読み書きをするのですが。どうも上手くいきません。
----概要---- 1つは、ファイルフィールドクラスで、ファイルを読み、もう一方は、レコードクラスでファイルを指定された型で保存します。 フィールドクラス ・abstract FieldRecordFile, extention FixFix(長さ調節します) VarCon(delimiterで書くフィールドを区切ります)varInd(インデックスを追加します) レコードクラス abstract Record(メソッドreadObject(DataInputStream dis)が各フィールドクラスのgetRecord(int n)で使われます。getRecordでnew Record()を生成しようと思うのですが、Recordクラスが受け取りません) FixFixRecord VarIndRecord VarIndRecord(それぞれのクラスにreadObject(Reader rd) writeObject(DataOutputStream dos)をもち、各々の形式でデータをカプセル化します。この時、readObject(rd)はそれぞれのフィールドクラスのメソッド(void buildFile()で、データを読み書くrecordクラスに合うようにします。)readObjectは一方はバイナリ、もう一方はアスキーで読み取ります。getRecordではrandom accessがつかわれず、markとreset、VarIndとFixFixクラスではskipByteメソッドを使います。 | ||||
|
投稿日時: 2003-03-04 11:57
unibon です。こんにちわ。
#果敢に投稿させていただきます。
老婆心ながら、試されているコードを長すぎず端折り過ぎない程度に取捨選択されて提示されたほうが 分かりやすいような気がします。 ちなみに readObject/writeObject は ObjectInput/ObjectOutput インターフェースとは別のものですよね。 というか、そもそも何ができて何ができないことが問題なのかが良く分かりません。 #ここで挫折。 | ||||
|
投稿日時: 2003-03-04 12:58
多分そうだと思います。レコード(名前16length、float6つ、int2つ、シンボル(string)4charactersにVarIndクラスのみ20characters以内の長さ)をまず、各FieldクラスのRecord getRecord(int n)でDataInputStreamでファイルを読み込み、Recordオブジェクトを作ります。それを、レコードクラスで、getName getSymbol...で読み込んでくれずnullになってしまいます。しかし、各レコードクラスのreadObject(DataInputStream dis)readObject(Reader rd)、writeObject(DataOutputStream dos)では受け取っているのです。フィールドクラスのDataInputStreamでは、mark()、reset()を使って、データの長さを調節し、Readerはフィールドクラス内のbuildFile()を使って、データを読み込み、これは、レコードクラス内のreadObject(Reader rd)で、StringTokenizerを使って分解された後、writeObjectでカプセル化されます。
このレコードクラスのコンストラクタは2つで、一つがname=name、symb=symb...でもう一つがname=null、symb=null...となります(extentionはsuper()のdefaultです) 多分、この問題は、メモリが非常に貴重だったころのテーマだと思います。 やはり、長さの問題でしょうか。コンストラクタは間違ってませんよね。あと、DataInputStreamはStringを読むメソッドがなく(readUTF()は×)、charあたりで読むようになると思うのですが、どのようにしたら長さを調整できるのでしょうか。 | ||||
|
投稿日時: 2003-03-06 09:17
unibon です。こんにちわ。
#再び果敢に投稿させていただきます。
コンストラクタのコードを提示されてはどうでしょうか。 前回も少し触れましたが、日本語での解説だけよりは、 実際のコード(プログラム)を書かれるほうが伝わりやすいと思います。 #あるいは、適度に両者を併用するともっと良いでしょう。 ちなみにコンストラクタでコーディング上のありがちな間違いとしては、 class MyClass { private String name; public MyClass(String name) { name = name; } } などです(フィールド名と引数の名前が同じ)が、 こんな簡単なことではたぶんないですよね。 | ||||
|
投稿日時: 2003-03-06 10:10
もう、情けないくらい何もわかっていません。
コンストラクタはthisで区別しています。問題は、どうやってStringをreadUTFを使わずに読むか、とmark()とreset()を使いこなすかだと思うのですが... public abstract class Record { /** * Create a record with given properties. */ public Record(String name, String symb, float high, float low, float close, int vol, int volchange,float priceChange, short rate){ this.name = name; this.symb = symb; this.high = high; this.low = low; this.close = close; this.vol = vol; this.volchange = volchange; this.priceChange = priceChange; this.rate = rate; } /** * Create a lazy constructor. */ public Record(){ name = null; symb = null; high = 0; low = 0; close = 0; vol = 0; volchange = 0; priceChange = 0; rate = 0; } ....略 これは、FileReder public void readObject(Reader rd) throws IOException{ BufferedReader br = new BufferedReader(rd); String s=br.readLine(); if(s==null) return; StringTokenizer lineTokenizer = new StringTokenizer(s); this.name = lineTokenizer.nextToken(); this.high = Float.parseFloat(lineTokenizer.nextToken()); this.low = Float.parseFloat(lineTokenizer.nextToken()); this.close = Float.parseFloat(lineTokenizer.nextToken()); this.vol= Integer.parseInt(lineTokenizer.nextToken()); this.volchange= Integer.parseInt(lineTokenizer.nextToken("+ ")); this.price = Float.parseFloat(lineTokenizer.nextToken("+ ")); this.rate = Short.parseShort( lineTokenizer.nextToken("+ ")); this.symb = lineTokenizer.nextToken(); } こちらはレコードFixして保存するクラス public FixFixRecord(String name, String symb, float high, float low, float close, int vol, int volchange, float priceChange,short rate){ super(name, symb, high,low, close, vol, volchange, priceChange,rate); this.name=name; this.symb=symb; this.high=high; this.low=low; this.close=close; this.vol=vol; this.volchange=volchange; this.priceChange=priceChange; this.rate=rate; } /** * Create a new Record. * Require: * s == unprocessed Equity Tracking Record. */ public FixFixRecord(){ super();//default constructor } ここでカプセル化します。 public void readObject(DataInputStream dis)throws IOException{ try{ this.name =""+dis.readChar(); this.high= dis.readFloat(); this.low= dis.readFloat(); this.close= dis.readFloat(); this.vol=dis.readInt(); this.volchange=dis.readInt(); this.priceChange= dis.readFloat(); this.rate= dis.readShort(); this.symb=dis.readLine(); }catch(FileNotFoundException e){ System.out.println("File not found"); e.printStackTrace(); }catch(IOException e){ System.out.println("File not found"); e.printStackTrace(); } } /** * Write the contents of the current object into the given output stream */ public void writeObject(DataOutputStream dos)throws IOException{ try{ dos.writeChars(this.getName()); dos.writeChars(symb); dos.writeFloat(this.high); dos.writeFloat(low); dos.writeFloat(close); dos.writeInt(this.vol); dos.writeInt(this.volchange); dos.writeFloat(this.priceChange); dos.writeShort(this.rate); dos.close(); }catch (FileNotFoundException e){ System.out.println("File not found"); e.printStackTrace(); }catch (Exception e){ System.out.println("a bad line"); e.printStackTrace(); } } こちらが、ファイルクラス public class FixFix extends FieldRecordFile{ /** * Create a new FixFix with the specified Data File and * Destination File. */ public FixFix(String dataFileName, String destinationFileName) { super(dataFileName,destinationFileName); this.input = new File(dataFileName); this.output = new File(destinationFileName); } /** * The record # n. * Require: * n < Maximum Number Records in File */ public Record getRecord(int n)throws IOException{ Record theRecord=new FixFixRecord(); try{ FileInputStream fis = new FileInputStream(this.input); BufferedInputStream bis= new BufferedInputStream(fis); dis =new DataInputStream(bis);//このあたりが問題です。レコードがあるかどう かチェックする必要があります dis.skipBytes(n*52); dis.mark(n*52); if(dis.read() !=-1){ dis.reset(); theRecord.readObject(dis); String name =""+dis.readChar();//readLine()も試みました。 String smb =""+dis.readChar(); float high = dis.readFloat(); float low =dis.readFloat(); float close = dis.readFloat(); int vol = dis.readInt(); int volChan = dis.readInt(); float pri = dis.readFloat(); short pric = dis.readShort(); dis.skipBytes(40); //ここでオブジェクトを作ってくれません。 theRecord = new FixFixRecord(name,smb,high,low,close,vol,volChan,pri,pric); dis.close(); } }catch (FileNotFoundException e){ System.out.println("File Not Found"); }catch (Exception e){ e.printStackTrace(System.err); } return theRecord; } /** * Get the next record. */ public Record nextRecord(){ ランダムアクセスをしないので、次のレコードを Record theRecord=new FixFixRecord();読むようにします。 try{ FileInputStream fis = new FileInputStream(this.input); BufferedInputStream bis= new BufferedInputStream(fis); dis =new DataInputStream(bis); dis.mark((int)this.numRec*52); theRecord.readObject(dis); if(dis.available() !=-1){ dis.reset(); dis.skipBytes((int)(numRec+1)*75); String name =dis.readLine(); float high = dis.readFloat(); float low =dis.readFloat(); float close = dis.readFloat(); int vol = dis.readInt(); int volChan = dis.readInt(); float pri = dis.readFloat(); short pric = dis.readShort(); String smb =dis.readLine(); dis.skipBytes(20); theRecord = new FixFixRecord(name,smb,high,low,close,vol,volChan,pri,pric); } dis.close(); }catch (FileNotFoundException e){ System.out.println("File Not Found :"+e); }catch (Exception e){ e.printStackTrace(System.err); System.out.println("Error : "+ e); } return theRecord; } input file ALLIANCE BANCOR 21.375 21.000 21.000 15 -15 +0.000 +0 ANEY ABCDEFGEHJKLMNZZZZZZ ATT 90.100 85.102 88.000 111111 -1111 +2.100 +2 TTTT ABCDEFGEHJKLMNZZZZZZ CORT BUSINESS 47.812 46.250 47500 199 -9 +1.312 +3 CBZL ABCDEFGEHJKLMNEEZZZZ HINGHAM 37.000 37.000 37.000 3 -96 +2.750 +8 HIFS ABCDEFGEHJKLMNDDZZZZ KEANE 56.500 54.875 56.500 12018 +343 +2.000 +4 KEAL ABCDEFGEHJKLMNZFFZZZ 後ろの文字は、VerIndのみ読み込むようにするので、FixFixではskipByteを使う必要があります。 後ろから2番目の項目(シンボル)は名前の次、前から2番目にくるようにします。 いろいろ、位置を変えてみましたが、どうもしっくりいきません。 | ||||
|
投稿日時: 2003-03-07 09:53
unibon です。こんにちわ。
#DataInputStream/DataOutputStream はあまり使った経験がないので、 #以下、多少勘違いしてるかもしれませんが。 やはり、おっしゃるように mark/skip/reset などの、 位置合わせが難しくそれが大きな問題だと思います。 また、 > String name =""+dis.readChar();//readLine()も試みました。 などで出現している readChar は1文字だけを読むメソッドであり、 文字列を読むものではないはずです。 あと、そもそも、ファイルを固定長のブロック単位で読み書きする必要があるのか、 ということから再検討されても良いかもしれません。 シーケンシャルに、延々とファイルに書き込み、 それをファイルから読み込む際も、skip/mark/reset などで前後することもなく読み続け、 たとえば10番目のレコードだけほしいなら、 9番目までのレコードは読み捨てるというのも手です。 このような完全なシーケンシャルでよいなら、たとえば、 ObjectInputStream/ObjectOutputStream(Serializable/Externalizable 関連)を使ったり、 あるいは、文字列を考慮した、 DataInputStream.readUTF/DataOutputStream.writeUTF なども使えるなど、 設計の自由度は高まります。 また、もし、今のままで進めるとしたら、 とりあえずは扱いの難しい文字列は含めずに int や float だけを読み書きしてみることを試されてはどうでしょうか。 | ||||
|
投稿日時: 2003-03-07 18:13
コンバンワ、YKIDです。
いや、それ以前に、同じようなコードがいっぱいあって、ソースが無駄に冗長なような気がするのですが・・・。 Recordクラスと、FixFixRecordクラスは継承関係にあるように見受けられるのに、Recordクラスのコンストラクタと、FixFixRecordのコンストラクタは同じ事(値の代入)をしているのはなぜですか? ファイルから値を読込むコード(どのクラスかは不明ですが、getRecord()とかnextRecord()とかreadObject()とかいうメソッド)がいくつもかかれているのですが、なぜですか? 失礼ですが、要件を整理してクラス設計からやり直したほうが良いかと。 | ||||
|
投稿日時: 2003-03-08 07:02
ReaderはASCIIでDataInputStreamはByteで処理します。そのために似たようなメソッドがあります。FixFixのクラスでは、データの変更があってもいじることのないように、recordクラスがあります。DataInputStreamは、Stringがないので、Byteで読むようなのですが、どのように処理をしてよいのか今ひとつ分かりません。
| ||||
