#author("2019-11-28T14:41:02+09:00","ocha","ocha")
#author("2019-11-28T15:46:27+09:00","ocha","ocha")
[[Lecture]]

*Java プログラミング入門 [#kd7c750b]
*Java プログラミング入門 [#de53d4fb]


このページは、学部2年生向け授業である、「マルチメディアプログラミング実習」
のために用意しました。

(Wikiの仕様で大文字小文字が混在した英単語に疑問符?が追加されるところがありますが、無視してください。)


**第12章 Swing [#n78c2cf0]
**第11章 入出力 [#hb3a05b8]


SwingはJavaのパッケージで、GUIを構築するための数多くのclassが含まれています。例えば、ウィンドウを作成するためのクラス、ボタンを作成するためのクラス、メニューを作成するためのクラスなどがあります。
Javaの入出力は、ファイル、ネットワーク、キーボード、ディスプレイを対象としています。C言語に比べて、高機能な上に、ネットワークへの入出力も標準装備されているところが便利です。

***歴史(AWTとの違い) [#f1351d32]
 (ファイル、ネットワーク、キーボード)
     |
     | 入力ストリーム
     |
     V
 (Javaプログラム)
     |
     | 出力ストリーム
     |
     V
 (ファイル、ネットワーク、ディスプレイ)

初期のJavaでは、AWT (Abstract Window Toolkit) というパッケージが使われていました(今でも使えます)。AWTを使っても、ウィンドウ、ボタン、メニューなどを全部作ることができます。でも、Swingに移行しています。AWTとSwingでは作れるGUIの見た目が違います。AWTは、Java独特のGUIになります。それに対して、Swingでは、稼働しているOSのGUIに近い形のアプリケーションが作れます。例えば、AWTでメニューバーを作ると、Windows風に、ウィンドウ上部にメニューバーが現れます。他のmacOSのアプリと一緒に使うと、違和感があります。それに対して、Swingでは、画面上部にメニューバーが現れます。
**バイトストリーム [#h69eaef6]

データを入出力するのがバイトストリームです。
ここでは、

***クラスJFrame [#t7348676]
- File Output Stream
- Data Output Stream
- File Input Stream
- Data Input Stream

まずはJFrameというSwingのクラスを使います。Frameは枠のことで、ウィンドウです。
JはJavaのJです。
を使ってみます。

以下のリンクからJFrameクラスを選択して、何ができるかざっと見ておきましょう。
*** File Output Streamを使ってバイト単位で書き出し [#e74b0e4e]

こちらで機能を確認しましょう。

https://docs.oracle.com/javase/jp/8/docs/api/index.html

- 次に簡単なウィンドウを出してみましょう。
基本的なインスタンスメソッドは、writeとcloseです。writeには1バイトの書き込み、バイト配列の書き込みがあります。IOExceptionを投げるので、キャッチします。

授業の最初で作ったウィンドウを出すプログラムです。
 write(int b)

 import javax.swing.JFrame;
 public class SimpleWindow {
は、int型の引数の下位1バイトを書き出します。以下のプログラムでファイルに1バイト書き出すことができます。

 import java.io.*;
 
        public static void main(String argv[]) {
                JFrame f = new JFrame("私が作った最初の窓");
                f.setSize(200,100); 
                f.setVisible(true);
        }
 public class FoutTest {
 	public static void main(String[] args) {
 		try {
 			FileOutputStream fout = new FileOutputStream("fout.dat");
 			fout.write(1234);
 			fout.close();
 		}
 		catch (IOException e) {
 			System.out.println(e);
 		}
 	}
 }

これでfout.datという名前のファイルができあがるはずです。 作ったファイルを

 hexdump fout.dat

してみてください

 $ hexdump fout.dat 
 0000000 d2                                             
 0000001

1234は0x4d2だったのでその下1バイトが書き込まれました。

***Data Output StreamでJava整数型データを出力する [#l6a1be55]

こちらで機能を確認しましょう。

https://docs.oracle.com/javase/jp/8/docs/api/index.html

Javaのいろいろなデータ型を書き出すことができます。
int, long, short, float, double, booleanなどのデータを書き出します。
以下では、int型データを書き出しています。
なお、Data Output StreamはFile Output Streamの機能を利用しています。
Data Output Streamのコンストラクトには、File Output Streamのインスタンスが必要です。
なので2段階のコンストラクト作業になります。



 import java.io.*;
 
 public class DoutTest {
 	public static void main (String[] args) {
 		try {
 			FileOutputStream fout = new FileOutputStream("dout.dat");
 			DataOutputStream dout = new DataOutputStream(fout);
 			dout.writeInt(100);
 			dout.close();
 			
 		}catch (Exception e) {
 			System.out.println(e);
 		}
	}
 }

このままだと、ウィンドウを閉じてもプログラムは終了しません。
ウィンドウを閉じた時に、プログラムを終了するかしないかは、アプリの設計でどちらでも可能です。がシンプルなプログラムでは、ウィンドウを閉じた時に終了する方式が多いようです。
ウィンドウを閉じるとプログラムが終了するようにしてみましょう。以下のように1行追加します。
これでdout.datという名前のファイルができあがるはずです。 作ったファイルを

 import javax.swing.JFrame;
 public class SimpleWindow {
 hexdump dout.dat

してみてください

 e100:java siio$ hexdump dout.dat 
 0000000 00 00 00 64                                    
 0000004

int型は4バイトなので4バイトのファイルが出来上がっています。100は0x000064なので、その内容のファイルです。


***整数を入出力する例 [#j899e2e7]

File/Data Output Streamにはそれぞれ対応したFile/Data Input Streamがあります。
こちらで機能を確認しましょう。

https://docs.oracle.com/javase/jp/8/docs/api/index.html

Javaのint型のデータで100をファイルに書いて、これを読み込む例です。

 import java.io.*;
 
        public static void main(String argv[]) {
                JFrame f = new JFrame("私が作った最初の窓");
                f.setSize(200,100); 
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
        }
 public class DoutTest {
 	public static void main (String[] args) {
 		try {
 			FileOutputStream fout = new FileOutputStream("dout.dat");
 			DataOutputStream dout = new DataOutputStream(fout);
 			dout.writeInt(100);
 			dout.close();
 			
 			FileInputStream finput = new FileInputStream("dout.dat");
 			DataInputStream dinput = new DataInputStream(finput);
 			System.out.println(dinput.readInt());
 			dinput.close();
 			
 		}catch (Exception e) {
 			System.out.println(e);
 		}
 	}
 }


***演習 [#iffeaa5d]

1から100までのint型の数値をwirteIntメソッドでファイルに書き出すプログラムを書いてください。また、そのファイルをreadIntメソッドで読み込み、表示してください。

作ったファイルを
 hexdump dout.dat
してみてください

解答例


 import java.io.*;
 
 public class DoutTest {
 	public static void main (String[] args) {
 		int i;
 		try {
 			FileOutputStream fout = new FileOutputStream ("dout.dat");
 			DataOutputStream dout = new DataOutputStream(fout);
 			for(i=1;i<101;i++) dout.writeInt(i);
 			dout.close();
 			
 			FileInputStream fin = new FileInputStream ("dout.dat");
 			DataInputStream din = new DataInputStream(fin);
 			
 			for(i=1;i<101;i++) System.out.println(din.readInt());
 			din.close();
 			
 		} catch (FileNotFoundException e) {
 			System.out.println(e);
 		} catch (IOException e) {
 			System.out.println(e);
 		}
 	}
 }

このプログラムをよくみていきましょう。
mainの最初の行で、JFrameのコンストラクタを呼び出して、インスタンスを作っています。
引数付きのコンストラクタを使っています。Stringの引数を使うと、その内容がウィンドウのタイトル名になります。
作ったインスタンスはJFrameを参照する変数 f に代入されています。

mainの2行目では、JFrameのインスタンスメソッドであるsetSize()を呼んでいます。文字通り、ウィンドウのサイズを設定するメソッドです。
**文字ストリーム [#x25291f2]

mainの最後の行では、setVisible()メソッドを呼んでいます。これは、ウィンドウを目に見えるように表示する機能です。作っただけでは表示されないです。
文字を読み書きするのが文字ストリームです。文字に適した処理が用意されています。
ReaderとWriterというクラスのグループがあります。

***文字列の書き出し [#a85525d6]

File Writerを使うと文字列を書き出すことができます。
close, flush, writeなどのメソッドがあります。
こちらで機能を確認しましょう。

*** JFrameを継承するプログラミング [#j767173a]
https://docs.oracle.com/javase/jp/8/docs/api/index.html

アプリケーションで使うウィンドウを作る時の流儀の一つに、素のウィンドウクラスを継承して、使いたいウィンドウをサブクラスで作る方法があります。Javaではそのような方法が、一般的です。ということで、JFrameを継承して、ウィンドウを作ってみます。上のプログラムと同じことを行いますが、やり方が違っています。以下です。
File Writerにはwrite()メソッドで、文字や、文字配列や、Stringを書き出すことができます。
以下ではStringを書き出しています。


 import javax.swing.JFrame;
 public class SimpleWindow extends JFrame {
 import java.io.*;
 
 	public void initialize () {
 		this.setTitle("私が作った最初の窓");
 		this.setSize(200,100);
 		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 		this.setVisible(true);
 public class PrintWriterTest{
 	public static void main(String[] args) {
 		try {
 		//writer.txtというファイルを作って文字を書き込む
 			FileWriter fwriter = new FileWriter("writer.txt");
 			fwriter.write("Multimedia Programming 実習");
 			fwriter.close();	
 		}
 		catch (IOException e) {
 			System.out.println(e);
 		}
 	}
 }


また、Print Writerというクラスでは、System Out Printlnのようにprintlnに相当する機能が使えます。
Javaのいろいろなデータを書き出すのに便利です。


***printlnで書き出すプログラム [#efb2dbc9]

writer.txtというファイルに、

 int x = 2020;
 String s = "Multimedia Programming 実習";

というJavaの変数を、printlnで書き出すプログラムを作ってください。

//Print Writerをコンストラクトするためには、File Writerのインスタンスが必要です。なので、これも2段階のコンストラクションを行います。

 import java.io.*;
 
 	public static void main (String argv[]) {
 		SimpleWindow sw = new SimpleWindow();
 		sw.initialize();
 public class PrintWriterTest{
 	public static void main(String[] args) {
 		try {
 		//writer.txtというファイルを作って文字を書き込む
 			PrintWriter pwriter = new PrintWriter("writer.txt");
 			pwriter.println(2020);
 			pwriter.println("Multimedia Programming 実習");
 			pwriter.close();	
 		}
 		catch (IOException e) {
 			System.out.println(e);
 		}
 	}
 }

このプログラムでは、JFrameを継承して、サブクラスとしてSimpleWindowを定義しています。
なので、SimpleWindowのインスタンスは、JFrameの機能を全て使えます。
別のプログラムからSimpleWindowのインスタンスを作って表示しても良いのですが、面倒なので、自信を動かすプログラムをmainで書きました。今まで、クラスを作ってそれを動かすプログラムをmainに書いていたのと同じです。

mainでは、自分自身のインスタンスを作って、それへの参照をswという変数に代入しています。
そしてinitialize()というインスタンスメソッドを呼んでいます。
作ったファイルを hexdump してみてください

initialize()は今の所SimpleWindowで新たに定義した唯一のメンバーです。
その名の通り、自分自身の初期化を行うつもりで命名しました。
コンストラクタとして実装しても良いのですが、結構複雑な仕事をするので、
別のメソッドにしました。ちなみに、他のオブジェクト指向言語では、
newした後に、init()とかinitialize()とかのメソッドを呼ぶ方式も多いです。(例えばSmallTalk言語)。
ここではそれを真似しました。
 $ hexdump writer.txt 
 0000000 32 30 32 30 0a 4d 75 6c 74 69 6d 65 64 69 61 20
 0000010 50 72 6f 67 72 61 6d 6d 69 6e 67 20 e5 ae 9f e7
 0000020 bf 92 0a                                       
 0000023

initialize()の中で、ウィンドウのタイトルを決めて、サイズを決めて、終了オプションを指定して、setVisibleしています。
hexdump -cでキャラクタ表示にもなります。

***ラベルを表示するウィンドウ [#dc55da2c]
 $ hexdump -c writer.txt 
 0000000   2   0   2   0  \n   M   u   l   t   i   m   e   d   i   a    
 0000010   P   r   o   g   r   a   m   m   i   n   g       ?   ? 237   ?
 0000020   ? 222  \n                                                    
 0000023

このままではウィンドウが空っぽなので、文字を表示してみましょう。
文字を表示するクラスにJLabelがあります。その名の通りラベルです。
2020という数値は、int型なのですが、ASCII文字列に変換されて文字として書き出されていることがわかります。
「Multimedia Programming 実習」は、もともとが文字列なので、そのまま文字列として書き出されています。0x0Aは改行コードです。
int型などのデータを文字に自動変換してくれるところが、Print Writerの特徴です。
Stringだけでしたら、File Writerの機能を使っても同様に書き出すことが可能です。

以下のリンクからJLabelクラスを選択して、何ができるかざっと見ておきましょう。


***read Lineで改行コードまでを読み込む [#y3262833]

File ReaderはFile Writerと同様に文字列を読み込みます。
読み込む文字数を指定して読み込むことも可能です。
さらに便利なクラスがBuffered Readerで、こちらは改行文字までを読み込んでくれます。
こちらで機能を確認しましょう。

https://docs.oracle.com/javase/jp/8/docs/api/index.html

基本的な使い方は以下です。まずは、インスタンスを作ります。コンストラクタの引数で、表示させる文字を指定することもできます。
Buffered ReaderもFile Readerのインスタンスから作りますので、2段階のコンストラクションになります。

 Label label = new Label("Hello!");
writer.txtというテキストファイルがあるとして、これから1行ずつ読み込んで画面表示するプログラムは以下のようになります。

ところで、JFrameで作ったインスタンスは、Containerというクラスのインスタンスを持っています。その名前の通り、「何かを格納するもの」です。つまりウィンドウに情報を格納する機能を持ったインスタンスです。JFrameのインスタンスに、getContentPane()というメソッドを送ると、ウィンドウに表示したい情報を格納するインスタンスを返してくれます。
 public class BufferedReaderTest{
 	public static void main(String[] args) {
 		try {
 			FileReader freader = new FileReader("writer.txt");
 			BufferedReader breader = new BufferedReader(freader);
 			String tmp;
 			while( (tmp=breader.readLine() ) != null) {
 				System.out.println(tmp);
 			}
 			breader.close();
 		}
 		catch (IOException e) {
 			System.out.println(e);
 		}
 	}
 }

 Container content = this.getContentPane();
このプログラムを参考にして、
先のPrint Writer Testに書き足して、
書き込んだデータを読み出して画面に表示するプログラムを作ってください。

で、自分自身のコンテントペーンを返してくれます。
これに対して、上記で作ったラベルインスタンスをaddすることができます。
ヒント:

 content.add(label);
 import java.io.*;
 
 public class PrintWriterTest{
 	public static void main(String[] args) {
 		try {
 		//writer.txtというファイルを作って文字を書き込む
 			PrintWriter pwriter = new PrintWriter("writer.txt");
 			pwriter.println(2020);
 			pwriter.println("Multimedia Programming 実習");
 			pwriter.close();	
			 
			 
			 ここに書き足す
			 
			 
 		}
 		catch (IOException e) {
 			System.out.println(e);
 		}
 	}
 }


上記の、継承を使ったプログラムによるウィンドウの中に、
Hello!という文字を出してみよう。
上で紹介した3行を、initialize()メソッドに加えれば文字を出せます。

解答例:

 import javax.swing.*;
 import java.awt.*;

 import java.io.*;
 
 public class SimpleWindow extends JFrame {
 
 	public void initialize () {
 		this.setTitle("私が作った最初の窓");
 		
 		JLabel label = new JLabel("Hello!");
 		Container content = this.getContentPane();
 		content.add(label);
 		
 		this.setSize(200,100);
 		this.setVisible(true);
 		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 public class PrintWriterTest{
 	public static void main(String[] args) {
 		try {
 		//writer.txtというファイルを作って文字を書き込む
 			PrintWriter pwriter = new PrintWriter("writer.txt");
 			pwriter.println(2020);
 			pwriter.println("Multimedia Programming 実習");
 			pwriter.close();			
 		//writer.txtのファイルの中身をSystem.out.printlnで表示する
 			FileReader freader = new FileReader("writer.txt");
 			BufferedReader breader = new BufferedReader(freader);
 			String tmp;
 			while( (tmp=breader.readLine() ) != null) {
 				System.out.println(tmp);
 			}
 			breader.close();
 		}
 		catch (IOException e) {
 			System.out.println(e);
 		}
 	}
 }


**標準入出力 [#u09d26a5]

標準入出力には、

- キーボードからプログラムへの標準入力
- プログラムからディスプレイへの標準出力
- エラー出力

の3種類があります。これらはJavaのクラス変数として定義されています。

- System.in キーボードからプログラムへの標準入力
- System.out プログラムからディスプレイへの標準出力
- System.err エラー出力

それぞれの型は、

- System.in は Input Stream型
- System.out は Print Stream型
- System.err は Print Stream型

です。使えるメソッドはこちらで確認できます。

https://docs.oracle.com/javase/jp/8/docs/api/index.html

***標準入力から読み込んだ文字列をそのままディスプレイに表示するプログラム [#mcb98bfc]

 import java.io.*;
 
 	public static void main(String argv[]) {
 		SimpleWindow sw = new SimpleWindow();
 		sw.initialize();
 public class StandardIOTest {
 	public static void main(String[] args) {
 	
 		try {
 			//System.inからInputStreamReaderを作り、それからBufferedReaderを作る
 			InputStreamReader ireader = new InputStreamReader (System.in);
 			BufferedReader breaderK = new BufferedReader(ireader);
 			
 			System.out.println("文字列を入力してリターンを押してください");
 			String line = breaderK.readLine();
 			System.out.println("あなたが入力した文字列" + line);

 			}
		catch(IOException e) {
 				System.out.println(e);
 			}
 	}
 
 }

***演習 [#m02d0351]

コンテンツの大きさに合わせてウィンドウサイズを変更する機能があります。
上記のプログラムではsetSize()で変更していますが、これの代わりに、
キーボードから1行入力された文字列から writer.txtという名前のテキストファイルを作るプログラムを作ってください。

 this.pack();
//http://gyazo.com/f9aee7f492d574f870e85e2022df374c.png

というメソッドを呼び出してみましょう。以下のようになるはずです。
 e100:java siio$ java KeyToFile 
 Hello, これはテストです。
 Hello, これはテストです。
 e100:java siio$ cat writer.txt 
 Hello, これはテストです。

http://gyazo.com/c6efe47de19436f7564660377fe8b98c.png
ヒント

  import java.io.*;
  
  public class KeyToFile {
  	public static void main(String[] args) {
  	
  		try {
 
 
 ここにプログラムを書く
  		
  			}
 		catch(IOException e) {
  				System.out.println(e);
   			}
     }
  }

解答例:

 import javax.swing.*;
 import java.awt.*;

解答例

 import java.io.*;
 
 public class SimpleWindow extends JFrame {
 
 	public void initialize () {
 		this.setTitle("私が作った最初の窓");
 public class KeyToFile {
 	public static void main(String[] args) {
 	
 		try {
 			InputStreamReader ireader = new InputStreamReader (System.in);
 			BufferedReader breaderK = new BufferedReader(ireader);
 			String line = breaderK.readLine();
 			
 			PrintWriter pwriter = new PrintWriter("writer.txt");
 			pwriter.println(line);
 			pwriter.close();
 			
 			FileReader freader = new FileReader("writer.txt");
 			BufferedReader breaderF = new BufferedReader(freader);
 			
 			String tmp=null;		
 			while(  (tmp=breaderF.readLine())  != null)
 				System.out.println(tmp);
 			
 			breaderF.close();
 		
 		JLabel label = new JLabel("Hello!");
 		Container content = this.getContentPane();
 		content.add(label);
 		this.pack();
 		
 		this.setVisible(true);
 		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 			}
			catch(IOException e) {
 				System.out.println(e);
 			}
 	}
 }


***http://www.ocha.ac.jp/の内容を表示するプログラムを書いてみよう [#kf0c5bf6]

http://gyazo.com/13044fdd9d372118a1f6fe93896eadb3.png

ヒント1

以下のリンクからURLクラスを選択して、調べましょう。

https://docs.oracle.com/javase/jp/8/docs/api/index.html


ヒント2

 import java.net.*;

が必要です。

 URL targetURL = new URL("http://www.ocha.ac.jp/");

でURLクラスのインスタンスが得られる。

 InputStream istream = targetURL.openStream();

でこれからInputStreamのインスタンスが得られる。

 InputStreamReader isreader = new InputStreamReader(istream);

でこれからInputStreamReaderのインスタンスが得られる。

 BufferedReader breader = new BufferedReader(  isreader );

でこれからBufferedReader のインスタンスが得られる。

ヒント3


 import java.io.*;
 import java.net.*;
 
 	public static void main(String argv[]) {
 		SimpleWindow sw = new SimpleWindow();
 		sw.initialize();
 public class URLTest {
 	public static void main (String argv[]) {
 		try {
 			
			 
			 ここにプログラムを書く
			 
			 
 		} catch (IOException e) {
 			System.out.println("error...");
 		}
 	}
 
 }

***ボタンを1個表示するウィンドウ [#ied43afe]

今度はウィンドウにボタンを表示してみましょう。
ボタンなので、多分JButtonというクラスがありそうです。
以下から探して、何ができるかざっと見ておきましょう。
ヒント4:

https://docs.oracle.com/javase/jp/8/docs/api/index.html
 import java.io.*;
 import java.net.*;
 
 public class URLTest {
 	public static void main (String argv[]) {
 		try {
 			URL targetURL = new URL("http://www.ocha.ac.jp/");
 			InputStream istream = targetURL.openStream();
 			InputStreamReader isreader = new InputStreamReader(istream);
 			BufferedReader breader = new BufferedReader(  isreader );
 		
 ここで一行ずつ読み込む
 
 		} catch (IOException e) {
 			System.out.println("error...");
 		}
 	}
 }


上記のプログラムのJLabelのところをJButtonにすればだいたい良いようです。試してみましょう。

解答例:

 import javax.swing.*;
 import java.awt.*;
 import java.io.*;
 import java.net.*;
 
 public class SimpleWindow extends JFrame {
 
 	public void initialize () {
 		this.setTitle("私が作った最初の窓");
 public class URLTest {
 	public static void main (String argv[]) {
 		try {
 			URL targetURL = new URL("http://www.ocha.ac.jp/");
 			InputStream istream = targetURL.openStream();
 			InputStreamReader isreader = new InputStreamReader(istream);
 			BufferedReader breader = new BufferedReader(  isreader );
 		
 		JButton button = new JButton("Hello!");
 		Container content = this.getContentPane();
 		content.add(button);
 		this.pack();
 			String line;
 			while((line=breader.readLine()) != null) System.out.println(line);
 		
 		this.setVisible(true);
 		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 		} catch (IOException e) {
 			System.out.println("error...");
 		}
 	}
 
 	public static void main(String argv[]) {
 		SimpleWindow sw = new SimpleWindow();
 		sw.initialize();
 	}
 
 }

http://www.siio.jp/index.php?plugin=attach&pcmd=open&file=button.png&refer=How2JavaProgramming

***写真ファイルのダウンロード [#edb3e256]

//ここまで
 http://siio.jp/cat.jpg 

***ボタンを2個表示するウィンドウ [#cb6cf696]
をダウンロードして、cat.jpgというファイルを作るプログラムを作ってください。
データはテキストじゃなくて、バイナリーです。

プログラム12.2をみてください。
getContentPane()で得られたContainerに直接ボタンを貼付けることもできますが、
貼付けられるのは一つのボタンだけのようです。
そこで、JPanel (パネル) に2個のボタンを貼付け、それをContainerに貼付けることで複数のボタンを表示しています。
ヒント1:

InputStreamのインスタンスに対してread()メソッドを使うと1バイトのデータが得られます。読み終わると-1になります。
1バイトのデータを書き出すなら、FileOutputStreamだけで可能です。

http://gyazo.com/03c28df2419065241b8736b7b69d7fd3.png
ヒント2:

プログラム12.2を参考にして、継承を使ったプログラムによるウィンドウの中に、
2個のボタンを出してみよう。
 import java.io.*;
 import java.net.*;
 
 public class URLJpeg {
 	public static void main (String argv[]) {
 		try {
 			URL targetURL = new URL("http://siio.jp/cat.jpg");
 			InputStream istream = targetURL.openStream();
 			
 			FileOutputStream fout = new FileOutputStream("cat.jpg");


http://gyazo.com/4c3086ae9b6b5434d2ea741369f731c5.png
というインスタンスを作って、

解答例:
 istream.read()

 import javax.swing.*;
 import java.awt.*;
で読んで、

 fout.write(1バイト)

で書き出します。

解答例

 import java.io.*;
 import java.net.*;
 
 public class SimpleButton extends JFrame {
 //http://siio.jp/cat.jpg
 //をダウンロードして、cat.jpgというファイルを作るプログラム
 
 	public void initialize () {
 		this.setTitle("私が作った最初の窓");
 		
 		JPanel panel = new JPanel();
 		JButton button1 = new JButton("button1");
 		JButton button2 = new JButton("button2");
 		panel.add(button1);
 		panel.add(button2);
 		Container container = this.getContentPane();
 		container.add(panel);	
 	
 		this.pack();		
 		this.setVisible(true);
 		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 public class URLJpeg {
 	public static void main (String argv[]) {
 		try {
 			URL targetURL = new URL("http://siio.jp/cat.jpg");
 			InputStream istream = targetURL.openStream();
 			
 			FileOutputStream fout = new FileOutputStream("cat.jpg");
 			
 			int aData;
 			while((aData  = istream.read()) != -1) fout.write(aData);
 			
 			istream.close();
 			fout.close();
 			
 			
 		} catch (IOException e) {
 			System.out.println("error...");
 		}
 	}
 
 	public static void main(String argv[]) {
 		SimpleButton sw = new SimpleButton();
 		sw.initialize();
 	}
 
 }


このプログラムでは,ボタンを押しても何もおこりません.

ボタンが押されたイベントを受け取るためには,
+ActionListenerをimplementしたクラスを作る
+そのインスタンスを作る
+これをボタンにaddActionListener()で登録する
必要があります.
***本日のレポート [#o4524903]

プログラム12.3を参考に,ボタンを押したらprintlnで次のようなメッセージを表示するプログラムを作ってみましょう.
上記のプログラム(URLJpeg.java, URLJpeg.class) を、出席番号+名前のフォルダにいれて、ZIP圧縮して提出してください。`

http://gyazo.com/67d27d0588f4dd5d11410e1107165994.png

***写真読み込みの高速化 [#ia7ce1f8]

ヒント(最初の6行です)
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
上記の例では写真データを1バイトずつ読み書きしていました。
InputStreamのメソッドを調べると、複数バイト単位で読み込むメソッドがあります。
たとえば、1024バイトずつ読み書きすることで、処理速度が向上すると期待できます。
そこで、複数バイト読み書きするよう、上記のプログラムを変更して、
実際にどの程度(実行速度にして何倍くらい)性能向上するか確認してみましょう。


 read
 
 public class SimpleButton extends JFrame implements ActionListener {
 public int read(byte[] b)
          throws IOException
 入力ストリームから配列長さだけのバイト数を読み込もうとし、それをバッファ配列 b に格納します。
 実際に読み込まれたバイト数は整数として返されます。
 戻り値は、バッファに読み込まれたバイトの合計数。ストリームの終わりに達してデータがない場合は -1

を使って読みこみ、

 write
 
 JButton button1, button2;
 
 	public void initialize () {
 public void write(byte[] b,
                   int off,
                   int len)
            throws IOException
 指定された byte 配列の、オフセット位置 off から始まる len バイトを出力ストリームに書き込みます。

解答例
を使ってください。

 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
-ヒント


 byte[] data = new byte[1024];

という配列を用意して、

 	int datalength;
 	while(( datalength=istream.read(data)) != -1) fout.write(data, 0, datalength);

とします。

-解答例

 import java.io.*;
 import java.net.*;
 
 public class SimpleButton extends JFrame implements ActionListener {
 //http://siio.jp/cat.jpg
 //をダウンロードして、cat.jpgというファイルを作るプログラムを作ってください。
 //データはテキストじゃなくて、バイナリーです。
 
 JButton button1, button2;
 
 	public void initialize () {
 		this.setTitle("私が作った最初の窓");
 	
 		JPanel panel = new JPanel();
 		button1 = new JButton("button1");
 		button2 = new JButton("button2");
 		button1.addActionListener(this);
 		button2.addActionListener(this);
 
 		panel.add(button1);
 		panel.add(button2);
 		Container container = this.getContentPane();
 		container.add(panel);
 	
 		this.pack();		
 		this.setVisible(true);
 		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 public class URLJpeg2 {
 	public static void main (String argv[]) {
 		byte[] data = new byte[1024];
 		try {
 			URL targetURL = new URL("http://siio.jp/cat.jpg");
 			InputStream istream = targetURL.openStream();
 			
 			FileOutputStream fout = new FileOutputStream("cat.jpg");
 			
 			int datalength;
 			while(( datalength=istream.read(data)) != -1) fout.write(data, 0, datalength);
 			
 			istream.close();
 			fout.close();
 			
 			
 		} catch (IOException e) {
 			System.out.println("error...");
 		}
 	}
 	
 	public void actionPerformed (ActionEvent e) {
 		if(e.getSource()==button1) 
 			System.out.println("Hello");
 		else
 			System.out.println("Goodbye");
 	}
 
 	public static void main(String argv[]) {
 		SimpleButton sw = new SimpleButton();
 		sw.initialize();
 	}
 
 }

ここではボタンを区別するために、インスタンス(への参照)を比較した。それ以外の方法もある。
一つは、ボタンのテキストを入手することである。ボタンのテキストを入手してそれを比較しても良い。
ボタンのテキストを表示するだけなら以下のようにしても良い。

         public void actionPerformed(ActionEvent e){
                 System.out.println(((JButton)e.getSource()).getText());
         }
ここでは1024バイトを読み込むことにしました。でも、InputStreamのメソッドを見ると、available()というのがあります。

もう一つは、ボタンにコマンドを書く方法である。
ボタンにsetActionCommand(String)を定義しておくと、getActionCommand()で知ることができる。
 available()
 この入力ストリームのメソッドの次の呼出しによって、ブロックせずにこの入力ストリームから読み込むことができる(またはスキップできる)推定バイト数を返します。

 button1.setActionCommand("hello");
これを使えば、適切な長さを見積もれるかもしれません。

としておけば、actionPerformedの中で
***引数のURLをファイルにするプログラムを考えてみましょう [#mc747214]

 e.getActionCommand();
curlというコマンドがあります。

で文字列を得られる。例えば、
 curl http://ocha.ac.jp/

         public void actionPerformed(ActionEvent e){
                 System.out.println(e.getActionCommand());
         }
などとすると、htmlが見られますし、

でコマンド部分を印刷できる。
 curl http://siio.jp/cat.jpg > cat.jpg

//***宿題:プログラム12.4 [#sb6fece9]
などとすると、ファイルとして保存できます。これに近いプログラムを作ってみましょう。

***プログラム12.4をやってください。 [#k14ed280]

***演習12.2(改) [#q3f681b0]

上で作った二つのボタンのプログラムに対して、レイアウトマネージャのFlowLayoutを使って、左寄せ、センタリング、右寄せを試してください。
***宿題 [#wb66142e]

演習のヒント
上記の引数のURLをファイルにするプログラムを作ってください。
また、cat.jpgのファイル取得でまとめて読むことでどれくらい速度が改善したかを、
レポートにしてください。レポートの書式は任意です。(テキストファイルでかまいません)

 		bt1 = new JButton("button1");
 		bt2 = new JButton("button2");
 		panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
 		bt1.setActionCommand("this is b1");
 		bt2.setActionCommand("this is b2");
これらのjava, class, レポートのファイルをまとめて、出席番号+名前のフォルダに入れて、圧縮して、12月10日の授業の開始時間に提出してください。

FlowLayoutにはCENTER, LEFT, RIGHTなどの揃え方の指定がありますが、これをコンストラクタの引数で指定できるようです。addのところではレイアウト指定しないようです。


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS