テキストファイルを読み込む
FileInputStreamクラス
ファイルからプログラムへのStreamを扱います。
java.io.FileInputStream
FileをInputするStreamだ。
そのまんまね。
目次
1.継承関係
データをストリームとして利用する場合には、
Streamインターフェース(クラスの仲間)を実装したクラスを利用します。
FileInputStreamも、Streamインターフェースを実装したクラスの仲間です。
特に、File から Input する Stream を扱います。
Streamインターフェースを実装したクラスの継承関係
java.io.InputStream 抽象クラス (java.io.Streamインターフェースを実装)
|
└ java.io.FileInputStream クラス
重要
File から Input する Stream を扱います。
2.コンストラクタ
FileInputStreamクラスは、引数のファイルからのストリームを作って、
ファイル内のデータをバイト単位で取得します。
相手のファイルがテキストファイルである必要はありません。
public FileInputStream(String name)
throws java.io.FileNotFoundException
public FileInputStream(File file)
throws java.io.FileNotFoundException
例外処理を記述する場合には、以下をインポートする必要があります。
例外のimport
import java.io.FileNotFoundException;
3.readメソッド
readメソッドは、ストリームから 1byte(8bit)を読み込んで、intで返します。
readメソッドを実行するたびに、次の 1byteを返します。
ストリームの終端に達すると -1 を返します。
public int read()
throws java.io.IOException
例外処理を記述する場合には、以下をインポートする必要があります。
例外のimport
import java.io.IOException;
ストリームの終わりに達した場合
-1 を返します。
-1が出るまで
readし続ければ
ファイル全体を読み込める。
readすると
勝手に次のバイトに
進んじゃうんスか?
そうなんだ。だから、
一文で代入と評価をしないといけない。
ちょっと独特な書き方になるぞ。
青い部分の代入式全体を、オレンジ色の部分で評価しています。
byteData に -1 が代入されると whileブロックを抜けます。
byteData 変数の宣言が whileブロックの外側にあるのもポイントです。
4.closeメソッド
public void close()
throws java.io.IOException
例外処理を記述する場合には、以下をインポートする必要があります。
例外のimport
import java.io.IOException;
閉じないと
なんかやばいんスか?
ちゃんと閉じないと
後ろから恐ろしい人影が~
5.サンプルコード
読み込む為のファイルを hello.txt という名前で、wsディレクトリに配置しました。
中身は以下のようにしました。
Sample02_01 を wsディレクトリで実行して中身を読み込んでみましょう。
This is hello.txt
こんにちわ。
end
//Sample02_01.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
class Sample02_01{
public static void main(String[] args){
String path = "hello.txt";
File file = new File(path);
try {
FileInputStream inStream = new FileInputStream(file);
int byteData;
while((byteData = inStream.read()) != -1) {
System.out.println(byteData);
/*
String str16 = String.format("%1$d\t0x%1$x\t%c", byteData);
System.out.println(str16);
*/
}
inStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
}
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Sample02_01.java
ws>java Sample02_01
84 0x54 T
104 0x68 h
105 0x69 i
115 0x73 s
32 0x20 空白
105 0x69 i
115 0x73 s
32 0x20 空白
104 0x68 h
101 0x65 e
108 0x6c l
108 0x6c l
111 0x6f o
46 0x2e .
116 0x74 t
120 0x78 x
116 0x74 t
10 0x0a 改行
227 0xe3 0xe38193 こ
129 0x81 ↑↑
147 0x93 ↑
227 0xe3 0xe38293 ん
130 0x82
147 0x93
227 0xe3 0xe381ab に
129 0x81
171 0xab
227 0xe3 0xe381a1 ち
129 0x81
161 0xa1
227 0xe3 0xe3828f わ
130 0x82
143 0x8f
227 0xe3 0xe38082 。
128 0x80
130 0x82
10 0x0a 改行
101 0x65 e
110 0x6e n
100 0x64 d
10 0x0a 改行
説明のため
16進数表記と文字を
添えてみた。
FileInputStreamクラスは、相手のファイルにどのようなデータが入っているか
何の解釈もせずに、バイト列として読み込みます。
今回用意した hello.txt は、文字コードが UTF-8 でしたので、
日本語部分は 3バイトで一文字ですが、FileInputStreamは、容赦なく1バイトにぶった切りました。
すべて ASCII文字であれば、(char)byteData とすれば解決できますが、
複数バイトの文字はダメですね。
これ
使えなくないっスか?
確かに。
これではテキストファイルを
読み込んだとは言えないな。
6.補足 文字符号化形式 UTF-8
これは細かい話だ。
参考程度で良いぞ。
少し細かい話ですが補足させて下さい。
Sample02_01 の結果を見てもわかる通り UTF-8 での日本語部分は 3バイトで表現されています。
でも、単純に 3バイトを結合しても、いわゆる Unicode の文字コードにはなりません。
byte配列にすると、文字の境目が分からなくなってしまうので、
文字コード(文字集合)←→ byte配列 の変換は単純ではないのです。
文字 'こ' の場合
Unicode の文字コード 0x3053 ←→ UTF-8 の byte配列 [0xe3,0x81,0x93]
この変換の種類を 文字符号化形式 といいます。
UTF-8 とは、厳密に言うと、文字符号化形式の一種です。
ちなみにASCII文字は、byte配列にしてもそのままの値です。
この変換は後述の Reader や writer が自動でやってくれます。
それで Reader が
出てくるわけね?
お疲れ様でした。