#概要
z/OS環境(IBMメインフレーム環境)におけるファイルはデータセット(data set)と呼ばれています。データセットはLinux,Unix,Windowsのファイルとはちょっと違います(※1)。
以下にデータセットの特徴とJava言語によるデータセット入出力処理の実装サンプルを示します。
※1 z/OS環境にはTSOやJCLで操作する環境とは別にUSSと呼ばれるUnix環境もあります。USS環境のファイルはLinux,Unix,Windowsのファイルと同じようにJavaの標準APIでアクセス可能です。
#データセットの特徴
データセットには以下のような特徴があります。
- 入力・出力いずれの場合も、オープンの前にまずアロケート(プロセスに対するデータセットの関連付け)をしなければならない。
- 新規データセットの作成時には、レコード・フォーマット、論理レコード長、ブロックサイズ(論理レコードをいくつかまとめたものをブロックといいます)、データセット編成等の属性を指定してアロケートしなければならない。
- 入力・出力いずれの場合でも、クローズの後にフリー(アロケートの逆でデータセットをプロセスから開放する)をしなければならない。
- レコードの区切り位置は改行文字ではなくレコード長により識別される。
上記のような特徴を持つデータセットは、Java標準API(java.ioパッケージやjava.nioパッケージ)で入出力処理を実装することはできません。
では、どうするかというと、**Java Batch Launcher and Toolkit for z/OS(以降、JZOSと表記)**を利用します。
JZOSは、z/OS環境で実行するJavaアプリケーションの開発を支援するツールキットで、IBM Java for z/OSに含まれています(JZOSの概要については参考リンクJZOS Batch Launcher and Toolkitを参照)。
以下にデータセットからの入力処理を実装したサンプルJavaアプリケーションおよびデータセットへの出力処理を実装したサンプルJavaアプリケーションをそれぞれ示します(※2)。
※2 データセットには様々な種類がありますが、以降ではWindowsファイルやUnixファイルに類似していて最も単純な構造の順次編成方式のデータセットに対象を絞ってサンプルを示しています。
#サンプル・プログラム(データセットからの入力処理)
以下のサンプル・プログラム(DSRead.java)は、データセット'USER01.TEST.DATA'
からレコードを読み込み標準出力に書き出します。データはUTF-8
でエンコーディングされているものとします。
package sample;
import com.ibm.jzos.RecordReader;
import com.ibm.jzos.ZFile;
public class DSRead {
public void main(String args[]) throws Exception {
String ddName = ZFile.allocDummyDDName();
String dsName = "USER01.TEST.DATA";
RecordReader reader = null;
int x = 0;
try {
ZFile.bpxwdyn("alloc fi("+ddName+") da("+dsName+") shr reuse");
reader = RecordReader.newReaderForDD(ddName);
byte[] recordBuf = new byte[reader.getLrecl()];
while ((reader.read(recordBuf)) >= 0) {
String rec = new String(recordBuf, "UTF-8");
System.out.println(rec);
x++;
}
System.out.println("record count : "+x);
} catch(Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
ZFile.bpxwdyn("free fi("+ddName+")");
}
}
}
ここがポイント!
- データセットのアロケートとフリーは
ZFile#bpxwdyn
メソッドで行います。- このメソッドはダイナミック・アロケーション(プログラムから動的にデータセットをアロケーションすること)をするためにBPXWDYNと呼ばれるコマンド・インターフェースをコールします。実行したいコマンド文字列(
"alloc ..."
,"free ..."
)を引数に指定します。
- このメソッドはダイナミック・アロケーション(プログラムから動的にデータセットをアロケーションすること)をするためにBPXWDYNと呼ばれるコマンド・インターフェースをコールします。実行したいコマンド文字列(
- allocコマンド(※3)とfreeコマンドには、DD名を指定します。DD名はプログラム内でデータセットを識別する論理名になります。
ZFile#allocDummyDDName
メソッドでユニークなDD名を生成しています。 - ファイルからデータ・レコードを読み込む処理は
RecordReader
で行います。-
RecordReader
のインスタンスは、前述のDD名を指定してファクトリー・メソッドRecordReader#newReaderForDD
をコールすることによって取得します。APIの詳細は参考リンクのJZOS API(Javadoc)を参照してください。
-
※3 alloc
はallocate
の省略表記です。allocateコマンドの具体例は参考リンクallocateコマンドの例を参照してください。
#サンプル・プログラム(データセットへの出力処理)
以下のサンプル・プログラム(DSWrite.java)は、既に存在しているデータセット'USER01.TEST.DATA'に上書きモードでレコードを書き出します。データセット'USER01.TEST.DATA'は、固定長で論理レコード長が80バイトの編成とし、getTestData
メソッドで作った3行のレコードを出力します。データはUTF-8でエンコーディングして出力するものとします。
package sample;
import com.ibm.jzos.RecordWriter;
import com.ibm.jzos.ZFile;
public class DSWrite {
public void main(String args[]) throws Exception {
String ddName = ZFile.allocDummyDDName();
String dsName = "USER01.TEST.DATA";
RecordWriter writer = null;
int x = 0;
try {
ZFile.bpxwdyn("alloc fi("+ddName+") da("+dsName+") old reuse");
writer = RecordWriter.newWriterForDD(ddName);
int lrecl = writer.getLrecl();
String records[] = getTestData();
for (String record : records) {
writer.write(record.getBytes("UTF-8"), 0, lrecl);
x++;
}
System.out.println("record count : "+x);
} catch(Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
ZFile.bpxwdyn("free fi("+ddName+")");
}
}
private String[] getTestData() {
String[] records = new String[3];
records[0] = String.format("%-80s", "AAAAAAAAAAAAAAAAAAAA");
records[1] = String.format("%-80s", "BBBBBBBBBBBBBBBBBBBB");
records[2] = String.format("%-80s", "CCCCCCCCCCCCCCCCCCCC");
return records;
}
}
ここがポイント!
- データセットのアロケートとフリーについては上記サンプル
DSRead.java
とほぼ同じです。- 唯一異なるのは、allocコマンドのDISPパラメーターに、shrではなくoldを指定している点です。oldを指定することによってデータセットを排他的にアクセスできます。
- ファイルにデータ・レコードを書き出す処理は
RecordWriter
で行います。-
RecordWrite
のインスタンスは、DD名を指定してファクトリー・メソッドRecordWriter#newWriterForDD
をコールすることによって取得します。APIの詳細は参考リンクのJZOS API(Javadoc)を参照してください。
-
#参考リンク
JZOS Batch Launcher and Toolkit
https://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com.ibm.java.zsecurity.80.doc/zsecurity-component/jzos.html
JZOS API (Javadoc)
http://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com.ibm.java.zsecurity.api.80.doc/com.ibm.jzos/index.html
BPXWDYN
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.2.0/com.ibm.zos.v2r2.bpxb600/wdyn.htm
allocateコマンドの例
http://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.ikjc500/ikj2l2_ALLOCATE_command_examples.htm