byte配列のファイル操作

byte列をファイルへ出力するには、FileOutputStreamを使います。

次のように、 new FileOutputStream("ファイル名") の実行でファイルが作成されます。
この時、 FileOutputStreamオブジェクトが生成され、 このオブジェクトを使えば、それをcloseをするまで、writeメソッドで、byte配列を出力できます。
(なお、FileOutputStreamの生成でFileNotFoundExceptionを投げる指示があり、スロー宣言(throws Exception )などが必要です)

import java.io.FileOutputStream;

public class Test
{
	public static void main(String[] arg)throws Exception
	{
		FileOutputStream fos = new FileOutputStream("file.bin");
		// 上記の実行でファイルが生成されます。

		byte[] data;//ファイル書き込みデータを管理する配列

		data = new byte[2];
		data[0] = 0x0c; // CRコード(carriage return)
		data[1] = 0x0a; // LFコード(line feed) 
		fos.write(data);//出力(dataのbyte列をファイルに書き込む)

		data = new byte[] { 0x32, 0x01, 0x02 };//3byte
		fos.write(data);//出力(dataのbyte列をファイルに書き込む)

		fos.close();//閉じる(fosを使ったファイル操作を終えた時に実行)
	}
}

上記の実行において、2byteと3byteの配列を書き込んでいるので、最終的に5byteの長さで、次のイメージのファイルができます。

0x0c0x0a0x320x010x02

 (上記で出力したデータに意味はありません。よく使うコードなどを出力しました)
つまり、ファイルなどのbyte出力ストリーム(FileOutputStream)オブジェクトがfpwで管理されていると、次のよう表現で書き込むことができるわけです。
     fpw.write( byte型の配列 );
  なお、writeメソッドには、配列の一部を出力する次の使い方もできます。

     fpw.write(byte[] b, int off, int len)

これは、指定されたバイト配列からのオフセット位置 off から始まる len バイトをこのファイル出力ストリームに書き込みます。 なおwriteメソッドは、void型で戻り値はありません。

 

byte列をファイルから入力するには、FileInputStreamを使います。

次のように、 new FileInputStream("ファイル名") の実行で既存のファイルを開きます。
この時、 FileInputStreamオブジェクトが生成され、 このオブジェクトを使えば、それをcloseをするまで、 readメソッドで、byte配列を入力できます。
(なお既存のファイルが存在しない場合、FileInputStreamの生成でFileNotFoundExceptionを投げるように作られています。 よって、スロー宣言(throws Exception )などが必要です)
以下は、前述で作成した、次のようなファイルが実行位置にあって、 それを読み込み表示するコードとその実行例です

0x0c0x0a0x320x010x02
import java.io.FileInputStream;

public class Test {
	public static void main(String[] arg)throws Exception {
		FileInputStream fis = new FileInputStream("file.bin");
		// 上記の実行でファイルが生成されます。

		byte[] data= new byte[3];//ファイル読み込みデータを管理する3byte;配列

		fis.read(data);//入力(ファイルから3byte読み込む)
		System.out.printf(" %02X", data[0]);// 16進桁で、満たない左桁を0で埋めて表示
		System.out.printf(" %02X", data[1]);// 16進桁で、満たない左桁を0で埋めて表示
		char c = (char)data[2];//次のバイトをASCIIコードとして、その文字を取得
		System.out.printf(" %c", c);

		data = new byte[2];
		fis.read(data);//ファイルで、前回読み取った次位置からから2byte読み込む
		short k = data[0];
		k <<= 8;		// k = k << 8 に相当する処理で、k を左8bitシフトした値に変更(256倍している)
		k |= data[1];	// k = k | data[1] に相当する処理
		System.out.printf(" %02d", k);	// 10進数で、kを表示

		fis.close();//閉じる(fisを使ったファイル操作を終えた時に実行)
	}
}
Z:\Java>java Test
 0C 0A 2 258
Z:\Java>

2回に分けて、読み取っている例です。ファイル内の3byte目は、0x32は、 ASCII文字として0x32と表示しました。また、0x01,0x02の部分は Javaのshort型データとして使い、short型に変換して258と表示しました。 このように、ファイルなどのbyte入力ストリーム(FileInputStream)オブジェクトがfprで管理されていると、次のよう表現で読み込むことができるわけです。
     int n = fpr.read( byte型の配列 );
  なお、readメソッドには、配列の一部へ入力する次の使い方もできます。

     int n = fpr.read(byte[] b, int off, int len)

これは、指定されたバイト配列のオフセット位置 off から始まる len バイトを読み込みさせる指示です。 何れも、配列に読み込んだbyte数が戻り値になります。

また、byte入力ストリーム(FileInputStream)オブジェクトには、引数なしのreadメソッドも 存在します。これは、ストーリムから読み取った1byteを戻り値にするメソッドです。
このメソッドは、有効な入力がまだない場合にブロックします。 (これは入力待ちで returnしない状態です) そしてこれらのメソッドは、ファイルの終わりに達した場合に -1 を返します。この例は後述しています。

 

文字列をbyte列に変換する。

byte列を、どの文字に割り振るかは、システムによって違います
このbyte列を、どの文字に割り振るかを決めた仕様は キャラクタセット と呼ばれ、たくさんのキャラクタセット名が存在します。
文字列を簡単にファイル化する場合のPrintWriterクラス紹介しました。 (確認後はブラウザの戻る操作で戻ってください)
PrintWriterクラスのキャラクタセットはそのシステムで使われるデフォルトの文字です。
しかし、異機種間で、 取り扱う文字列を利用する場合は、 特別にキャラクタセット名を指定して、byte列へ変換しなければなりません。
例えば、日本語 Microsoft Windows XPなど使われる文字列は、特殊なShift JISで、このキャラクタセット名は、 MS932なのですが、そのbyte列へ変換してからファイル化しないと、そのシステムで使えないテキストファイルになります。  (例えば,Unixで作成したファイルをMicrosoft Windowsで使う場合などのです)
これに対応するため、Javaの文字列オブジェクトでは、指定のキャラクタセット名のbyte列に変換するgetBytesメソッドが用意されています。 このメソッドは、引数でキャラクタセット名を指定し、戻り値が変換したbyte配列になっています。

以下で簡単な文字列をMS932のキャラクタセットでbyte配列にして、それをファイル化するプログラム例を示します。

import java.io.FileOutputStream;

public class Test{
	public static void main(String[] arg)throws Exception{
		//ファイルへ出力するストリーム取得
		FileOutputStream fpw = new FileOutputStream("file.txt");
					// 上記の実行でファイルが生成されます。

		byte[] data;//ファイル書き込みデータを管理する配列

		data = "012345789abcd\r\nABCあいう\r\nHello".getBytes("MS932");//文字列をバイト列に変換
			//変換する時、変換後のバイト列を、『MS932』のキャラクタセットで使うように変換する。

		fpw.write(data);//dataのbyte列をファイルに書き込む。(Microsoft Windows用のテキストファイルとして)

		fpw.close();//閉じる
	}
}

上記で作成したテキストファイルは、どのシステムで実行した場合でも、 バイナリ的に、Microsoft Windowsへコピーできれば、そこで次のようにテキストとして見えるファイルになります。

このファイルをバイナリで読み取り、各コードを16進で表示するプログラム例と実行結果を示します。 ここでは、引数無しのreadメソッドを使っています。

import java.io.FileInputStream;// バイナリファイル読み取りストリーム用クラス

public class Test {
	public static void main(String[] arg)throws Exception{
		//ファイルから入力するストリーム取得
		FileInputStream fpr = new FileInputStream("file.txt");
		int pos = 0;	/* ファイル内位置管理用(position )*/
		int c; 			/* 1byte読み取り値記憶用*/
		while( (c = fpr.read()) != -1)	{
			if(pos % 16 == 0){
				System.out.printf("\n%04X ", pos);
			}
			System.out.printf("%02X ", c);/* 表示*/
			pos++;
		}
		fpr.close();
	}
}
Z:\Java>java Test

0000 30 31 32 33 34 35 37 38 39 61 62 63 64 0D 0A 41
0010 42 43 82 A0 82 A2 82 A4 0D 0A 48 65 6C 6C 6F
Z:\Java>

なお、ByteBufferクラスを使うと容易に各種基本データ型をbyte配列に設定できます。