• 検索結果がありません。

ファイル入出力Ⅱ

N/A
N/A
Protected

Academic year: 2021

シェア "ファイル入出力Ⅱ"

Copied!
10
0
0

読み込み中.... (全文を見る)

全文

(1)

ファイル入出力Ⅱ

JV⑩ □ ストリーム(概要、概説) □ ストリーム(ファイルストリーム) □ ストリーム(文字ストリーム) □ ストリーム(バイナリストリーム) □ ストリーム(パイプストリーム) 今回の課題項目 □ ストリームの基本(概要、概説、使用クラス) □ ストリームの実践(ファイルストリーム、文字ストリーム、バイナリストリーム) □ ストリームの実践(パイプストリーム) 今回の重点項目

(2)

プログラムでは一般に、多くの種類のデータを、多くの種類の入力先から取得して、多くの種類の出力先へ書 き込む必要が考えられる。Java では、此等のデータの入出力(I/O)は一般にストリームとして解釈する事に 成る。入力元へのストリームを開いて情報を読み込み、出力先へのストリームを開いて情報を書き込み、必要 が無く成れば其等のストリームを閉じる。 此等のストリームを扱う為の標準クラスライブラリは、java.io パッケージから提供される。此等のクラスは一 般に、取り扱うデータの種類に応じて文字ストリームとバイトストリームの二つに分けられる。然して、此等 のストリームはオブジェクトとして扱われる ■ ストリーム概要 ■ ストリームとはデータの直線的な流れと謂う概念で有り、現代的なプログラミング言語では、入出力を ストリームとして扱う。例えば、ディスク上のファイルに向かうストリームが有る時、其処に書き込ん だデータはファイルに出力される。ネットワークから流れ込むストリームからはネットワーク越しのデ ータを受け取る事が出来る。プログラマはストリームに対する入出力を考える丈で、其の流れ行く果て の、実デバイスに対しては考えなくて良く成る。

Java ではデータ I/O にストリームと謂う概念を使用する。java.io パッケージ内のストリームクラスは、 大きく分けると、バイトストリーム、文字ストリーム、オブジェクトストリームの3種に成る。Java のI/O は、総てストリームのオブジェクトとして実装する。

java.io パッケージ内のクラスは、デバイス I/O、ネットワーク I/O 等が統一的な枠組みで設計されて居 る。総てのストリームは、バイトストリーム、文字ストリーム、オブジェクトストリームに分けられ、 次の6種の抽象クラス/インタフェースに基づく。 OutputStream 抽象クラス 総てのバイト出力ストリームのスーパークラス。 write()でデータを書き込む。 InputStream 抽象クラス 総てのバイト入力ストリームのスーパークラス。 read()でデータを読み込む。 Writer 抽象クラス 総ての文字出力ストリームのスーパークラス。 write()で文字配列を書き込む。 Reader 抽象クラス 総ての文字入力ストリームのスーパークラス。 read()で文字配列を読み込む。 ObjectOutputStream クラス Serializable インタフェースを実装するクラス型のオブジェクトを連 続するバイト列に変換(シリアライズ、直列化)した物とプリミティ ブ型データをOutputStream に書き出す。 ObjectInputStream クラス ObjectOutputStream で書き出したオブジェクトを読み込んで復元 する。 Java では、文字は 2 バイトの UNICODE で表現される。此の点で、文字列処理に於いては、バイトの 連続(シーケンス)で有るバイトストリームは効率が悪く、文字ストリームが要求される。亦、オブジ ェクトをファイルやDB に格納したり、ネットワーク越しに遣り取りしたりする為に、オブジェクトス トリームが必要と成る。

(3)

■ ストリーム概説 ■

java.io のストリームクラスは要件に応じて多岐に渡る。バイトストリームは InputStream と OutputStream、文字ストリームは Reader と Writer を継承して居る。詳細は API 仕様書に譲るとして、 此処では其の全体を概観して見る。 バイトストリームと文字ストリームには、御互いにカウンターパート(Counter part:相対物)と成る クラスが存在する物が有る。次に、代表的なストリームに関する夫々れの対応を示す。 基本的なストリーム バイト・ストリーム 文字ストリーム 説明 入力 出力 BufferedInputStream BufferedOutputStream BufferedReader CharArrayReader 入出力にバッファを使って効率を上げる 入力 出力 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter StringWriter バイト配列や文字配列、String 型オブジェ クトに対するストリームを作成する 入力 出力 FileInputStream FileOutputStream FileReader FileWriter ファイルに対するストリームを作成する 入力 出力 FilterInputStream FilterOutputStream FilterReader FilterWriter 此等を継承してカスタムストリームを作成 する為の抽象クラス 入力 出力 PipeInputStream PipeOutputStream PipeReader PipeWriter 複数の異なるストリーム間を繋げるパイプ を作成する ■ ファイルストリーム ■ ファイルに対するストリームは、次のクラスのオブジェクトとして作る。 テキストファイル FileReader FileWriter バイナリファイル FileInputStream FileOutputStream 此等のクラスでは、JavaVM が動作して居るネイティブなファイルシステム上に有るファイルに対する ストリームを作る。此のファイルは、File クラスや FileDescriptor クラスのオブジェクトとして参照す る。

(4)

■ 文字ストリーム ■ 継承関係: java.io.FileReader java.io.FileWriter java.lang.Object | +--java.io.Reader | +--java.io.InputStreamReader | +--java.io.FileReader java.lang.Object | +--java.io.Writer | +--java.io.OutputStreamWriter | +--java.io.FileWriter コンストラクタ: FileReader(File file) FileReader(FileDescriptor fd) FileReader(String fileName) FileWriter(File file) FileWriter(FileDescriptor fd) FileWriter(String fileName)

FileWriter(String fileName, boolean append)

FileWriter の場合は、書き込み時にファイルに追加するのか(append に true を指定)、新規に書き込 むのか(append に false を指定)を第二引数で指定出来る。引数が一つの場合はファイルの先頭から新 規書き込みと成り(append に false を指定した場合に同じ)、既存のデータは失われる(詳細に付いて はAPI 仕様書を参照)。 ■ バイトストリーム ■ 継承関係: java.io.FileInputStream java.io.FileOutputStream java.lang.Object | +--java.io.InputStream | +--java.io.FileInputStream java.lang.Object | +--java.io.OutputStream | +--java.io.FileOutputStream コンストラクタ: FileInputStream(File file) FileInputStream(FileDescriptor fdObj) FileInputStream(String name) FileOutputStream(File file) FileOutputStream(FileDescriptor fdObj) FileOutputStream(String name)

FileOutputStream(String name, boolean append)

FileOutputStream の場合は、書き込み時にファイルに追加するのか(append に true を指定)、新規に 書き込むのか(append に false を指定)を第二引数で指定出来る。引数が一つの場合はファイルの先頭 から新規書き込みと成り(append に false を指定した場合に同じ)、既存のデータは失われる。

(5)

■ パイプストリーム ■

多くの言語でパイプ(Pipe)と言う仕組みが提供されて居る。其等は、一般に、或るプロセスの出力を 別のプロセスの入力に繋げる事で有る。

例えばUNIX 系 OS では、コマンド "cat /etc/passwd | wc -l" とする事で、"cat /etc/passwd" の出力 を "wc -l" の入力に与える事が出来る。Java では、文字ストリームのパイプとバイトストリームのパイ プが用意されて居る。 文字ストリーム PipedReader PipedWriter バイトストリーム PipedInputStream PipedOutputStream 例えば、メソッドの中で、次の様に、パイプの入口と出口を作る。

PipedWriter pipeOut = new PipedWriter();

PipedReader pipeIn = new PipedReader(pipeOut);

此の例では、pipeOut から取得したストリームは、其の儘 pipeIn で取得出来る。詰まり、書き込みの 文字ストリームを読み込みの文字ストリームに繋げた事に成る。 pipeOut を此のメソッド内で処理して、戻り値に pipeIn を指定すれば、此のメソッドの処理結果を書 き込むストリームを、読み込みのストリームにパイプを通して繋げられる訳で有る。例えば、上記に続 いて下記の様に記述したとする。 // ファイルのインスタンス化

FileReader source = new FileReader("words.txt"); // 読み込みバッファでラップ

BufferedReader inp = new BufferedReader(source); // 書き込みのパイプを PrintWriter でラップ

PrintWriter out = new PrintWriter(pipeOut); // 読み込みバッファから読み込んで書き込み String line;

while ((line = inp.readLine()) != null) {

out.println(line); out.flush(); }

out.close();

此のプロセスでout に書き込まれた物はパイプストリーム PipeOut に渡され、パイプを通って pipeIn から読み込む事が出来る。従って、此のメソッドでreturn pipeIn; とすれば、次の制御へパイプが繋が る訳で有る。

此のプロセスを実行するメソッドをReader pipe(Reader source) として定義すれば、引数 source で受 け取ったストリームをpipeOut に書き込んで、其れを pipeOut に出力して返す事が可能で有る。

(6)

■ テキストファイルの書込 ■

下記のコードを、テキストエディタで入力し、FileIOtextW.java と謂うファイル名で保存した後、コン パイルして、実行する。

import java.io.*;

public class FileIOtextW {

public static void main(String args[]) {

try {

// ファイルのオープン

FileWriter f = new FileWriter("TestFile.txt"); // データの書き込み(文字列を書き込む) f.write("King of Squid¥n"); f.write("烏賊の王様¥n"); // ファイルのクローズ f.close(); } catch(Exception e) { System.err.println("例外発生:" + e); System.exit(1); } System.out.println("ファイルの書き込みが完了しました!"); } }

▼ FileWriter クラスの write メソッドでは、パラメータが int 型と char 型と String オブジェクトの

5種類がオーバーロード(overload:多重定義)されて居り、1文字と文字列の孰れもが書込可能 で有る。

void write(int c) 単一の文字を出力 void write(char[]) 文字の配列を出力 void write(char[] c, int off, int len) 文字の配列の一部を出力 void write(String s) 文字列を出力

void write(String s, int off, int len) 文字列の一部を出力

※ 猶、write メソッドでは、行末の改行を出力しない為、改行を必要とする場合には、エスケープシー ケンスの改行文字¥n を出力する必要が有る。

※ 猶、FileWriter コンストラクタの第2引数で true を指定すると、追加モード(Append)と成り、 ファイルの末尾にデータが付け加えられる様に成る。

テキストファイルの場合は、バ イト単位で入出力を行うより、 文字単位、或るいは、行単位で 入出力を行う方が便利な事が有 る。テキストファイルに書き込 み を 行 う 為 に は 、 java.io.FileWriter クラスを使用 する。同クラスのメソッドは、 総てインスタンスメソッドで有 る為、コンストラクタを使用し てインスタンスを生成する必要 が有る。

(7)

■ テキストファイルの読込 ■

下記のコードを、テキストエディタで入力し、FileIOtextR.java と謂うファイル名で保存した後、コン パイルして、実行する。

import java.io.*;

public class FileIOtextR {

public static void main(String args[]) { try { int d; // ファイルのオープン

FileReader f = new FileReader("TestFile.txt"); // データの読み込み(1文字宛読み込む) while((d = f.read()) != -1) { // データの表示(1文字宛表示する) System.out.print((char)d); } // ファイルのクローズ f.close(); } catch(Exception e) { System.err.println("例外発生:" + e); System.exit(1); } System.out.println("ファイルの読み込みが完了しました!"); } } ▼ FileReader クラスの read メソッドは文字単位(日本語なら2バイト)で読み込む。亦、パラメー

タがint 型で有る為、画面に表示する際には char 型にキャスト(cast:型変換)する必要が有る。 FileReader クラスの read メソッドでは、パラメータが無い場合と char 型の3種類がオーバーロー ド(overload:多重定義)されて居り、1文字と複数文字の孰れもが読込可能で有る。

int read() 単一の文字を入力 int read(char[] c) 文字の配列に入力 int read(char[] c, int off, int len) 文字の配列の一部に入力

パラメータ無しの場合は、0~65535(¥u0000~¥uFFFF)の範囲と仕ての文字を読み込み、char 型の配列では、格納開始位置オフセットoff から文字数 len の文字を読み込む。亦、戻り値には、パ ラメータ無しの場合は、読み込んだ文字コードが、char 型の配列では、読み込んだ文字数が返され、 ストリームの終わりに達した場合は、孰れも-1 が返される。 テキストファイルから読み 込 み を 行 う 為 に は 、 java.io.FileReader クラスを 使用する。同クラスのメソッ ドは、総てインスタンスメソ ッドで有る為、コンストラク タを使用してインスタンス を生成する必要が有る。

(8)

■ テキストファイルのコピー ■

下記のコードを、テキストエディタで入力し、FileIOtextC.java と謂うファイル名で保存した後、コン パイルして、実行する。

import java.io.*;

public class FileIOtextC {

public static void main(String args[ ]) { try { int d; // 入力ファイルのオープン

FileReader inp = new FileReader("TestInp.txt"); // 出力ファイルのオープン

FileWriter out = new FileWriter("TestOut.txt"); while ((d = inp.read()) != -1) // 入力 { out.write(d); // 出力 } // ファイルのクローズ inp.close(); out.close(); } catch (Exception e) { System.err.println("例外発生:" + e); System.exit(1); } System.out.println("ファイルのコピーが完了しました!"); } } ▼ FileReader クラスでは、読み込むファイルが存在しない場合にFileNotFoundException の例外が、 亦FileWriter クラスでは、ファイルにアクセスする事が出来ない場合に IOException の例外が投げ られる等、ファイル入出力に於いては、try~catch 文に依り、例外に対処する必要が有る。此の処 理は必須で有り、対処されて居ない場合は、コンパイル時にエラーが発生する。 此処では、例外をException クラスで受け取る事に依り、総ての例外に対処して居る。個々の例外 に対処する場合は、catch のパラメータに、発生する可能性の有る例外の種類を指定する。上記に 於いて個々の例外に対処するには、下記の様に夫々れの例外に対応するcatch 節を複数記述する。 catch(FileNotFoundException e) { // 読込時の例外処理 } catch(IOexception e) { // 書込時の例外処理 } テキストファイルをコピーす る 為 に は 、 読 み 込 む 為 の java.io.FileReader クラスと 書 き 込 む 為 の java.io.FileWriter クラス を 使用する。孰れのクラスのメ ソッドも、総てインスタンス メソッドで有る為、コンスト ラクタを使用してインスタン スを生成する必要が有る。

(9)

■ テキストファイルのコピー(バッファ利用) ■

前 記 の コ ー ド FileIOtextC.java の 該当 部分 を、 テ キス トエ ディ タで下 記 のコ ード に変 更し、 FileIOtextCB.java と謂うファイル名で保存した後、コンパイルして、実行する。

前出のプログラムは、ファイルから1 文字宛読み書きして居るので、余り能率的では無い。上記の FileReader オブジェクトとFileWriter オブジェクトを、夫々れ BufferedReader クラスと BufferedWriter クラスでラッ プ(Wrap)すると、バッファリングの効果に依り、実行速度が向上する。

// 入力ファイルのオープン

BufferedReader inp = new BufferedReader(new FileReader("TestInp.txt")); // 出力ファイルのオープン

BufferedWriter out = new BufferedWriter(new FileWriter("TestOut.txt"));

下記のコードを、テキストエディタで入力し、FileIOtextCBL.java と謂うファイル名で保存した後、コ ンパイルして、実行する。

import java.io.*;

public class FileIOtextCBL {

public static void main(String args[ ]) {

try {

String d;

// 入力ファイルのオープン

BufferedReader inp = new BufferedReader(new FileReader("TestInp.txt")); // 出力ファイルのオープン

BufferedWriter out = new BufferedWriter(new FileWriter("TestOut.txt")); while ((d = inp.readLine()) != null) // 入力

{ out.write(d); // 出力 out.newLine(); // 改行 } // ファイルのクローズ inp.close(); out.close(); } catch (Exception e) { System.err.println("例外発生:" + e); System.exit(1); } System.out.println("ファイルのコピーが完了しました!"); } } ▼ 読み込まれた行は Unicode の文字列に変換されるが、出力時には処理系の文字コードに戻される。 入力行には、改行は含まれない為、行を出力した後に、改行を出力する newLine()メソッドを使用 する必要が有る。此の方法なら、システム毎に改行コードの違い(Windows では 2 文字、UNIX で は1 文字として扱われる)を考える必要も無い。 猶、readLine()は、ファイルの終わり迄、読み尽くした後では、null と謂う特別な値を返す。此れ が返されれば、読み込み処理を終了する。 FileReader ク ラ ス に は readLine メ ソ ッ ド が 有 り、此れを使用すると、 文字単位ではなく、行単 位で、データを読み込む 事が出来る。

(10)

■ テキストファイルのコピー(エンコーディング利用) ■ 下記のコードを、テキストエディタで入力し、FileIOtextCE.java と謂うファイル名で保存した後、コ ンパイルして、実行する。 下記の例は、EUC コードで書かれたファイルを EUC エンコード方式を指定して読み込み、其の内容を Shift-JIS エンコード方式でエンコードし、別のファイルへ書き込むプログラムで有る。 import java.io.*;

public class FileIOtextCE {

public static void main(String args[ ]) { System.out.println("エンコーディング:" + System.getProperty("file.encoding")); try { int d; // 入力ファイルのオープン InputStreamReader inp =

new InputStreamReader(new FileInputStream("TestEUC.txt"), "EUC-JP"); // 出力ファイルのオープン

OutputStreamWriter out =

new OutputStreamWriter(new FileOutputStream("TestSJIS.txt"), "SJIS"); while ((d = inp.read()) != -1) // 入力 { out.write(d); // 出力 } // ファイルのクローズ inp.close(); out.close(); } catch (Exception e) { System.err.println("例外発生:" + e); System.exit(1); } System.out.println("ファイルのコピーが完了しました!"); } } ▼ EUC エンコードで読み込みを行う為には、コンストラクタの第1引数に読み込むオブジェクトを、 第2引数にEUC-JP を指定して、InputStreamReader オブジェクトを生成する。 Shift-JIS エンコードで書き込みを行う為には、コンストラクタの第1引数に書き込むオブジェクト を、第2引数にShift-JIS を指定し、OutputStreamWriter オブジェクトを生成する。 ※ 猶、Java インタープリタは、其の環境の標準的なエンコーディングを自動的に判断して使用する。 エンコーディングを調べるには、System.getProperty("file.encoding") を利用する。 エンコード方式を指定してファイル 入 出 力 処 理 を 行 う 為 に は 、 FileInputStream オブジェクトと FileOutputStream オ ブ ジ ェ ク ト を、夫々れ、エンコーディング機能 の有る InputStreamReader クラス とOutputStreamWriter クラスでラ ップ(Wrap)して使用する。

参照

関連したドキュメント

& Shipyarrd PFIs.. &

パターン 1 は外航 LNG 受入基地から内航 LNG 船を用いて内航 LNG 受入基地に輸送、その 後ローリー輸送で

2)海を取り巻く国際社会の動向

Wärtsilä の合弁会社である韓国 Wärtsilä Hyundai Engine Company Ltd 及び中国 Wärtsilä Qiyao Diesel Company Ltd と CSSC Wärtsilä Engine Co...

ASHATAMA http://www.indomarine.org 672 (Indo Marine, Indo Aerospace, Indo

[r]

Strengthening of Operators in maritime business and Develop connectivity to facilitate Multimodal Transport To expand trading routes of national merchant fleet and to

         --- 性状及び取り扱いに関する情報の義務付け   354 物質中  物質中  PRTR PRTR