入出力まとめ
Linux における代表的な入出力
Javaの前にLinuxにおける入出力を知っておいたほうがいいと思います。
Javaプログラムを実行している環境であるLinuxでは、代表的な入出力として以下があります。
- 標準入出力
- ファイル入出力
標準入出力は、主に画面に映し出されるもの・キーボードや他のプログラムからの入力などが挙げられます。
幾つかコマンドを実行して入出力を確認してください。
名称 | 例 | 説明 |
---|---|---|
標準出力1 | echo "出力内容" | 画面に出力 |
標準出力2 | echo "出力内容" >> file.txt | 標準出力されたものを> でファイル書込、>> で追記.(リダイレクトという) |
標準入力1 | read VAL | 変数VALに格納。echo $VAL で標準出力に表示できる |
標準入力2 | cat << END_OF_LINE | END_OF_LINE という行が出る前入力を続ける。EOF やEOL という行が出るまで続けることが多い。 |
標準入力3 | 下記参照 | echo の標準出力を | (パイプライン) を用いて、tr でキャッチしている。tr は置換コマンド。-d (delete)なので、H を除去して、ELLO が出るはず。 |
ファイル出力 | echo "HELLO" >> hello.txt | >> を用いてhello.txt に追記。> で追記せずにファイル出力 |
ファイル入力 | cat < hello.txt | hello.txtを読み込む. |
下記参照されるところ
echo "HELLO" | td -d 'H'
Javaにおける入出力
Javaでは、ストリームと呼ばれる順序付けられたデータの列を扱います。
大別して2種類あります。
名称 | 説明 |
---|---|
バイトストリーム | 8bit単位でバイナリデータ(画像やプログラムデータなど文字で表現されないデータ)を扱う |
文字ストリーム | 16bit単位でUTF-16を扱う |
それらを利用するクラスは以下の通りです。
種類 | バイトストリーム | 文字ストリーム |
---|---|---|
入力 | InputStream | Reader |
出力 | OutputStream | Writer |
それらの代表的なメソッドを以下に示します。
名前 | 処理 |
---|---|
InputStream.read() | 1byteを読み込み、INT型で0-255(8bit10進数)の何れか値を返す。 |
Reader.read() | 1文字を読み込み、INT型で0-65535(16bit10進数)で返す。 |
OutputStream.write(int i) | 1byte(変数i の下位8bit)を書込 |
Writer.write(int i) | 1文字(変数i の下位16bit)を書き込む。 |
これらをファイルやバッファ用に継承したもののうち代表的なものが以下のものです。
InputStream/OutputStream
名称 | 説明 |
---|---|
ByteArrayInputStream | バイト型の配列を入力する。 |
BufferedInputStream | 8192Byte(=8KiB)をバッファ(一時的で高速な保存領域)に溜め込み、入力する。 |
FileInputStream | ファイルから1Byte毎に読み込む。 |
PipedInputStream | 並列処理(スレッド処理)で別の処理からの出力を入力する |
Outputの場合は、適宜InputStreamをOutputStreamに返れば大体同じです。
Outputの場合はこのほかに、PrintStream
というクラスもあります。
PrintStreamはテキスト出力します。System.out.println()
はPrintStream
を利用しています。
例
////////////////////////////////////////////////
// File入力する
///////////
// 文字列連結用
StringBuilder sb = new StringBuilder();
// FileInputStream sample.txtを読込
FileInputStream fis = new FileInputStream("sample.txt");
while(true){
int line = fis.read(); // 1byteずつ読込、その1byteを返す。
if(line == -1) break; // lineが-1を取ったらファイル入力終了
else sb.append(line); // sbに追記する
}
System.out.println(sb.toString()); //標準出力に吐く
/////////////////////////////////////////////////////////
// Bufferedを併用してみる
////////////////
sb.setLength(0); //StringBuilderの中身を空にする。
// Bufferedを併用
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("sample.txt") );
while(true){
int line = bis.read(); // 8KiB毎にバッファ読込しておき、1byteずつ返す
if(line == -1) break;
else sb.append(line);
}
//////////////////////////////////////////////////////////
// 入力したファイルを別のファイルに出力する
///////////////////
BufferedOutputStream bos = null;
// エラーが発生しても`bos.close()`を実行しないといけないので`try-catch-finally`を利用する。
try {
// sample.copy.txtに出力する
bos = new BufferedOutputStream(new FileOutputStream("sample.copy.txt"));
// ただのコピーだとつまらないので1行目にメッセージ入れる。
String mesg = "***** THIS FILE IS COPIED FILE!!! USING JAVA PROGRAM *****";
byte[] mesg_bytes =mesg.getBytes();
bos.write(mesg_bytes);
// 入力した文字列を追記する
bos.write(sb.toString().getBytes());
// Flush(書き込み)する。(Flush(フラッシュ)-> 書込み でピンとくるようにしておく。)
bos.flush();
}catch(Exception e){
e.printStackTrace(); // Exceptionは printStackTrace() を利用するとエラーの詳細をprintしてくれる。
}finally{
try{
//エラーを吐こうが、吐かないが、バッファのクローズを最後に行う。バッファが開きっぱなしは良くない、というか危ない。
bos.close();
}catch(IOException e){
e.printStackTrace();
}
}
上記例でもわかる通り、
write()
はbyte[]
しか受け付けてくれません。ここでDataOutputStreamを利用すれば、writeUTF()やwriteCharなどが利用でき他の型でもOutputできます。
Reader/Writer
文字ストリームにも色々あります。
- CharArrayReader
- BufferedReader/Writer
- FileReader/Writer
- PrintWriter
- StringWriter
- PipedReader/Writer
- InputStreamReader
- OutputStreamWriter
例
fWriter = null;
BufferedReader bufReader = null;
BufferedWriter bufWriter = nill;
try{
// インスタンス生成
fWriter = new FileWriter("HelloWorld.sh");
bufReader = new BufferedReader(new FileReader("sample.txt"));
bufWriter = new BufferedWriter(new FileWriter("copied.txt"));
// FileWriteのみならバッファつかわないのでflush()しない
fWriter.write("#!/bin/bash");
fWriter.write("echo HelloWorld!");
// lineがnullになるまでLoop.
while((String line = bufReader.readLine()) != null){
bufWriter.write(line);
}
// 書込
bufWriter.flush();
}finally{
try{
//ストリームを閉じる
bufWriter.close();
bufReader.close();
}catch(IOException e){
System.err.println(e);
}
}
そのほか
前述したDataOutputStream(もちろんDataInputStreamも)をはじめとして、様々な入出力方法があります。
あとは単なるコピーならば、Javaのバージョン8で追加されたNew I/O 2のもの(Filesクラスなど)を利用するほうが楽です。
参考: ファイルについて
また、読み書きの際に文字コードを指定したり変換したりすることもできます。
参考: bituse.info
文字コード変換に関しては、クラスによっては講義で実施するような課題ですので、試してみても良いと思います。(文字コードを検出する、UTF-8からEUC-JPに変更するなど)
最終更新日: 2021年4月30日