InputStreamのread()関数

このQ&Aのポイント
  • InputStreamのread()関数とは?
  • FilterInputStreamとの関係について
  • Socketを使用したInputStreamの読み取り
回答を見る
  • ベストアンサー

InputStreamのread()関数

InputStreamの関数 public abstract int read()throws IOException サブクラスはこの関数をオーバーライドする。 ところがFilterInputStreamはInputStreamを変数にもちread()を呼び出している。(↓を参照) http://java.sun.com/javase/ja/6/docs/ja/api/java/io/FilterInputStream.html#read() サブクラスでオーバーライドするなら、そもそも変数でInputStreamがもてる時点でおかしいわけです。 他にも同じようなものに Socket sock; InputStream is = sock.getInputStream(); これでなぜかis.read()が使える。

  • Java
  • 回答数5
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.5

>いや、しかし、 >Socketでは >public InputStream getInputStream()throws IOException > > その説明では >public HogeStream getInputStream() > > で無ければならず。 引数の時と同じ理屈です。 getInputStream() は InputStream の何かの派生クラスのインスタンスを「実行時に状況に応じて」戻します。 コードを書く時には、実行時に戻ってくる具体的な型はわからないけれど、 InputStream の派生クラスであることはわかっています。 そのため、InputStream 型の変数 in を宣言して、これで InputStream の派生クラスのオブジェクトを受け取っているのです。 InputStream には read() が仮想関数として宣言されているので、その派生クラスは read() を実装しているはずです。 これによって in.read() に必ず意味があることが保証され、 「実行時に」getInputStream() から戻されたインスタンスが実装している read() が呼び出されます。

その他の回答 (4)

  • aton
  • ベストアンサー率47% (160/334)
回答No.4

koko_u_さん,大変ですね。 質問者というより,このサイトを利用するJava/オブジェクト指向言語学習者のために回答を書きます。 本質的には継承に関する理解の問題だと思います。 > Socket sock; > InputStream is = sock.getInputStream(); > これでなぜかis.read()が使える。 こちらの例の方が説明が簡単なのでこっちを使いますが,このとき変数isに入っているのは,InputStreamクラスそのもののインスタンスである必要はなく,その派生クラス(例えばByteArrayInputStreamやFileInputStream)のインスタンスであってもいい(*注),というのが継承の持つ機能の一つです。 注: 実際はInputStreamの派生クラスのうちのコンクリートクラスのどれかが入っていると考えるのが普通。 以下のようなコードを書いて動かしてみれば理解できるかもしれません。 abstract class AA { abstract void aMethod(); } class BB extends AA { void aMethod() { System.out.println("BB"); } } class CC { AA getAA() { return new BB(); } } class DD { public static void main(String[] args) { CC cc = new CC(); AA aa = cc.getAA(); aa.aMethod(); } }

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.3

>>「実装を移動する」とはどのようなコトを指しているのですか? >これの実際の処理内容はどこに書いてますか? >public abstract int read() throws IOException; うーん。会話が成立していない。抽象メソッドだから、その派生クラスで read() は実装される。 ここまではいいですよね。 >>InputStream は抽象クラスなので、これは「InputStream の派生クラスをコンストラクタに渡せ」という意味です。 >同じ名前で派生クラスを作ろうとするとエラー(ループ)になるのでは?どうやってその派生クラスを作ったのか? >class InputStream extends InputStream() だから class HogeStream extends InputStream { ... } と「派生クラスを」定義するのです。 FilterStream のコンストラクタの引数は InputStream 型ですが、これは InputStream の派生クラスのすべてを 引数として受け取ることができることを意味しています。 これは OK?

osiete_kun
質問者

補足

いや、しかし、 Socketでは public InputStream getInputStream()throws IOException その説明では public HogeStream getInputStream() で無ければならず。

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.2

>全然違うと思う。(またはその実装はどこにありますか?) 実装は InputStream の派生クラスの中。 >実装まで移動できない。 「実装を移動する」とはどのようなコトを指しているのですか?再度補足して下さい。 FilterInputStream のコンストラクタは InputStream を引数としていますね? InputStream は抽象クラスなので、これは「InputStream の派生クラスをコンストラクタに渡せ」という意味です。 InputStream の派生クラス HogeStream のインスタンス hoge をもって stream = new FilterStream(hoge); すると、stream の保持するメンバ変数 in は hoge です。 実行時にどこかで in.read() したときに、polymorphism が発動して、hoge に実装された read() が呼び出されます。

osiete_kun
質問者

補足

>「実装を移動する」とはどのようなコトを指しているのですか? これの実際の処理内容はどこに書いてますか? public abstract int read() throws IOException; >InputStream は抽象クラスなので、これは「InputStream の派生クラスをコンストラクタに渡せ」という意味です。 同じ名前で派生クラスを作ろうとするとエラー(ループ)になるのでは?どうやってその派生クラスを作ったのか? class InputStream extends InputStream()

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

>ところがFilterInputStreamはInputStreamを変数にもちread()を呼び出している。 リンク先はまったく見てませんが、それが polymorphism というやつでしょう。 FilterInputStream は InputStream の「派生クラスとなる何か」をメンバーとして保持することができ、 インスタンス毎に様々な InputStream の派生クラスのインスタンスをそのメンバー変数として持てる。 そして、read() を呼び出すと、その派生クラスに応じた read() の実装が実行時に呼び出される。 そんな感じだと思う。 >Socket sock; >InputStream is = sock.getInputStream(); > これでなぜかis.read()が使える。 これも getInputStream() が InputStream の派生クラスの何かを戻しているはずです。

osiete_kun
質問者

補足

>そして、read() を呼び出すと、その派生クラスに応じた read() の実装が実行時に呼び出される。 全然違うと思う。(またはその実装はどこにありますか?) 実装まで移動できない。 プログラムにはread(byte b[])を使ったので 実際にread(byte b[])を使って移動してみると read(byte b[]) は read(b, 0, b.length) を呼び出す。 read(b, 0, b.length) はread()を呼び出す。 read()は public abstract int read() throws IOException; となっていてこれ以上移動できない。

関連するQ&A

  • InputStream.read()でタイムアウトの処理をしたい。

    InputStream.read()でタイムアウトの処理をしたい。 現在自分は、InputStreamに入力されたデータをOutputStreamに移したいとかんがえているのですが、途中でreadメソッドが固まってしまいうまくいきません。 ソースで説明させていただきますと、 public static int copy(InputStream input,OutputStream output)throws IOException { byte[] buffer = new byte[1024 * 4]; int count = 0; int n = 0; while (0 < (n = input.read(buffer))) //ここで固まる { output.write(buffer, 0, n); count += n; System.out.println("available = " + input.available()); System.out.println(count + " byte = " + n); } return count; } このようなコピーするメソッドを書いたのですが、何度かループした後readメソッドで固まってしまいます。また、availableは常に0を返しております。 おそらくストリームの終わりが検出できないため、このような状態になっていると推測されるのですが、プログラムの性質上、InputStreamに入ってくるデータを変更することはできません。 なのでこの問題を解決するべく、ある程度の時間readメソッドがブロックされたら、breakするというような処理を書きたいのですが、どのようにすればよいでしょうか?

    • ベストアンサー
    • Java
  • ソケット通信の受信で、InputStreamの終了が認識出来ません。

    ソケット通信の受信で、InputStreamの終了が認識出来ません。 (1)下記のネット上で見つけたチャットクライアントのソース"ChatClient.java"を流用しました。  http://www.saturn.dti.ne.jp/~npaka/android/SocketEx/index.html (2000文字を超えるので掲載出来ません)  チャットサーバもこのサイトのソースを実装しました。この組み合わせで送受信は確認しました。 (2)これに下記のjavaのオープンソースを実装して、バイト読み出しに変更します。  【"java\io\InputStream.java"より】   public int read(byte b[]) throws IOException {  //※1     return read(b, 0, b.length);      //※2   }   public int read(byte b[], int off, int len) throws IOException {//※3     if (b == null) {       throw new NullPointerException();     } else if ((off < 0) || (off > b.length) || (len < 0) ||         ((off + len) > b.length) || ((off + len) < 0)) {       throw new IndexOutOfBoundsException();     } else if (len == 0) {       return 0;     }     int c = read();    //※4     if (c == -1) {       return -1;     }     b[off] = (byte)c;     int i = 1;     try {       for (; i < len ; i++) {       c = in.read();       if (c == -1) {         break;       }       if (b != null) {         b[off + i] = (byte)c;       }       }     } catch (IOException ee) {     }     return i;   }  ・リンク先のソース中の入力ストリーム読み出し部の名前の付け替え  size=in.read(w); → size=readsocket(w);  ・javaのオープンソース"java\io\InputStream.java"中の名前の付け替え   ※1:public int readsocket(byte b[]) throws IOException {   ※2:return readsocket2(b, 0, b.length);   ※3:public int readsocket2(byte b[], int off, int len) throws IOException {   ※4:int c = in.read(); (3)この変更を行うと、※4の“in.read()”で入力ストリームの終了の"-1"が入って来ず、forループから抜けなくなってしまいました。帰って来るのは送信したコードのみです。どこが悪いのでしょうか?

    • ベストアンサー
    • Java
  • javaのソケット通信の受信で、InputStreamの終了が認識出来

    javaのソケット通信の受信で、InputStreamの終了が認識出来ません。 (1)下記のネット上で見つけたチャットクライアントのソース"ChatClient.java"を流用しました。  http://www.saturn.dti.ne.jp/~npaka/android/SocketEx/index.html  チャットサーバもこのサイトのソースを実装しました。この組み合わせで送受信は確認しました。 (2)これを下記のjavaのオープンソースを実装して、バイト読み出しに変更しました。  ・上記の元のソースの受信ループ中の読み出し部   size=in.read(w); → size=readsocket(w);  【"java\io\InputStream.java"より】   public int read(byte b[]) throws IOException {  //※1     return read(b, 0, b.length);      //※2   }   public int readsocket2(byte b[], int off, int len) throws IOException {//※3     if (b == null) {       throw new NullPointerException();     } else if ((off < 0) || (off > b.length) || (len < 0) ||         ((off + len) > b.length) || ((off + len) < 0)) {       throw new IndexOutOfBoundsException();     } else if (len == 0) {       return 0;     }     int c = read();    //※4     if (c == -1) {       return -1;     }     b[off] = (byte)c;     int i = 1;     try {       for (; i < len ; i++) {       c = in.read();       if (c == -1) {         break;       }       if (b != null) {         b[off + i] = (byte)c;       }       }     } catch (IOException ee) {     }     return i;   } ・上記の名前の付け替え   ※1:public int readsocket(byte b[]) throws IOException {   ※2:return readsocket2(b, 0, b.length);   ※3:public int readsocket2(byte b[], int off, int len) throws IOException {   ※4:int c = in.read(); (3)この変更を行うと、“in.read()”でストリームの終了の"-1"が入って来ず、forループから抜けなくなってしまいました。帰って来るのは送信したコードのみです。どこが悪いのでしょうか?

    • ベストアンサー
    • Java
  • バイナリファイルでOutOfMemoryエラー

    お世話になります。 ブラウザ画面からファイルをアップロードし、そのバイナリデータを返すメソッドを作成したのですが、約50MB以上のファイルを使用するとOutOfMemoryエラーとなりJava heap spaceが足りないといわれてしまいます。ヒープサイズをあげればエラーはしなくなるとはおもいますが、根本的な解決にはならないと思います。 public byte[] upload(FormFile ff) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream is = ff.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); byte[] byteData; try { int data = 0; byte[] buffer = new byte[1024]; while ((data = bis.read(buffer) != -1) { baos.write(buffer, 0, data); } byteData = baos.toByteArray(); } catch (IOException e) { throw e; } finally { if (null != bis) { bis.close(); } } return byteData; } 以上のようなメソッドなのですが、おかしい点はありますでしょうか。 指摘していただけると助かります。 よろしくお願いいたします。

    • ベストアンサー
    • Java
  • 圧縮クライアントのプログラム

    java eclipeを使って通信のプログラムを勉強しています。 参考にしている本は、TCP/IPソケットプログラミングjava編です。 本に書かれてるソースコードのとおりに入力したら、 Exception in thread "main" java.io.FileNotFoundException: test.txt (No such file or directory) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at java.io.FileInputStream.<init>(Unknown Source) at socket_127.CompressClient.main(CompressClient.java:20) というエラーが出ました。 このエラーを調べると、 「指定されたパス名で示されるファイルが開けなかったことを通知します。」とかかれていました。このプログラムが入っているフォルダの中にtest.txtというテキストファイルを作成して同じフォルダに入れてあります。 このプログラムの引数は、 <Server> IPアドレス <Port>  110 <File> test.txt としました。 このエラーをとる方法を教えていただけないでしょうか? 下にソースコードを載せますので、解決方法をお願いします。 package socket_127; import java.net.*; // for Socket import java.io.*; // for IOException and [File]Input/OutputStream public class CompressClient { public static final int BUFSIZE = 256; // Size of read buffer public static void main(String[] args) throws IOException { if (args.length != 3) throw new IllegalArgumentException("Parameter(s): <Server> <Port> <File>"); String server = args[0]; int port = Integer.parseInt(args[1]); String filename = args[2]; FileInputStream fileIn = new FileInputStream(filename); FileOutputStream fileOut = new FileOutputStream(filename + ".gz"); Socket sock = new Socket(server, port); sendBytes(sock, fileIn); InputStream sockIn = sock.getInputStream(); int bytesRead; byte[] buffer = new byte[BUFSIZE]; while ((bytesRead = sockIn.read(buffer)) != -1) { fileOut.write(buffer, 0, bytesRead); System.out.print("R"); } System.out.println(); sock.close(); fileIn.close(); fileOut.close(); } private static void sendBytes(Socket sock, InputStream fileIn) throws IOException { OutputStream sockOut = sock.getOutputStream(); int bytesRead; byte[] buffer = new byte[BUFSIZE]; while ((bytesRead = fileIn.read(buffer)) != -1) { sockOut.write(buffer, 0, bytesRead); System.out.print("W"); } sock.shutdownOutput(); } }

  • javaについて>IEのクッキーを使いたい

    IEでログインした状態であれば、ヤフーメールなどクッキーを使うHPにアクセスできるかと思ったのですがアクセスできません。どうすればよいでしょうか? 多分、javaはIEのクッキーを利用していないのですよね・・・ 何とか、IEのクッキーを利用できれば良いのですが。何か、良いお知恵はありませんでしょうか? 宜しくお願い致します。 以下、コードです。 ーーーーーーーーーーーーーーーーーーーーーーー import java.io.*; import java.net.*; class Test { static String input() throws IOException { InputStream is = new FileInputStream("url.txt");//urlを入力 BufferedReader br = new BufferedReader(new InputStreamReader(is)); String str = br.readLine(); return(str); } static void read(String str) throws IOException { OutputStream os = new FileOutputStream("log.txt",true); BufferedWriter fr = new BufferedWriter(new OutputStreamWriter(os)); URL url = new URL(str); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(),"JISAutoDetect")); for (;;) { String i = in.readLine(); if(i == null) { break; } System.out.println(i + "\n"); fr.write(i + "\n"); } in.close(); fr.close(); } public static void main(String[] args) throws IOException { Test brow = new Test(); brow.read(brow.input()); } }

    • ベストアンサー
    • Java
  • サーブレットで文字化け

    サーバ Fedora Core 6 / tomcat5.5 クライアントもFedoraなら文字化けしません。 ウィンドウズxpから接続すると文字化けします。 アプレットのプログラムで送信する関数のみ抜粋した。引数sが送信する文字列でこれが文字化けします。送信した変数sをJLabelで表示するとウィンドウズでも文字化けしてなかった。そしてサーバー側のログは文字化けしていたのですが原因がわかりません。どうしたらいいですか? //■アプレット側 文字列送信用関数 public void send(String s) { try { sock = new Socket(サーバのIPアドレス,9999); //■サーバーに接続 fin = sock.getInputStream(); fout = sock.getOutputStream(); ffin = new InputStreamReader(fin); in = new BufferedReader(ffin); out = new PrintWriter(fout,true); out.println("POST / HTTP/1.1"); out.println("Accept: */* "); out.println("Accept-Language: ja"); out.println("Accept-Encoding: gzip,deflate"); out.println("User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"); out.println("Host: "+getParameter("ipAddress")); out.println("Content-Type: application/x-www-form-urlencoded; charset=UTF-8"); out.println("Content-Length: "+(s.getBytes("UTF-8").length)); out.println("Connection: Keep-Alive"); out.println(""); out.println(s); } catch(IOException e) { } } サーバー側 変数sの表示 public void service(HttpServletRequest req, HttpServletResponse res)throws ServletException,IOException { //■通信関係 PrintWriter out; BufferedReader in; //■入力した文字列 String st,str; try { //■通信開始 in = new BufferedReader(new InputStreamReader(req.getInputStream())); out = new PrintWriter(res.getOutputStream(),true); //■文字列読み込み st = in.readLine(); str = new String(st.getBytes("UTF-8")); System.out.println("受信した文字列"+str);

  • 403を返されてしまいます。

    グーグルの検索結果を取得したいのですが 以下のようなプログラムでは403を返されてしまいます。 他のページではちゃんと取得できるのですが 原因は何なんでしょうか。また、これを回避する方法はあるのでしょうか? import java.net.*; import java.io.*; public class test { public static void main(String args[]) { try { URL objURL = new URL("http://www.google.co.jp/search?hl=ja&q=java&lr="); URLConnection objURLCnn = objURL.openConnection(); InputStream inputStream = objURLCnn.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "JISAutoDetect")); String line; while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } java.io.IOException: Server returned HTTP response code: 403 for URL: http://www.google.co.jp/search?hl=ja&q=java&lr= at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source) at test.main(test.java:10)

  • InputStreamはreadが1回しかできない?

    1つのFileInputStreamのクラスから2つのFileOutputStreamのクラス (仮にOutputStream1、OutputStream2とします)へwriteし、 ファイル2つを作成しようとしています。 最初にOutputStream1へwriteし、次にOutputStream2へwriteしたとき、 両方のStreamで作成したファイルが空(0KB)の状態になってしまいます。 1つのInputStreamから連続して2つ以上のOutputStreamに書くことはいけない ことなのでしょうか?(どうしてもやりたいのですが) もしかしてFileInputStreamの完全なコピー(cloneじゃなくシリアライズして 複製を作成する)を作る方法しかないのでしょうか?とはいうものの シリアライズできるInputStreamクラスを作成できず困っていたりします。 (あとOutputStreamをInputStreamに変換できたらなぁとかも思うの  ですが無理ですよね・・・?) どなたかご存じの方、是非ご教授下さい。

    • ベストアンサー
    • Java
  • java:読み込んだデータの確認

    javaを使って通信のプログラムをつくっています。 送信側でバイトデータを作成して送信します。そして受信側でそのバイトデータを読み込みます。 送信側で作ったバイト数が本当に受信側に届いたかのチェックをするには、 どうすればよいでしょうか?下のコードは、自作した受信処理です。 調べると、read(byte[] b,int off,int len)の返り値が読み込んだバイト数ということなので、 これを使うのではないかと思うのですが、どう使えばよいか分かりません。下のコードは、とりあえず、受信したらcount++として受信処理分だけ countを増やして受信したバイトを数えています。 readの返り値で受信したバイト数を取得するには、どうすればよいでしょうか? 御教授お願いします。 送信側 BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream()); for (int i = 0; i < Data; i++) {   for (;;) {     try {       out.write(i);       out.flush();       count++;       break;     } catch (IOException e) {       System.err.println((count + 1) + "つ目のバイト:書き込みエラー>>再書き込み");     }   } } 受信側 BufferedInputStream in = new BufferedInputStream(sock.getInputStream()); int ch = 0; // 読み込んだ文字 int Count = 0; // 届いたバイト数のカウンター while (ch != -1) {   try {     ch = in.read(); Count++;   } catch (IOException e) {     System.err.println(Count + "つ目のバイトデータ:読み込みエラー");   } }

    • ベストアンサー
    • Java

専門家に質問してみよう