このページは、学部2年生向け授業である、「マルチメディアプログラミング実習」 のために用意しました。
(Wikiの仕様で大文字小文字が混在した英単語に疑問符?が追加されるところがありますが、無視してください。)
Javaの入出力は、ファイル、ネットワーク、キーボード、ディスプレイを対象としています。C言語に比べて、高機能な上に、ネットワークへの入出力も標準装備されているところが便利です。
(ファイル、ネットワーク、キーボード) | | 入力ストリーム | V (Javaプログラム) | | 出力ストリーム | V (ファイル、ネットワーク、ディスプレイ)
データを入出力するのがバイトストリームです。 ここでは、
を使ってみます。
こちらで機能を確認しましょう。
https://docs.oracle.com/javase/jp/8/docs/api/index.html
基本的なインスタンスメソッドは、writeとcloseです。writeには1バイトの書き込み、バイト配列の書き込みがあります。IOExceptionを投げるので、キャッチします。
write(int b)
は、int型の引数の下位1バイトを書き出します。以下のプログラムでファイルに1バイト書き出すことができます。
import java.io.*; 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バイトが書き込まれました。
こちらで機能を確認しましょう。
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); } } }
これでdout.datという名前のファイルができあがるはずです。 作ったファイルを
hexdump dout.dat
してみてください
e100:java siio$ hexdump dout.dat 0000000 00 00 00 64 0000004
int型は4バイトなので4バイトのファイルが出来上がっています。100は0x000064なので、その内容のファイルです。
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 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); } } }
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); } } }
文字を読み書きするのが文字ストリームです。文字に適した処理が用意されています。 ReaderとWriterというクラスのグループがあります。
File Writerを使うと文字列を書き出すことができます。 close, flush, writeなどのメソッドがあります。 こちらで機能を確認しましょう。
https://docs.oracle.com/javase/jp/8/docs/api/index.html
File Writerにはwrite()メソッドで、文字や、文字配列や、Stringを書き出すことができます。 以下ではStringを書き出しています。
import java.io.*; 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のいろいろなデータを書き出すのに便利です。
writer.txtというファイルに、
int x = 2020; String s = "Multimedia Programming 実習";
というJavaの変数を、printlnで書き出すプログラムを作ってください。
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); } } }
作ったファイルを hexdump してみてください
$ 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
hexdump -cでキャラクタ表示にもなります。
$ 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
2020という数値は、int型なのですが、ASCII文字列に変換されて文字として書き出されていることがわかります。 「Multimedia Programming 実習」は、もともとが文字列なので、そのまま文字列として書き出されています。0x0Aは改行コードです。 int型などのデータを文字に自動変換してくれるところが、Print Writerの特徴です。 Stringだけでしたら、File Writerの機能を使っても同様に書き出すことが可能です。
File ReaderはFile Writerと同様に文字列を読み込みます。 読み込む文字数を指定して読み込むことも可能です。 さらに便利なクラスがBuffered Readerで、こちらは改行文字までを読み込んでくれます。 こちらで機能を確認しましょう。
https://docs.oracle.com/javase/jp/8/docs/api/index.html
Buffered ReaderもFile Readerのインスタンスから作りますので、2段階のコンストラクションになります。
writer.txtというテキストファイルがあるとして、これから1行ずつ読み込んで画面表示するプログラムは以下のようになります。
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); } } }
このプログラムを参考にして、 先のPrint Writer Testに書き足して、 書き込んだデータを読み出して画面に表示するプログラムを作ってください。
ヒント:
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); } } }
解答例:
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(); //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); } } }
標準入出力には、
の3種類があります。これらはJavaのクラス変数として定義されています。
それぞれの型は、
です。使えるメソッドはこちらで確認できます。
https://docs.oracle.com/javase/jp/8/docs/api/index.html
import java.io.*; 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); } } }
キーボードから1行入力された文字列から writer.txtという名前のテキストファイルを作るプログラムを作ってください。
e100:java siio$ java KeyToFile Hello, これはテストです。 Hello, これはテストです。 e100:java siio$ cat writer.txt Hello, これはテストです。
ヒント
import java.io.*; public class KeyToFile { public static void main(String[] args) { try { ここにプログラムを書く } catch(IOException e) { System.out.println(e); } } }
解答例
import java.io.*; 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(); } catch(IOException e) { System.out.println(e); } } }
ヒント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 class URLTest { public static void main (String argv[]) { try { ここにプログラムを書く } catch (IOException e) { System.out.println("error..."); } } }
ヒント4:
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..."); } } }
解答例:
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 ); String line; while((line=breader.readLine()) != null) System.out.println(line); } catch (IOException e) { System.out.println("error..."); } } }
http://is.ocha.ac.jp/~gradthesis/cat.jpg
をダウンロードして、cat.jpgというファイルを作るプログラムを作ってください。 データはテキストじゃなくて、バイナリーです。
ヒント1:
InputStreamのインスタンスに対してread()メソッドを使うと1バイトのデータが得られます。読み終わると-1になります。 1バイトのデータを書き出すなら、FileOutputStreamだけで可能です。
ヒント2:
import java.io.*; import java.net.*; public class URLJpeg { public static void main (String argv[]) { try { URL targetURL = new URL("http://is.ocha.ac.jp/~gradthesis/cat.jpg"); InputStream istream = targetURL.openStream(); FileOutputStream fout = new FileOutputStream("cat.jpg");
というインスタンスを作って、
istream.read()
で読んで、
fout.write(1バイト)
で書き出します。
解答例
import java.io.*; import java.net.*; //http://is.ocha.ac.jp/~gradthesis/cat.jpg //をダウンロードして、cat.jpgというファイルを作るプログラム public class URLJpeg { public static void main (String argv[]) { try { URL targetURL = new URL("http://is.ocha.ac.jp/~gradthesis/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..."); } } }
上記のプログラム(URLJpeg.java, URLJpeg.class) を、出席番号+名前のフォルダにいれて、ZIP圧縮して提出してください。`
上記の例では写真データを1バイトずつ読み書きしていました。 InputStreamのメソッドを調べると、複数バイト単位で読み込むメソッドがあります。 たとえば、1024バイトずつ読み書きすることで、処理速度が向上すると期待できます。 そこで、複数バイト読み書きするよう、上記のプログラムを変更して、 実際にどの程度(実行速度にして何倍くらい)性能向上するか確認してみましょう。
read public int read(byte[] b) throws IOException 入力ストリームから配列長さだけのバイト数を読み込もうとし、それをバッファ配列 b に格納します。 実際に読み込まれたバイト数は整数として返されます。 戻り値は、バッファに読み込まれたバイトの合計数。ストリームの終わりに達してデータがない場合は -1
を使って読みこみ、
write public void write(byte[] b, int off, int len) throws IOException 指定された byte 配列の、オフセット位置 off から始まる len バイトを出力ストリームに書き込みます。
を使ってください。
byte[] data = new byte[1024];
という配列を用意して、
int datalength; while(( datalength=istream.read(data)) != -1) fout.write(data, 0, datalength);
とします。
import java.io.*; import java.net.*; //http://is.ocha.ac.jp/~gradthesis/cat.jpg //をダウンロードして、cat.jpgというファイルを作るプログラムを作ってください。 //データはテキストじゃなくて、バイナリーです。 public class URLJpeg2 { public static void main (String argv[]) { byte[] data = new byte[1024]; try { URL targetURL = new URL("http://is.ocha.ac.jp/~gradthesis/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..."); } } }
ここでは1024バイトを読み込むことにしました。でも、InputStreamのメソッドを見ると、available()というのがあります。
available() この入力ストリームのメソッドの次の呼出しによって、ブロックせずにこの入力ストリームから読み込むことができる(またはスキップできる)推定バイト数を返します。
これを使えば、適切な長さを見積もれるかもしれません。
curlというコマンドがあります。
curl http://ocha.ac.jp/
などとすると、htmlが見られますし、
curl http://is.ocha.ac.jp/~gradthesis/cat.jpg > cat.jpg
などとすると、ファイルとして保存できます。これに近いプログラムを作ってみましょう。
上記の引数のURLをファイルにするプログラムを作ってください。 また、cat.jpgのファイル取得でまとめて読むことでどれくらい速度が改善したかを、 レポートにしてください。レポートの書式は任意です。(テキストファイルでかまいません)
これらのjava, class, レポートのファイルをまとめて、出席番号+名前のフォルダに入れて、圧縮して、12月10日の授業の開始時間に提出してください。