7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JZOSを使ってJavaからデータセットにアクセスしてみる

Last updated at Posted at 2017-11-10

#概要
z/OS環境(IBMメインフレーム環境)におけるファイルはデータセット(data set)と呼ばれています。データセットはLinux,Unix,Windowsのファイルとはちょっと違います(※1)。
以下にデータセットの特徴とJava言語によるデータセット入出力処理の実装サンプルを示します。

※1 z/OS環境にはTSOやJCLで操作する環境とは別にUSSと呼ばれるUnix環境もあります。USS環境のファイルはLinux,Unix,Windowsのファイルと同じようにJavaの標準APIでアクセス可能です。

#データセットの特徴
データセットには以下のような特徴があります。

  1. 入力・出力いずれの場合も、オープンの前にまずアロケート(プロセスに対するデータセットの関連付け)をしなければならない。
  2. 新規データセットの作成時には、レコード・フォーマット、論理レコード長、ブロックサイズ(論理レコードをいくつかまとめたものをブロックといいます)、データセット編成等の属性を指定してアロケートしなければならない。
  3. 入力・出力いずれの場合でも、クローズの後にフリー(アロケートの逆でデータセットをプロセスから開放する)をしなければならない。
  4. レコードの区切り位置は改行文字ではなくレコード長により識別される。

上記のような特徴を持つデータセットは、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でエンコーディングされているものとします。

DSRead.java
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 ...")を引数に指定します。
  • allocコマンド(※3)とfreeコマンドには、DD名を指定します。DD名はプログラム内でデータセットを識別する論理名になります。ZFile#allocDummyDDNameメソッドでユニークなDD名を生成しています。
  • ファイルからデータ・レコードを読み込む処理はRecordReaderで行います。
    • RecordReaderのインスタンスは、前述のDD名を指定してファクトリー・メソッドRecordReader#newReaderForDDをコールすることによって取得します。APIの詳細は参考リンクのJZOS API(Javadoc)を参照してください。

※3 allocallocateの省略表記です。allocateコマンドの具体例は参考リンクallocateコマンドの例を参照してください。

#サンプル・プログラム(データセットへの出力処理)
以下のサンプル・プログラム(DSWrite.java)は、既に存在しているデータセット'USER01.TEST.DATA'に上書きモードでレコードを書き出します。データセット'USER01.TEST.DATA'は、固定長で論理レコード長が80バイトの編成とし、getTestDataメソッドで作った3行のレコードを出力します。データはUTF-8でエンコーディングして出力するものとします。

DSWrite.java
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

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?