- PR -

DataOutputStreamへのCast

1
投稿者投稿内容
NO
会議室デビュー日: 2003/03/02
投稿数: 15
投稿日時: 2003-03-21 21:22
BufferedOutputStream[i]からDataOutputStreamのキャストでエラーが出てしまいます。対処の仕方の分かる方いらっしゃいませんか。

具体的には
//construcotr
this.inStream = new BufferedReader(new FileReader(inFile));
this.outStream=new BufferedOutputStream[n];
for(int i=0;i<n;i++){
String filename=filePref+(i+1);
this.outStream[i]= new BufferedOutputStream(new DataOutputStream(new FileOutputStream(filename)),bSize);

レコードを読みこむ
this.seedRec.readObject(this.inStream);

レコードクラスで受け取る
public void readObject(Reader r)throws IOException{
String s="";
BufferedReader br = (BufferedReader)r;
try{
s= br.readLine();
if(s ==null)
return;
StringTokenizer lineTokenizer = new StringTokenizer(s);
this.id = Integer.parseInt(lineTokenizer.nextToken());
this.salary = Float.parseFloat(lineTokenizer.nextToken());
this.name = lineTokenizer.nextToken();
}catch(IOException e){}

そして、また元のクラスに戻りソート後書きこむ
outputItem.writeObject(outStream[i]);

そしてレコードクラスでjava.lang.ClassCastException: java.io.BufferedOutputStream
public void writeObject(OutputStream os) throws IOException {
DataOutputStream dos = (DataOutputStream)os;
try {
dos.writeInt(this.id);
dos.writeFloat(this.salary);
dos.writeInt(this.name.length());
dos.writeChars(this.name);
dos.flush();
} catch (IOException e) {

}
}

maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-03-21 22:11
こんにちは。
>BufferedOutputStream[i]からDataOutputStreamのキャストでエラーが出てしまいます。
BufferedOutputStream[i]からDataOutputStreamへキャストしている個所が見当たりま
せんが???

writeObjectメソッドの DataOutputStream dos = (DataOutputStream)os のことなら、
DataOutputStream dos = new DataOutputStream(os) では?
クラスの継承関係をヘルプで見直してみては?
あと、
this.outStream[i]= new BufferedOutputStream(new DataOutputStream(new FileOutputStream(filename)),bSize); は、
this.outStream[i]= new BufferedOutputStream(new FileOutputStream(filename),bSize); ではだめ?

違ってたらごめんなさい。

エラーがでるなら、Javaの場合はエラーがでるソースと行数がわかるので、エラーの
個所は特定できるでしょう。具体的にと前置きしてるわりに、不要な個所のソースも含め貼
り付けるのは、いかがなものかと。もっと不具合を絞り込んで、それでもわからなければ
わからない個所を簡潔に質問したほうがいいのでは?(^^;

キャストのエラーがでるという程度で、解析してといわんばかりにソース貼り付けて、
具体的に何をしたという説明もなく、わかる方いませんか?というのはいかがなものかと
思うのですが?(^^;
NO
会議室デビュー日: 2003/03/02
投稿数: 15
投稿日時: 2003-03-22 05:21
不要な所を書き込んだつもりはありません。なぜ"new"にしなかったかというと、読み込みと同様、Distrubutorクラスとのつながりがあるからです。まず、クラスDistributorのコンストラクタで、ファイルを指定したbufferサイズで読み、n個の書き込みファイルを作ります。ここで、DataOutputStreamをラップしておく必要があると考えられます。このことは重要だと思い、表示しました。次に、DistributorクラスのメソッドDistributeでBinariTree(HeapArea)を作ります。その次にreadObject(Sortable)で、interface SortableのimplementationクラスRecordで、読み込みます。もし、ここでnewを使うと、レコードは一つしか読み込みません。ここで、読み込んだレコードは、Distributeでしていした回数、(heapサイズ)を繰り返したのち、ソートされます。ここでは、サラリーの高い順にソートされるので、Maxナンバーから順にファイルに書き込まれます。このDistributeで受けたMaxをRecordクラスで書き込みます。この時、Castに失敗します。
以上のように、2つのクラスとのつながりがあるので、2つのクラスを表示しました。無駄はないはずです。逆に書かないと返って分からなくなると思います。maruさんのおっしゃっていることは、一番最初にやったことです。それで駄目だったので、前回表示した結果になりました。どなたか、きっとこのことを理解されている方がいらっしゃるかと思い、投稿しました。writeObjectのparameterをDataOutputStreamにする手もあると思いますが、そうするとinterfaceSortableも変えることになります。
maruさんのおっしゃる
>BufferedOutputStream[i]からDataOutputStreamのキャストでエラーが出てしまいます。
BufferedOutputStream[i]からDataOutputStreamへキャストしている個所が見当たりま
せんが???
は意味がわかりません。iはrunの数ですが...

改めて、どなたか他にいい案をお持ちの方はいらっしゃいませんか。
へげもん
ベテラン
会議室デビュー日: 2002/04/14
投稿数: 87
お住まい・勤務地: 埼玉県
投稿日時: 2003-03-22 07:27
いい案も何も、BufferedOutputStream を DataOutputStream にキャストすることは不可能です。これらは継承関係にないのですから。maruさんが書いてるように、Java APIのヘルプを見れば次のように載ってます。
コード:
java.lang.Object
  |
  +--java.io.OutputStream
        |
        +--java.io.FilterOutputStream
              |
              +--java.io.DataOutputStream

java.lang.Object
  |
  +--java.io.OutputStream
        |
        +--java.io.FilterOutputStream
              |
              +--java.io.BufferedOutputStream


このように、両者は親子関係になく、兄弟関係なのでキャストはできません。

引用:

ここで、DataOutputStreamをラップしておく必要があると考えられます。このことは重要だと思い、表示しました。



念のためですが、コンストラクタで
new BufferedOutputStream(new DataOutputStream(...),bSize);
とやっても、継承関係はまったく変わりませんので、キャストできないことにも変わりありません。

今回のコードは、maruさんが書いているように、下記のようにするだけで十分だと思いますが、何か問題がありますか?
コード:
//construcotr 
this.inStream = new BufferedReader(new FileReader(inFile)); 
this.outStream=new BufferedOutputStream[n]; 
for(int i=0;i<n;i++){ 
	String filename=filePref+(i+1); 
	this.outStream[i]= new BufferedOutputStream(
		new FileOutputStream(filename),bSize); 
}

//another method
for(int i=0;i<n;i++){ 
	outputItem.writeObject(outStream[i]); 
}

public void writeObject(OutputStream os) throws IOException { 
	DataOutputStream dos = new DataOutputStream(os); 
	dos.writeInt(this.id); 
	dos.writeFloat(this.salary); 
	dos.writeInt(this.name.length()); 
	dos.writeChars(this.name); 
	dos.flush(); 
} 


maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-03-22 09:12
こんにちは。
引用:

BufferedOutputStream[i]からDataOutputStreamへキャストしている個所が見当
たりませんが???


どの部分のことかはだいたいわかりましたが、あえて文書の頭にこのようなことを書
きました。この問題を考えたとき、BufferedOutputStreamをDataOutputStreamで
キャストしている個所(エラーが出ているといわれる個所)をさがして、
ここにかかれている os は OutputStream だが、言われているのは
DataOutputStream dos = (DataOutputStream)os のことかと推測を立てて、ソース
を逆に追っかけて ・・・ outStream[i]に BufferedOutputStreamを入れているのが
あって・・・と、やっと(といってもそんなに時間のかかるものでもないが)BufferedOutputStream と DataOutputStream が結びつきました。

今回の問題は、「キャストでエラーが出ている」という原因とその個所がはっきりしている
はずです。その問題と、Distrubutorクラス、ファイルを指定したbufferサイズ、
BinariTree(HeapArea)、サラリーの高い順・・・うんぬんかんぬん・・・関係ないの
ではないですか?今作られているソースを貼り付けられたのでしょうが、質問する場合は
問題部分を整理して、

BufferedOutputStream outStream = new BufferedOutputStream(
new DataOutputStream(new FileOutputStream(filename)),bSize);
DataOutputStream dos = (DataOutputStream)outStream;
キャストでエラーが出てしまいます。

程度にまとを絞って掲示板にあげたほうがいいとおもいますよ。そうすれば、もっと気楽
にアドバイスしてくれる人は増えると思います(^^;
そう思ったのは私だけではないと思います。

>maruさんのおっしゃっていることは、一番最初にやったことです。それで駄目だった
???


[ メッセージ編集済み 編集者: maru 編集日時 2003-03-22 09:50 ]
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-03-22 13:16
>DataOutputStreamをラップしておく必要がある
ここで言っているラップをどういう意味で使われているのかは、正確にはわかりませんが、
これは単に、BufferedOutputStreamのコンストラクタの引数に OutputStream型のクラス
(BufferedOutputStream と DataOutputStreamの親でもある)を渡しているだけではない
ですか?このように書いても outStream[i] が DataOutputStream になるわけではないと
思いますが。

私もJavaのクラス継承とキャストについて、正確に理解できているかは不安ですが、
自分のためにも再確認してみました。

OutputStream と BufferedOutputStream と DataOutputStream は、おそらく以下の
ソースのような関係になると思います。
※逆コンパイルしたわけではないのでわかりませんが・・・。

今回は、どちらかといえばパターンBに近いのではないでしょうか?

<参考ソース>
// 親クラス(OutputStreamに相当)
class Parent {
int a;
public void ABC(){
}
}

// 子クラス1(BufferedOutputStreamに相当)
class Child1 extends Parent{
Parent p;
public Child1(){}
public Child1( Parent p ){
this.p=p;
}
public void DEF(){
}
}

// 子クラス2(DataOutputStreamに相当)
class Child2 extends Parent{
Parent p;
public Child2(){}
public Child2( Parent p ){
this.p=p;
}
public void GHI(){
}
}

// テスト
class Test{
public static void main(String[] args){

// パターンA
Parent p1 = new Child1(); // Child1オブジェクトを親の Parent型の変数にいれる。親子関係なので可能。
// p1.DEF();//コンパイル時にエラー。元のオブジェクトはChild1だが使える機能はParentのもの
Child1 c1 = (Child1)p1; //上記変数の元のオブジェクトはChild1なのでChild1でキャストが可能。オブジェクトは同じ物をさしている。
c1.DEF();
// Child2 c2 = (Child2)p1; // これは実行時にキャストでエラー。親子関係ではないのでNG。キャストしたからといって子クラス1のオブジェクトに子クラス2の機能が追加されるわけではない。

// パターンB
Parent c3 = new Child1( new Child2( new Parent() ) );//コンストラクタ引数にChild2でラップ(?)しているわけではなく、Parent型の引数を渡しているだけ。
// Child2 c4 = (Child2)c3; // これも実行時にキャストでエラー。c3にChild2の機能が追加されているわけではない。

}
}

[ メッセージ編集済み 編集者: maru 編集日時 2003-03-22 13:37 ]
asip
ベテラン
会議室デビュー日: 2001/12/27
投稿数: 77
投稿日時: 2003-03-23 18:05
>OutputStream と BufferedOutputStream と DataOutputStream は、おそらく以下の
>ソースのような関係になると思います。

デザインパターンの1つ、Decoratorパターンですね。
デザインパターンの本をみると、必ずjava.ioが具体例として紹介されてます。

>※逆コンパイルしたわけではないのでわかりませんが・・・。
JDKのインストール時に選択しておけば、ルートディレクトリに"src.zip(or src.jar)"
があります、解凍すればJavaAPIの全ソースが見れます。逆コンパイルする必要は...
ありません。

[ メッセージ編集済み 編集者: asip 編集日時 2003-03-23 18:22 ]
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-03-24 10:46
こんにちは。

>デザインパターンの1つ、Decoratorパターンですね。
そうなんですか。デザインパターンって言葉は最近よく見かけますが、どんな物かよく知ら
なかったり、フレームワークとごっちゃになってたりで興味ありませんでした。
そろそろJavaにもなれてきたので、ここらへんも勉強してみます。(^^)
1

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