Das Ein- und Aussteigen der IBM Mainframe-Dateien in Java kann etwas mühsam sein:
Als ich darüber nachdachte, ob ich es selbst machen sollte, fand ich eine sehr praktische Utility-Klasse, die als Open Source bereitgestellt wurde, und werde daher die Verwendung vorstellen. ** * Obwohl dies praktisch ist, gibt es auf Japanisch nur wenige Informationen. Es ist eine Verschwendung. ** </ font>
IBM Toolbox for Java Vom Namen her fühlt es sich wie DER Hauptrahmen an.
Bevor ich das Tool vorstelle, werde ich kurz erläutern, was Sie von diesem Tool erwarten, dh die Anforderungen definieren und erläutern, wie das Tool gemäß diesen Anforderungen verwendet wird.
Es wird davon ausgegangen, dass der folgende IBM Mainframe-Dateidatensatz in Java eingegeben / ausgegeben wird.
Niveau | Name des Datenelements | Schimmel | Anzahl an Ziffern | Richtigkeit | Wiederholend | Teilzeitstelle | Bemerkungen |
---|---|---|---|---|---|---|---|
01 | ORDER-REC | 124 | Bestelldatensatz | ||||
03 | REC-NO | B | 4 | 2 | Rekordzahl | ||
03 | ORDER-NO | C | 10 | 10 | Bestellnummer | ||
03 | ZIP-CD | C | 8 | 8 | Postleitzahl | ||
03 | ADDRESS | C | 20 | 20 | Adresse(18 Bytes für IBM Kanji-Code, 20 Bytes für Shift-Code) | ||
03 | PRODUCT-GR | S | 3 | 84 | Produktgruppenartikel(OCCCURS 3 mal) | ||
05 | PRODUCT-CD | C | 15 | 15 | Produktcode | ||
05 | PRODUCT-AMT | Z | 5 | 2 | 5 | Produktgewicht(Zonen-Dezimalzahl) | |
05 | UNIT-PRC | P | 7 | 2 | 4 | Stückpreis(Dezimal gepackt) | |
05 | DISCOUNT-PRC | P | 7 | 2 | 4 | Rabattbetrag(Dezimal gepackt) |
Typlegende:
Schimmel | Erläuterung |
---|---|
B | Binärtyp. Wenn Sie die obige "Datensatznummer" in COBOL schreiben, wird "S9"(4) COMP-Vier ". Da es sich um eine 4-stellige Binärzahl handelt, beträgt die Anzahl der Bytes 2 Bytes. |
C | Zeichentyp. Wenn Sie die obige "Bestellnummer" in COBOL schreiben, "X"(10)」。 |
S | Gruppenelement. Es bündelt mehrere Datenelemente. |
P | Pack Dezimaltyp. Wenn Sie den obigen "Stückpreis" in COBOL schreiben, wird "S9"(7)V9(2) COMP-3」。 |
Z | Zonen-Dezimaltyp. Wenn das obige "Produktgewicht" in COBOL geschrieben ist, "9(5)V9(2)」。 |
Erläuterungen zu Zonen-Dezimalzahlen (auch als externe Dezimalzahlen und entpackte Dezimalzahlen bezeichnet) und gepackten Dezimalzahlen (interne Dezimalzahlen) finden Sie unter den folgenden URLs. https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%83%E3%82%AF10%E9%80%B2%E6%95%B0 https://www.ibm.com/support/knowledgecenter/ja/SSQ2R2_9.1.0/com.ibm.etools.cbl.win.doc/topics/cpari20e.htm#header_19
Erstellen Sie eine Datensatzformat-Definitionsdatei für die Mainframe-Datei und aktivieren Sie die Eingabe und Ausgabe der Datei entsprechend. Mit IBM ToolBox für Java können Sie Dateien basierend auf RFML-Dateien im XML-Format als Definitionsdateien für das Datensatzformat eingeben und ausgeben. Machen Sie es zuerst und setzen Sie es auf den Klassenpfad. Dies dient dazu, diese Definitionsdatei später vom Java-Programm aus dem Klassenpfad abzurufen.
Die DTD für diese XML-Datei finden Sie unter Programmieren von IBM Toolbox für Java. Beachten Sie, wo "ccs id =" 930 "" steht. Es wird auf der Root-Ebene und unter "ADRESS" geschrieben. Dies gibt den Zeichencode des Hauptrahmens an. Wenn Sie jedoch den gesamten Zeichencode angeben möchten, schreiben Sie ihn auf dieser Stammebene. Wenn einzeln angegeben, kann es für jedes Datenelement angegeben werden.
ORDER-FILE.rfml(Definitionsdatei für das Mainframe-Datensatzformat)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE rfml SYSTEM "rfml.dtd">
<rfml version="4.0" ccsid="930">
<struct name="PRODUCT-GR">
<data name="PRODUCT-CD" type="char" length="15"/>
<data name="PRODUCT-AMT" type="zoned" length="5" precision="2"/>
<data name="UNIT-PRC" type="packed" length="7" precision="2"/>
<data name="DISCOUNT-PRC" type="packed" length="7" precision="2"/>
</struct>
<recordformat name="ORDER01-REC">
<data name="REC-NO" type="int" length="2"/>
<data name="ORDER-NO" type="char" length="10"/>
<data name="ZIP-CD" type="char" length="8"/>
<data name="ADRESS" type="char" length="20" ccsid="930"/>
<data name="PRODUCT-GR" type="struct" struct="PRODUCT-GR" count="3"/>
</recordformat>
</rfml>
Das Folgende ist ein Beispiel für einen Fehler. Struktur und Array werden nicht unterstützt. Mit anderen Worten, Gruppenelemente und OCCURS können nicht verwendet werden. was ist zu tun?
Ausgabe der Hauptbilddatei Teil 1(Fehlerbeispiel)
/**
*Ausgabe der Hauptbilddatei. <BR>
*Gibt die Mainframe-Datei gemäß der Datensatzformatdefinition der RFML-Datei aus.<BR>
* {@code
rec.setField("PRODUCT-GR", null);}An dem Ort{@code
com.ibm.as400.access.ExtendedIllegalArgumentException: name (PRODUCT-GR): Field was not found.
}<BR>
*Ich bekomme eine Ausnahme. In der folgenden API-Dokumentation wird angegeben, dass Structure nicht unterstützt wird. Array wird ebenfalls nicht unterstützt.<BR>
* <a href=
* "https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzahh/javadoc/com/ibm/as400/data/RecordFormatDocument.html">
* https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzahh/javadoc/com/ibm/as400/data/RecordFormatDocument.html</a>
*/
@Test
public void test01MfFileOutput() {
//Suchen und lesen Sie die Datensatzformatdefinition im Klassenpfad.
RecordFormatDocument rfd = null;
try {
rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
} catch (XmlException e) {
throw new RuntimeException(e);
}
//Dateiausgabe mit Hauptrahmenzeichencode.
File ioFile = new File("./data/ORDER_FILE.dat");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(ioFile);
Record rec = rfd.toRecordFormat("ORDER01-REC").getNewRecord();
for (short i = 1; i < 11; i++) {
rec.setField("REC-NO", new Short(i));
rec.setField("ORDER-NO", "170423-123");
rec.setField("ZIP-CD", "103-0028");
rec.setField("ADRESS", "Yaesu, Chuo-ku, Tokio");
//↓ Hier tritt eine Ausnahme auf, also kommentieren Sie aus.
// rec.setField("PRODUCT-GR", null);
//Byte-Array und Ausgabe in Datei.
byte[] buf = rec.getContents();
StringUtil.dump("DEBUG:", buf, "");
fos.write(buf);
}
fos.flush();
} catch (XmlException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
Gruppenelemente und OCCURS können nicht verwendet werden. Gehen Sie daher wie folgt vor.
ORDER-FILE.rfml(Definitionsdatei für das Mainframe-Datensatzformat. Der Gruppenelementteil hat eine andere Datensatzdefinition.)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE rfml SYSTEM "rfml.dtd">
<rfml version="4.0" ccsid="930">
<recordformat name="PRODUCT-GR">
<data name="PRODUCT-CD" type="char" length="15"/>
<data name="PRODUCT-AMT" type="zoned" length="5" precision="2"/>
<data name="UNIT-PRC" type="packed" length="7" precision="2"/>
<data name="DISCOUNT-PRC" type="packed" length="7" precision="2"/>
</recordformat>
<recordformat name="ORDER01-REC">
<data name="REC-NO" type="int" length="2"/>
<data name="ORDER-NO" type="char" length="10"/>
<data name="ZIP-CD" type="char" length="8"/>
<data name="ADRESS" type="char" length="20" ccsid="930"/>
<data name="PRODUCT-B" type="byte" length="84"/>
</recordformat>
</rfml>
Ausgabe der Hauptbilddatei Teil 2(Erfolgsgeschichte)
/**
*Ausgabe der Hauptbilddatei. <BR>
*Gibt die Mainframe-Datei gemäß der Datensatzformatdefinition der RFML-Datei aus.<BR>
* 1.Da sich das Gruppenelement und OCCURS nicht wie beabsichtigt verhalten, wird dieser Teil als Byte-Array betrachtet.<BR>
* 2.Definieren Sie den Gruppenelementteil in einer anderen Datensatzformatdefinition und legen Sie dort ein Java-Objekt fest, um ein Byte-Array mit MF-Zeichencode zu erstellen.<br>
*3. 3. Über 2 über 1.Einstellen.
*/
@Test
public void test02MfFileOutput() {
//Suchen und lesen Sie die Datensatzformatdefinition im Klassenpfad.
RecordFormatDocument rfd = null;
try {
rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
} catch (XmlException e) {
throw new RuntimeException(e);
}
//Dateiausgabe mit Hauptrahmenzeichencode.
File ioFile = new File("./data/ORDER_FILE.dat");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(ioFile);
Record rec = rfd.toRecordFormat("ORDER01-REC").getNewRecord();
Record grp = rfd.toRecordFormat("PRODUCT-GR").getNewRecord();
for (int i = 1; i < 11; i++) {
rec.setField("REC-NO", new Short((short) i));
rec.setField("ORDER-NO", "170423-123");
rec.setField("ZIP-CD", "103-0028");
rec.setField("ADRESS", "Yaesu, Chuo-ku, Tokio");
//Der Code für den OCCURS-Teil des Gruppenelements.
//Ein Bytestrom des gesamten Gruppenelements, an das das Element übertragen wird.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//Bytelänge des Ziels für die Elementübertragung ÷ 1 Bytelänge für OCCURS(PRODUCT-GR)= Anzahl der OCCC-URS
int occursCount = rec.getFieldAsBytes("PRODUCT-B").length / grp.getRecordLength();
//OCCURS Wiederholen Sie dies einige Minuten lang
for (int j = 0; j < occursCount; j++) {
grp.setField("PRODUCT-CD", "ABCDEFGHIJ-000" + j);
grp.setField("PRODUCT-AMT", new BigDecimal("123.45"));
grp.setField("UNIT-PRC", new BigDecimal("+12345.67"));
grp.setField("DISCOUNT-PRC", new BigDecimal("-45.6"));
baos.write(grp.getContents());
}
//In einem Byte-Array von Gruppenelementen festlegen.
rec.setField("PRODUCT-B", baos.toByteArray());
//Byte-Array und Ausgabe in Datei.
byte[] buf = rec.getContents();
StringUtil.dump("DEBUG:", buf, "");
fos.write(buf);
}
fos.flush();
} catch (XmlException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
Gruppenelemente und OCCURS können nicht verwendet werden. Verwenden Sie daher das in der obigen Dateiausgabe gezeigte Bild.
Eingabe der Hauptbilddatei
/**
*Eingabe der Hauptbilddatei. <BR>
*Geben Sie die Mainframe-Datei gemäß der Datensatzformatdefinition der RFML-Datei ein.<BR>
* 1.Da sich das Gruppenelement und OCCURS nicht wie beabsichtigt verhalten, wird dieser Teil als Byte-Array betrachtet.<BR>
* 2.Definieren Sie den Gruppenelementteil in einer anderen Datensatzformatdefinition, legen Sie dort das Byte-Array des MF-Zeichencodes fest und machen Sie es zu einem Java-Objekt.<br>
*/
@Test
public void test03MfFileInput() {
//Erstellen Sie eine Mainframe-Datei.
this.test02MfFileOutput();
//Suchen und lesen Sie die Datensatzformatdefinition im Klassenpfad.
RecordFormatDocument rfd = null;
try {
rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
} catch (XmlException e) {
throw new RuntimeException(e);
}
//Geben Sie eine Datei mit dem Zeichencode des Hauptrahmens ein.
File ioFile = new File("./data/ORDER_FILE.dat");
FileInputStream fis = null;
try {
Record rec = rfd.toRecordFormat("ORDER01-REC").getNewRecord();
Record grp = rfd.toRecordFormat("PRODUCT-GR").getNewRecord();
fis = new FileInputStream(ioFile);
//Ruft die Anzahl der Bytes für einen Datensatz ab und erstellt ein Byte-Array für den Lesepuffer.
byte[] recordBuf = new byte[rec.getRecordLength()];
//Die MF-Datei enthält keine Zeilenvorschubzeichen. Daher wird es für die Anzahl der Bytes eines Datensatzes in den Puffer eingelesen.
while (fis.read(recordBuf) != -1) {
//Aufzeichnung aus dem Byte-Array des Puffers.
rec.setContents(recordBuf);
System.out.print("[" + rec.getField("REC-NO"));
System.out.print("],[" + rec.getField("ORDER-NO"));
//Der Code für den OCCURS-Teil des Gruppenelements.
//Ein Bytestrom des gesamten Gruppenelements, von dem das Element erhalten wurde.
ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) rec.getField("PRODUCT-B"));
//Erstellen Sie einen Lesepuffer für 1 OCCURS.
byte[] groupBuf = new byte[grp.getRecordLength()];
while (bais.read(groupBuf) != -1) {
grp.setContents(groupBuf);
System.out.print("],[" + grp.getField("PRODUCT-CD"));
System.out.print("],[" + grp.getField("PRODUCT-AMT"));
System.out.print("],[" + grp.getField("UNIT-PRC"));
System.out.print("],[" + grp.getField("DISCOUNT-PRC"));
}
System.out.println("]");
}
} catch (XmlException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
rfd.toRecord ("ORDER-REC"). getRecordLength () löst die folgende Ausnahme aus: 「com.ibm.as400.data.PcmlException: Value is not set. Processing element 'ORDER-REC.REC-NO'.」 Sie können die Länge wahrscheinlich nicht abrufen, da das Record-Objekt nicht im RecordFormatDocument-Objekt erstellt wurde. Ich ändere den Beispielcode, um ein Objekt mit getNewRecord () zu erstellen und dann die Länge zu erhalten.
Sie haben den Puffer im RecordFormatDocument-Objekt nicht festgelegt, nachdem Sie ihn in den Puffer eingelesen haben. while (fis.read(buffer) != -1) { rfd.setValues("ORDER-REC", buffer);
Der folgende Code ist beide Methoden, die ORDER-NOTE abrufen, jedoch mit unterschiedlichen Ergebnissen. (1) rfd.getValue("ORDER-REC.ORDER-NOTE") (2) rec.getField("ORDER-NOTE") In (1) wird der nachfolgende Leerzeichen von String ohne Erlaubnis gelöscht. (2) bleibt unverändert, wenn ein nachfolgender Raum vorhanden ist. (1) scheint PcmlDataValues.toObject () intern aufzurufen. Unter ihnen trimString.
PcmlDataValues.toObject()
//For Strings, trim blanks and nulls appropriately
if (dataType == PcmlData.CHAR) {
newVal = trimString((String)newVal, getTrim());
}
getValue () macht etwas Egoistisches, daher ist es besser, die Methode getField () zu verwenden.
AS400Array kann in RFML-Dateien schreiben, aber wenn es in RFML-Dateien eingelesen wird, wird seine OCCURS-Nummer nicht reproduziert. AS400Structre kann keine RFML-Dateien schreiben. Eine Ausnahme tritt auf, wenn ich versuche, sie als RFML-Datei zu lesen und zu verwenden.
Wenn Stream für die Dateieingabe / -ausgabe verwendet wird, ist es besser, das Byte-Array von Gruppenelementen mit Stream als Ganzes einzugeben / auszugeben.
IBMToolboxTest.java
package jp.golden.cat.util;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharConversionException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import com.ibm.as400.access.AS400Array;
import com.ibm.as400.access.AS400Bin4;
import com.ibm.as400.access.AS400ByteArray;
import com.ibm.as400.access.AS400DataType;
import com.ibm.as400.access.AS400PackedDecimal;
import com.ibm.as400.access.AS400Structure;
import com.ibm.as400.access.AS400Text;
import com.ibm.as400.access.ArrayFieldDescription;
import com.ibm.as400.access.BinaryFieldDescription;
import com.ibm.as400.access.CharacterFieldDescription;
import com.ibm.as400.access.HexFieldDescription;
import com.ibm.as400.access.PackedDecimalFieldDescription;
import com.ibm.as400.access.Record;
import com.ibm.as400.access.RecordFormat;
import com.ibm.as400.data.RecordFormatDocument;
import com.ibm.as400.data.XmlException;
/**
*Testen der IBM Toolbox für Java.<BR>
*
* <H1>Installation und Einrichtung</H1><BR>
*Auf der Download-Seite unten finden Sie die ZIP-Datei mit der OSS-Version des JAR(Zum Beispiel jtopen_9_3.zip)Herunterladen.<br>
* 「jtopen_9_3.zip\lib\java8\jt400.Führen Sie "jar" durch den Klassenpfad.<br>
* <br>
* <H1>Informationsquellen usw.</H1> <BR>
*IBM Toolbox für Java. Eine Übersichtsbeschreibung von IBM. URL:<a href=
* "https://www.ibm.com/support/knowledgecenter/ja/ssw_ibm_i_73/rzahh/page1.htm">https://www.ibm.com/support/knowledgecenter/ja/ssw_ibm_i_73/rzahh/page1.htm</a><BR>
*Programmieren von IBM Toolbox für Java. PDF Datei. Gliederung der Programmiermethoden. URL:<a href=
* "https://www.ibm.com/support/knowledgecenter/ja/ssw_ibm_i_73/rzahh/rzahhpdf.pdf">https://www.ibm.com/support/knowledgecenter/ja/ssw_ibm_i_73/rzahh/rzahhpdf.pdf</a><BR>
* IBM Toolbox for Java API Document。URL:<a href=
* "https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_72/rzahh/javadoc/index.html">https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_72/rzahh/javadoc/index.html</a><BR>
* JTOpen: The Open Source version of the IBM Toolbox for
*Java. Eine Übersicht über die Open Source Version. URL:<a href=
* "http://jt400.sourceforge.net/">http://jt400.sourceforge.net/</a><BR>
* JTOpen: The Open Source version of the IBM Toolbox for
*Java-Download-Seite. URL:<a href=
* "https://sourceforge.net/projects/jt400/">https://sourceforge.net/projects/jt400/</a><BR>
*Download-URL für die neueste Version. URL:<a href=
* "https://sourceforge.net/projects/jt400/files/latest/download?source=files">https://sourceforge.net/projects/jt400/files/latest/download?source=files</a><BR>
*Lizenz für JTOpen und IBM Toolbox für Java. Beide sind "IBM Public License Version"
* 1.0」。URL:<a href=
* "https://opensource.org/licenses/ibmpl.php">https://opensource.org/licenses/ibmpl.php</a><BR>
*/
public class IBMToolboxTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
/**
*Ausgabe der Hauptbilddatei. <BR>
*Gibt die Mainframe-Datei gemäß der Datensatzformatdefinition der RFML-Datei aus.<BR>
* {@code
rec.setField("PRODUCT-GR", null);}An dem Ort{@code
com.ibm.as400.access.ExtendedIllegalArgumentException: name (PRODUCT-GR): Field was not found.
}<BR>
*Ich bekomme eine Ausnahme. In der folgenden API-Dokumentation wird angegeben, dass Structure nicht unterstützt wird. Array wird ebenfalls nicht unterstützt.<BR>
* <a href=
* "https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzahh/javadoc/com/ibm/as400/data/RecordFormatDocument.html">
* https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzahh/javadoc/com/ibm/as400/data/RecordFormatDocument.html</a>
*/
@Test
public void test01MfFileOutput() {
//Suchen und lesen Sie die Datensatzformatdefinition im Klassenpfad.
RecordFormatDocument rfd = null;
try {
rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
} catch (XmlException e) {
throw new RuntimeException(e);
}
//Dateiausgabe mit Hauptrahmenzeichencode.
File ioFile = new File("./data/ORDER_FILE.dat");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(ioFile);
Record rec = rfd.toRecordFormat("ORDER01-REC").getNewRecord();
for (short i = 1; i < 11; i++) {
rec.setField("REC-NO", new Short(i));
rec.setField("ORDER-NO", "170423-123");
rec.setField("ZIP-CD", "103-0028");
rec.setField("ADRESS", "Yaesu, Chuo-ku, Tokio");
//↓ Hier tritt eine Ausnahme auf, also kommentieren Sie aus.
// rec.setField("PRODUCT-GR", null);
//Byte-Array und Ausgabe in Datei.
byte[] buf = rec.getContents();
StringUtil.dump("DEBUG:", buf, "");
fos.write(buf);
}
fos.flush();
} catch (XmlException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
*Ausgabe der Hauptbilddatei. <BR>
*Gibt die Mainframe-Datei gemäß der Datensatzformatdefinition der RFML-Datei aus.<BR>
* 1.Da sich das Gruppenelement und OCCURS nicht wie beabsichtigt verhalten, wird dieser Teil als Byte-Array betrachtet.<BR>
* 2.Definieren Sie den Gruppenelementteil in einer anderen Datensatzformatdefinition und legen Sie dort ein Java-Objekt fest, um ein Byte-Array mit MF-Zeichencode zu erstellen.<br>
*3. 3. Über 2 über 1.Einstellen.
*/
@Test
public void test02MfFileOutput() {
//Suchen und lesen Sie die Datensatzformatdefinition im Klassenpfad.
RecordFormatDocument rfd = null;
try {
rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
} catch (XmlException e) {
throw new RuntimeException(e);
}
//Dateiausgabe mit Hauptrahmenzeichencode.
File ioFile = new File("./data/ORDER_FILE.dat");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(ioFile);
Record rec = rfd.toRecordFormat("ORDER01-REC").getNewRecord();
Record grp = rfd.toRecordFormat("PRODUCT-GR").getNewRecord();
for (int i = 1; i < 11; i++) {
rec.setField("REC-NO", new Short((short) i));
rec.setField("ORDER-NO", "170423-123");
rec.setField("ZIP-CD", "103-0028");
rec.setField("ADRESS", "Yaesu, Chuo-ku, Tokio");
//Der Code für den OCCURS-Teil des Gruppenelements.
//Ein Bytestrom des gesamten Gruppenelements, an das das Element übertragen wird.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//Bytelänge des Ziels für die Elementübertragung ÷ 1 Bytelänge für OCCURS(PRODUCT-GR)= Anzahl der OCCC-URS
int occursCount = rec.getFieldAsBytes("PRODUCT-B").length / grp.getRecordLength();
//OCCURS Wiederholen Sie dies einige Minuten lang
for (int j = 0; j < occursCount; j++) {
grp.setField("PRODUCT-CD", "ABCDEFGHIJ-000" + j);
grp.setField("PRODUCT-AMT", new BigDecimal("123.45"));
grp.setField("UNIT-PRC", new BigDecimal("+12345.67"));
grp.setField("DISCOUNT-PRC", new BigDecimal("-45.6"));
baos.write(grp.getContents());
}
//In einem Byte-Array von Gruppenelementen festlegen.
rec.setField("PRODUCT-B", baos.toByteArray());
//Byte-Array und Ausgabe in Datei.
byte[] buf = rec.getContents();
StringUtil.dump("DEBUG:", buf, "");
fos.write(buf);
}
fos.flush();
} catch (XmlException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
*Eingabe der Hauptbilddatei. <BR>
*Geben Sie die Mainframe-Datei gemäß der Datensatzformatdefinition der RFML-Datei ein.<BR>
* 1.Da sich das Gruppenelement und OCCURS nicht wie beabsichtigt verhalten, wird dieser Teil als Byte-Array betrachtet.<BR>
* 2.Definieren Sie den Gruppenelementteil in einer anderen Datensatzformatdefinition, legen Sie dort das Byte-Array des MF-Zeichencodes fest und machen Sie es zu einem Java-Objekt.<br>
*/
@Test
public void test03MfFileInput() {
//Erstellen Sie eine Mainframe-Datei.
this.test02MfFileOutput();
//Suchen und lesen Sie die Datensatzformatdefinition im Klassenpfad.
RecordFormatDocument rfd = null;
try {
rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
} catch (XmlException e) {
throw new RuntimeException(e);
}
//Geben Sie eine Datei mit dem Zeichencode des Hauptrahmens ein.
File ioFile = new File("./data/ORDER_FILE.dat");
FileInputStream fis = null;
try {
Record rec = rfd.toRecordFormat("ORDER01-REC").getNewRecord();
Record grp = rfd.toRecordFormat("PRODUCT-GR").getNewRecord();
fis = new FileInputStream(ioFile);
//Ruft die Anzahl der Bytes für einen Datensatz ab und erstellt ein Byte-Array für den Lesepuffer.
byte[] recordBuf = new byte[rec.getRecordLength()];
//Die MF-Datei enthält keine Zeilenvorschubzeichen. Daher wird es für die Anzahl der Bytes eines Datensatzes in den Puffer eingelesen.
while (fis.read(recordBuf) != -1) {
//Aufzeichnung aus dem Byte-Array des Puffers.
rec.setContents(recordBuf);
System.out.print("[" + rec.getField("REC-NO"));
System.out.print("],[" + rec.getField("ORDER-NO"));
//Der Code für den OCCURS-Teil des Gruppenelements.
//Ein Bytestrom des gesamten Gruppenelements, von dem das Element erhalten wurde.
ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) rec.getField("PRODUCT-B"));
//Erstellen Sie einen Lesepuffer für 1 OCCURS.
byte[] groupBuf = new byte[grp.getRecordLength()];
while (bais.read(groupBuf) != -1) {
grp.setContents(groupBuf);
System.out.print("],[" + grp.getField("PRODUCT-CD"));
System.out.print("],[" + grp.getField("PRODUCT-AMT"));
System.out.print("],[" + grp.getField("UNIT-PRC"));
System.out.print("],[" + grp.getField("DISCOUNT-PRC"));
}
System.out.println("]");
}
} catch (XmlException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* COMP-Java-Objekt von 4(Integer)Test zum Konvertieren.
*/
@Test
public void test01() {
//Eingegebener Wert(MF-Byte-Daten)
//Sie müssen sich keine Gedanken über die Bytereihenfolge machen, da die Ender sowohl von IBM Mainframe als auch von Java große Ender sind.
byte[] mfData = new byte[] { 0x0A, 0x0B, 0x0C, 0x0D };
StringUtil.dump("test01:input :", mfData, "");
// COMP-Java-Objekt von 4(Integer)Konvertieren zu.
AS400Bin4 comp4 = new AS400Bin4();
int actual = ((Integer) comp4.toObject(mfData, 0)).intValue();
System.out.println("test01:actual :" + actual);
//Erwartete Wertschöpfung.
int expected = 168496141;
System.out.println("test01:expected:" + expected);
//0x0A0B0C0D ist die Dezimalzahl 164896141.
assertEquals(expected, actual);
}
/**
*Java-Objekt(Integer)Von COMP-Test um auf 4 zu konvertieren.
*/
@Test
public void test02() {
//Eingegebener Wert(Java-Objekt)
Integer javaObject = new Integer(168496141);
System.out.println("test02:input :" + javaObject);
//Java-Objekt(Integer)Von COMP-In 4 konvertieren.
AS400Bin4 comp4 = new AS400Bin4();
byte[] actual = comp4.toBytes(javaObject);
StringUtil.dump("test02:actual :", actual, "");
//Erwartete Wertschöpfung.
byte[] expected = new byte[] { 0x0A, 0x0B, 0x0C, 0x0D };
StringUtil.dump("test02:expected:", expected, "");
// test
assertArrayEquals(expected, actual);
}
/**
*PBC X-Format EBC DIC nach MS932(SJIS)Test zum Konvertieren. <BR>
*
* IBM Globalization - Coded character set identifiers.UR:<a href=
* "https://www-01.ibm.com/software/globalization/ccsid/ccsid_registered.html">https://www-01.ibm.com/software/globalization/ccsid/ccsid_registered.html</a><br>
*
* IBM Globalization - Coded character set identifiers - CCSID
* 5035。URL:<a href=
* "https://www-01.ibm.com/software/globalization/ccsid/ccsid5035.html">https://www-01.ibm.com/software/globalization/ccsid/ccsid5035.html</a><br>
*
*Alternative Unicode-Konvertierungstabelle für CCSID 5035.URL:<a href=
* "https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_9.5.0/com.ibm.db2.luw.admin.nls.doc/doc/c0022611.html">https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_9.5.0/com.ibm.db2.luw.admin.nls.doc/doc/c0022611.html</a><br>
*
* 79.CCSID 5035 zur Eingabe von Kleinbuchstaben.URL:<a href=
* "http://www.as400-net.com/tips/environment/79.html">http://www.as400-net.com/tips/environment/79.html</a><br>
*
* CCSID=930 「4370 UDC
*Ein super Set von 5026 japanischen Katakana Kanji mit Charakteren. Kana-Priorität halber Breite(Kleinbuchstaben halber Breite können nicht gemischt werden)。<BR>
* CCSID=939 「4370 UDC
*Japanische lateinische Zeichen einschließlich Zeichen Kanji, 5035 Super-Set. Priorität der unteren Buchstaben mit halber Breite(Kana-Zeichen mit halber Breite können nicht gemischt werden)。<BR>
*/
@Test
public void test03() {
//MF-Zeichencode, CCSID=930 「4370 UDC
//Ein super Set von 5026 japanischen Katakana Kanji mit Charakteren. Kana-Priorität halber Breite(Kleinbuchstaben halber Breite können nicht gemischt werden)Byte-Array.
// "123AαB"=0xF1F2F3C10E41410FC281。
//Halbe Breite Katakana"EIN"Ist CCSID=930 ist 0x81. Dies ist CCSID=Es ist 939 0x56.
//Zeichen in voller Breite"α"Ist der MF-Zeichencode 0X4141. Verschieben Sie dies heraus(0x0E)Und wechseln Sie hinein(0x0F)Deck, 0x0E41410F.
byte[] mfData = new byte[] { (byte) 0xF1, (byte) 0xF2, (byte) 0xF3, (byte) 0xC1, 0x0E, 0x41, 0x41, 0x0F,
(byte) 0xC2, (byte) 0x81 };
StringUtil.dump("test03:input :", mfData, "");
System.out.println("test03:Anzahl der Eingabebytes:" + mfData.length);
// CCSID=930 「4370 UDC
//Ein super Set von 5026 japanischen Katakana Kanji mit Charakteren. Kana-Priorität halber Breite(Kleinbuchstaben halber Breite können nicht gemischt werden)Byte-Array
//In Unicode konvertieren.
int ccsid = 930;
AS400Text xtype = new AS400Text(mfData.length, ccsid);
String unicodeString = (String) xtype.toObject(mfData);
System.out.println("test03:unicodeString Anzahl der Bytes:" + unicodeString.length());
StringUtil.dump("test03:unicodeString:", unicodeString.getBytes(), "");
//Unicode zu MS932(SJIS)Konvertieren zu.
String encoding = "MS932";
String actual = this.convertString(unicodeString, encoding);
System.out.println("test03:actual :" + actual);
//Verschieben(0x0E)Und wechseln Sie hinein(0x0F)Da es keine gibt, sind es 2 Bytes weniger.
System.out.println("test03:tatsächliche Anzahl von Bytes:" + this.getStringByteLength(actual, encoding));
StringUtil.dump("test03:actual :", this.getStringBytes(actual, encoding), "");
//Machen Sie den erwarteten Wert.
String expected = this.convertString("123AαB", encoding);
System.out.println("test03:expected:" + expected);
//Verschieben(0x0E)Und wechseln Sie hinein(0x0F)Da es keine gibt, sind es 2 Bytes weniger.
System.out.println("test03:erwartete Anzahl von Bytes:" + this.getStringByteLength(expected, encoding));
StringUtil.dump("test03:expected:", this.getStringBytes(expected, encoding), "");
// test
assertEquals(expected, actual);
}
/**
*Zeichencode-Konvertierung.
*
* @param from Die Quellzeichenfolge.
* @Parametercodierung Zeichencode nach der Konvertierung.
* @return Die konvertierte Zeichenfolge.
*/
String convertString(String from, String encoding) {
String res = null;
try {
res = new String(getStringBytes(from, encoding), encoding);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return res;
}
/**
*Konvertiert den Zeichencode und gibt ihn als Byte-Array zurück.
*
* @param from Die Quellzeichenfolge.
* @Parametercodierung Zeichencode nach der Konvertierung.
* @Byte-Array nach der Konvertierung zurückgeben.
*/
byte[] getStringBytes(String from, String encoding) {
byte[] res = null;
try {
res = from.getBytes(encoding);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return res;
}
/**
*Gibt die Anzahl der Bytes nach der Zeichencodekonvertierung zurück.
*
* @param from Die Quellzeichenfolge.
* @Parametercodierung Zeichencode nach der Konvertierung.
* @return Die Anzahl der Bytes nach der Zeichencodekonvertierung.
*/
int getStringByteLength(String from, String encoding) {
return getStringBytes(from, encoding).length;
}
/**
*Komplexer Datentypkonvertierungstest.
*/
@Test
public void test04() {
//Java-Verbundobjekt
Object[] javaObjects = {
new Integer(88),
new byte[] { 0x41 },
new BigDecimal("-12.34"),
"ABCDE"
};
//MF zusammengesetzte Datendefinition
AS400DataType[] mfDataType = {
new AS400Bin4(),
new AS400ByteArray(4),
new AS400PackedDecimal(4, 2),
new AS400Text(10)
};
//Erzeugt einen Konverter mit der durch das Argument angegebenen zusammengesetzten MF-Datendefinition.
AS400Structure converter = new AS400Structure(mfDataType);
//Erzeugt ein Byte-Array mit MF-Zeichencode-Konvertierung aus einem zusammengesetzten Java-Objekt.
byte[] outAS400 = converter.toBytes(javaObjects);
StringUtil.dump("test04:", outAS400, "");
Object[] outJavaObjects = (Object[]) converter.toObject(outAS400, 0);
System.out.println("[" + outJavaObjects[0] + "]");
StringUtil.dump("[", (byte[]) outJavaObjects[1], "]"); //Wenn 0x41 auf der Empfangsseite für 4 Bytes eingestellt ist, wird es linksbündig gesetzt. Füllen Sie den Rest mit 0x00.
System.out.println("[" + outJavaObjects[2] + "]");
System.out.println("[" + outJavaObjects[3] + "]"); //Wenn Sie auf der Empfangsseite 5 ABCDE-Zeichen für 10 Byte festlegen, wird dies mit der linken Klaue festgelegt. Der Rest ist Raum.
// test
assertEquals(88, outJavaObjects[0]);
assertArrayEquals(new byte[] { 0x41, 0x00, 0x00, 0x00 }, (byte[]) outJavaObjects[1]);
assertEquals(new BigDecimal("-12.34"), outJavaObjects[2]);
assertEquals("ABCDE ", outJavaObjects[3]);
}
/**
*Ein Test, der ein Definitionsobjekt für das MF-Datensatzformat erstellt und dessen Werte entsprechend festlegt.
*/
@Test
public void test05() {
//Artikeldefinition
BinaryFieldDescription bfd = new BinaryFieldDescription(new AS400Bin4(), "REC-NO");
CharacterFieldDescription cfd1 = new CharacterFieldDescription(new AS400Text(10), "ORDER-NO");
CharacterFieldDescription cfd2 = new CharacterFieldDescription(new AS400Text(20), "ORDER-NOTE");
//Datensatzformatdefinition
RecordFormat rf = new RecordFormat();
rf.addFieldDescription(bfd);
rf.addFieldDescription(cfd1);
rf.addFieldDescription(cfd2);
//Generieren Sie einen Datensatz und legen Sie den Wert des Java-Objekts fest.
Record rec = rf.getNewRecord();
rec.setField("REC-NO", new Integer(1));
rec.setField("ORDER-NO", "170415-123");
rec.setField("ORDER-NOTE", "HELLO WORLD");
//Holen Sie sich MF-Byte-Array.
byte[] actual = null;
try {
actual = rec.getContents();
} catch (CharConversionException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//Erwarteter Wert.
byte[] expected = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xF1, (byte) 0xF7,
(byte) 0xF0, (byte) 0xF4, (byte) 0xF1, (byte) 0xF5, (byte) 0x60, (byte) 0xF1, (byte) 0xF2, (byte) 0xF3,
(byte) 0xC8, (byte) 0xC5, (byte) 0xD3, (byte) 0xD3, (byte) 0xD6, (byte) 0x40, (byte) 0xE6, (byte) 0xD6,
(byte) 0xD9, (byte) 0xD3, (byte) 0xC4, (byte) 0x40, (byte) 0x40, (byte) 0x40, (byte) 0x40, (byte) 0x40,
(byte) 0x40, (byte) 0x40, (byte) 0x40, (byte) 0x40 };
StringUtil.dump("test05:actual :", actual, "");
StringUtil.dump("test05:expected:", expected, "");
// test
assertArrayEquals(expected, actual);
}
/**
*Generieren Sie das Definitionsobjekt für das MF-Datensatzformat und den Eingabe- / Ausgabetest der EBCIDIC-Binärdatei entsprechend.
*/
@Test
public void test06() {
RecordFormat rf = this.createOrderRecordFormat();
Record rec = rf.getNewRecord();
File ioFile = new File("./data/AS400.dat");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(ioFile);
//10 Datensatzgenerierung
for (int i = 1; i < 11; i++) {
rec.setField("REC-NO", new Integer(i));
rec.setField("AMOUNT", new BigDecimal("-12.34"));
rec.setField("ORDER-NO", "170415-123");
rec.setField("ORDER-NOTE", "HELLOαWORLD");
//OutputStream kann als Argument von getContents angegeben werden.
//Idiomly os.write(rec.getContents())Ich benutze es oft, also werde ich damit weitermachen.
fos.write(rec.getContents());
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (CharConversionException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
FileInputStream fis = null;
try {
fis = new FileInputStream(ioFile);
rec = rf.getNewRecord();
//Ermitteln Sie die Anzahl der Bytes für einen Datensatz und generieren Sie ein Byte-Array.
int len = rec.getRecordLength();
byte[] buffer = new byte[len];
//Die MF-Datei enthält keine Zeilenvorschubzeichen. Daher wird die Anzahl der Bytes eines Datensatzes in den Puffer eingelesen.
while (fis.read(buffer) != -1) {
rec.setContents(buffer);
StringUtil.dump("test06:", buffer, "");
System.out.print(rec.getField("REC-NO"));
System.out.print("," + rec.getField("ORDER-NO"));
System.out.print("," + rec.getField("AMOUNT"));
System.out.println("," + rec.getField("ORDER-NOTE"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
*Generieren Sie ein Definitionsobjekt für das MF-Datensatzformat aus der Definitionsdatei für das MF-Datensatzformat und testen Sie die Ausgabe der EBCDIC-Binärdatei entsprechend..
*
* @löst eine XmlException Record-Formatausnahme aus
* @löst eine IOException File IO Exception aus
*/
@Test
public void test07() throws XmlException, IOException {
//Generieren Sie die Definition des MF-Datensatzformats.
RecordFormat rf = this.createOrderRecordFormat();
//Speichern Sie die Definition des MF-Datensatzformats im Klassenpfad.
this.saveRecordFormat(rf, new File("src/test/java/jp/golden/cat/util/ORDER.rfml"));
//Suchen und lesen Sie die Definition des MF-Datensatzformats im Klassenpfad.
RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.ORDER.rfml");
//Schreiben Sie in EBCDIC.
File ioFile = new File("./data/AS400_2.dat");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(ioFile);
//10 Datensatzgenerierung
for (int i = 1; i < 11; i++) {
//Ich habe die Angewohnheit, Gegenstände anzugeben. "Name der Datensatzformatdefinition.Geben Sie den Artikel unter "Artikelname" an.
rfd.setValue("ORDER-REC.REC-NO", new Integer(i));
rfd.setValue("ORDER-REC.AMOUNT", new BigDecimal("-12.34"));
rfd.setValue("ORDER-REC.ORDER-NO", "170415-123");
rfd.setValue("ORDER-REC.ORDER-NOTE", "HELLOαWORLD");
fos.write(rfd.toByteArray("ORDER-REC"));
}
fos.flush();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
*Generieren Sie ein Definitionsobjekt für das MF-Datensatzformat aus der Definitionsdatei für das MF-Datensatzformat und testen Sie die Eingabe der EBCDIC-Binärdatei entsprechend..
*
* @löst eine XmlException Record-Formatausnahme aus
* @löst eine IOException File IO Exception aus
*/
@Test
public void test08() throws XmlException, IOException {
//Suchen und lesen Sie die Definition des MF-Datensatzformats im Klassenpfad.
RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.ORDER.rfml");
//Lesen Sie die EBCDIC-Datei.
File ioFile = new File("./data/AS400_2.dat");
FileInputStream fis = null;
try {
fis = new FileInputStream(ioFile);
// rfd.toRecord("ORDER-REC").getRecordLength()Löst die folgende Ausnahme aus.
// com.ibm.as400.data.PcmlException: Value is not set. Processing
// <data> element 'ORDER-REC.REC-NO'.
//Wahrscheinlich kann die Länge nicht abgerufen werden, da das Record-Objekt nicht im RecordFormatDocument-Objekt erstellt wurde.
//Daher getNewRecord()Erstellen Sie ein Objekt mit und erhalten Sie dann die Länge.
// int len = rfd.toRecord("ORDER-REC").getRecordLength();
//Ermitteln Sie die Anzahl der Bytes für einen Datensatz und generieren Sie ein Byte-Array.
int len = rfd.toRecordFormat("ORDER-REC").getNewRecord().getRecordLength();
byte[] buffer = new byte[len];
//Die MF-Datei enthält keine Zeilenvorschubzeichen. Daher wird die Anzahl der Bytes eines Datensatzes in den Puffer eingelesen.
while (fis.read(buffer) != -1) {
rfd.setValues("ORDER-REC", buffer);
StringUtil.dump("test08:", rfd.toByteArray("ORDER-REC"), "");
System.out.print("[" + rfd.getValue("ORDER-REC.REC-NO"));
System.out.print("],[" + rfd.getValue("ORDER-REC.ORDER-NO"));
System.out.print("],[" + rfd.getValue("ORDER-REC.AMOUNT"));
System.out.print("],[" + rfd.getValue("ORDER-REC.ORDER-NOTE"));
System.out.println("]");
Record rec = rfd.toRecord("ORDER-REC");
System.out.print("[" + rec.getField("REC-NO"));
System.out.print("],[" + rec.getField("ORDER-NO"));
System.out.print("],[" + rec.getField("AMOUNT"));
//Der folgende Code ist beide ORDER-Dies ist eine Methode zum Abrufen von HINWEIS, das Ergebnis ist jedoch unterschiedlich.
// (1) rfd.getValue("ORDER-REC.ORDER-NOTE")
// (2) rec.getField("ORDER-NOTE")
// (1)Der nachfolgende Leerzeichen des Strings wird ohne Erlaubnis gelöscht.(2)Bleibt intakt, wenn ein Leerzeichen vorhanden ist.
// (1)Intern PcmlDataValues.toObject()Scheint anzurufen. Unter ihnen trimString.
/*
* //For Strings, trim blanks and nulls appropriately if
* (dataType == PcmlData.CHAR) { newVal = trimString((String)
* newVal, getTrim()); }
*/
// getValue()Tut egoistische Dinge, also getField()Es ist besser, die Methode zu verwenden.
System.out.print("],[" + rec.getField("ORDER-NOTE"));
System.out.println("]");
}
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
*Kann die Struktur OCCURS eine Datensatzformatdefinition sein? => Ich kann nicht.
*
* @löst eine XmlException Record-Formatausnahme aus
* @löst eine IOException File IO Exception aus
*/
@Test
public void test09() throws XmlException, IOException {
//AS400-Datentypdefinition
AS400DataType[] as400Types = new AS400DataType[] {
new AS400Text(10),
new AS400PackedDecimal(4, 2),
};
AS400Structure as400Structure = new AS400Structure(as400Types);
AS400Array as400Array = new AS400Array(as400Structure, 3);
//Java-Objekt => AS400-Datenbyte-Array
Object[] inJavaObject = new Object[as400Array.getNumberOfElements()];
System.out.println("test09:AS400Array elements:" + as400Array.getNumberOfElements());
for (int i = 0; i < inJavaObject.length; i++) {
inJavaObject[i] = new Object[] {
new String("170415-123"),
new BigDecimal("-12.34"),
};
}
byte[] as400bytes = as400Array.toBytes(inJavaObject);
StringUtil.dump("test09:", as400bytes, "");
//AS400-Datentyp(Structure+Array)Können Datensatzformatdefinitionen in XML gespeichert werden? => Ich kann nicht.
ArrayFieldDescription afd = new ArrayFieldDescription(as400Array, "AMOUNTS");
RecordFormat rf = new RecordFormat("TEST09-REC");
rf.addFieldDescription(afd);
File rfml = new File("src/test/java/jp/golden/cat/util/TEST09.rfml");
FileOutputStream fos = null;
try {
//In RecordFormat kann AS400Structure mit der folgenden Ausnahme nicht als RFML-Datei gespeichert werden:
// com.ibm.as400.data.XmlException: Data type AS400Structure is not
// supported by RFML.
//In der API-Dokumentation wurde auch angegeben, dass dies nicht unterstützt wurde. Ich möchte auch das mehrdimensionale AS400Array sehen.
// https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzahh/javadoc/com/ibm/as400/data/RecordFormatDocument.html
thrown.expect(com.ibm.as400.data.XmlException.class);
thrown.expectMessage("Data type AS400Structure is not supported by RFML.");
RecordFormatDocument rfd = new RecordFormatDocument(rf);
fos = new FileOutputStream(rfml);
rfd.toXml(fos);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
* AS400Array+AS400Structure kann nicht in eine RFML-Datei umgewandelt werden. Behalten Sie es also bei, bis die Anzahl der Bytes gezählt ist, und speichern Sie es in der RFML-Datei.
*
*/
@Test
public void test10() {
//AS400-Datentypdefinition
AS400DataType[] types = new AS400DataType[] {
new AS400Text(10),
new AS400PackedDecimal(4, 2),
};
AS400Structure a400Structure = new AS400Structure(types);
AS400Array as400Array = new AS400Array(a400Structure, 3);
System.out.println("test10:AS400Structure byte length:" + a400Structure.getByteLength());
System.out.println("test10:AS400Arrat byte length:" + as400Array.getByteLength());
// AS400Array+Erstellen Sie eine Definition von AS400ByteArray für die Anzahl der Bytes von AS400Structure.
AS400ByteArray as400ByteArray = new AS400ByteArray(as400Array.getByteLength());
//Erstellen Sie eine Datensatzformatdefinition.
BinaryFieldDescription bfd = new BinaryFieldDescription(new AS400Bin4(), "REC-NO");
CharacterFieldDescription cfd1 = new CharacterFieldDescription(new AS400Text(10), "ORDER-NO");
HexFieldDescription hfd = new HexFieldDescription(as400ByteArray, "AMOUNTS"); // AS400Array+AS400ByteArray für die Anzahl der Bytes von AS400Structure
CharacterFieldDescription cfd2 = new CharacterFieldDescription(new AS400Text(20), "ORDER-NOTE");
RecordFormat rf = new RecordFormat("ORDER3-REC");
rf.addFieldDescription(bfd);
rf.addFieldDescription(cfd1);
rf.addFieldDescription(hfd);
rf.addFieldDescription(cfd2);
//In RFML-Datei speichern.
File rfml = new File("src/test/java/jp/golden/cat/util/ORDER3.rfml");
this.saveRecordFormat(rf, rfml);
}
/**
* AS400Array+Da AS400Structure nicht in eine RFML-Datei umgewandelt werden kann, wird der Datensatz als RFML-Datei ausgegeben, die diesen Teil in einem Byte-Array ausdrückt..
*
* @löst eine XmlException Record-Formatausnahme aus
* @löst eine IOException File IO Exception aus
*/
@Test
public void test11() throws XmlException, IOException {
//AS400-Datentypdefinition
AS400DataType[] types = new AS400DataType[] {
new AS400Text(10),
new AS400PackedDecimal(4, 2),
};
AS400Structure as400structure = new AS400Structure(types);
AS400Array as400array = new AS400Array(as400structure, 3);
//Generieren Sie ein Datensatzobjekt aus einer RFML-Datei.
RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.ORDER3.rfml");
Record rec = rfd.toRecordFormat("ORDER3-REC").getNewRecord();
//MF-Dateiausgabe
File ioFile = new File("./data/AS4003.dat");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(ioFile);
//10 Datensatzgenerierung
for (int i = 1; i < 11; i++) {
rec.setField("REC-NO", new Integer(i));
rec.setField("ORDER-NO", "170415-123");
// AS400Array+Erstellen Sie ein Byte-Array für den AS400-Strukturteil
//Erstellen Sie zunächst ein Java-Objekt, das festgelegt werden soll
Object[] inJavaObject = new Object[as400array.getNumberOfElements()];
for (int j = 0; j < inJavaObject.length; j++) {
inJavaObject[j] = new Object[] {
new String("170415-AA" + j),
new BigDecimal("-12.34"),
};
}
//Bild des Erstellens eines Byte-Arrays aus einem zweidimensionalen Java-Objekt
byte[] as400bytes = as400array.toBytes(inJavaObject);
System.out.println("test11:" + as400bytes.length);
//Legen Sie das Byte-Array fest
rec.setField("AMOUNTS", as400bytes);
rec.setField("ORDER-NOTE", "HELLOαWORLD");
fos.write(rec.getContents());
}
fos.flush();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
* AS400Array+AS400Structure kann nicht in eine RFML-Datei konvertiert werden. Betrachten Sie AS400Structure daher als einen Datensatz, konvertieren Sie ihn in eine RFML-Datei und lesen Sie ihn.
*
* @löst eine XmlException Record-Formatausnahme aus
* @löst eine IOException File IO Exception aus
*/
@Test
public void test12() throws IOException, XmlException {
//Generieren Sie ein Datensatzobjekt aus einer RFML-Datei.
RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.ORDER4.rfml");
Record rec1 = rfd.toRecordFormat("ORDER4-REC").getNewRecord();
//Datensatzdefinition für 1 OCCURS. Ich möchte wirklich AS400 Structure verwenden, aber es wird nicht unterstützt.
Record rec2 = rfd.toRecordFormat("AMOUNTS").getNewRecord();
//MF-Dateieingabe
File ioFile = new File("./data/AS4003.dat");
FileInputStream fis = null;
try {
fis = new FileInputStream(ioFile);
//Ermitteln Sie die Anzahl der Bytes für einen Datensatz und generieren Sie ein Byte-Array.
int len = rec1.getRecordLength();
byte[] buffer = new byte[len];
//Die MF-Datei enthält keine Zeilenvorschubzeichen. Daher wird die Anzahl der Bytes eines Datensatzes in den Puffer eingelesen.
while (fis.read(buffer) != -1) {
rec1.setContents(buffer);
System.out.print("[" + rec1.getField("REC-NO"));
System.out.print("],[" + rec1.getField("ORDER-NO"));
//Holen Sie sich das Byte-Array für die gesamten OCCURS
byte[] amounts = (byte[]) rec1.getField("AMOUNTS");
//Bytelänge des gesamten OCCURS ÷ 1 Bytelänge für OCCURS = Anzahl der OCCCURS
int occursCount = amounts.length / rec2.getRecordLength();
//OCCURS Wiederholen Sie dies einige Minuten lang
for (int i = 0; i < occursCount; i++) {
//Crop 1 OCCURS aus dem Mengenbyte-Array.
rec2.setContents(amounts, i * rec2.getRecordLength());
//1 BESTELLUNG, aus der OCCURS besteht-Standardausgabe von CNO und AMOUNT
System.out.print("],[" + rec2.getField("ORDER-CNO"));
System.out.print("],[" + rec2.getField("AMOUNT"));
}
System.out.print("],[" + rec1.getField("ORDER-NOTE"));
System.out.println("]");
}
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
*Verhaltenstest von AS400Array.
*
*Die Aufteilung von AS400Array umfasst insgesamt 30 Byte Datenstruktur vom Typ X, 10 Byte x 3 OCCURS.
*Speichern Sie dies in einer RFML-Datei. In XML zählen="3"Wird voraussichtlich mit ausgegeben. Bisher hat es funktioniert.
*Wenn ich jedoch die RFML-Datei lese, ein Record-Objekt erstelle und die Länge erhalte, beträgt sie 10 Byte. OCCURS wird nicht reproduziert.
*
*Fazit:Es ist möglich, count in die RFML-Datei zu schreiben, verwenden Sie jedoch nicht count in der RFML-Datei, da diese beim Lesen verloren geht.
*
* @löst eine XmlException Record-Formatausnahme aus
* @löst eine IOException File IO Exception aus
*/
@Test
public void test13() throws IOException, XmlException {
//Artikeldefinition
AS400Array as400Array = new AS400Array(new AS400Text(10), 3);
ArrayFieldDescription afd = new ArrayFieldDescription(as400Array, "ORDER-NOTE");
//Speichern Sie die Datensatzformatdefinition als Datei.
RecordFormat rf = new RecordFormat("TEST13-REC");
rf.addFieldDescription(afd);
//Erwarteter Wert:10*3=30byte.
int expected = rf.getNewRecord().getRecordLength();
// count="3"Es wird in gespeichert.
this.saveRecordFormat(rf, new File("src/test/java/jp/golden/cat/util/TEST13.rfml"));
//Generieren Sie ein Datensatzobjekt aus einer RFML-Datei.
RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.TEST13.rfml");
// 10*3=Ich erwarte 30 Bytes, aber aus irgendeinem Grund werden 10 zurückgegeben. count wird ignoriert.
int actual = rfd.toRecordFormat("TEST13-REC").getNewRecord().getRecordLength();
//Wenn ich versuche, es wie später zu speichern, verschwindet die Zählung und es wird gespeichert.
this.saveRecordFormat(rfd.toRecordFormat("TEST13-REC"),
new File("src/test/java/jp/golden/cat/util/TEST13_after.rfml"));
System.out.println("test13:actual:" + actual);
System.out.println("test13:expected:" + expected);
// assertEquals(expected, actual);
assertEquals(10, actual);
}
/**
*Erstellen Sie eine Definition des Auftragsdatensatzformats.
*
* @return Definition des Auftragsdatensatzformats erstellen.
*/
RecordFormat createOrderRecordFormat() {
//Artikeldefinition
BinaryFieldDescription bfd = new BinaryFieldDescription(new AS400Bin4(), "REC-NO");
CharacterFieldDescription cfd1 = new CharacterFieldDescription(new AS400Text(10), "ORDER-NO");
PackedDecimalFieldDescription pfd = new PackedDecimalFieldDescription(new AS400PackedDecimal(4, 2), "AMOUNT");
CharacterFieldDescription cfd2 = new CharacterFieldDescription(new AS400Text(20), "ORDER-NOTE");
//Datensatzformatdefinition
RecordFormat rf = new RecordFormat("ORDER-REC");
rf.addFieldDescription(bfd);
rf.addFieldDescription(cfd1);
rf.addFieldDescription(pfd);
rf.addFieldDescription(cfd2);
return rf;
}
/**
*Ruft die Definition des MF-Datensatzformats aus dem Klassenpfad ab.
*
* @param rfmlClassPath。
* @Rückgabe der MF-Datensatzformatdefinition.
*/
RecordFormatDocument loadRecordFormatDocument(String rfmlClassPath) {
RecordFormatDocument rfd = null;
try {
rfd = new RecordFormatDocument(rfmlClassPath);
} catch (XmlException e) {
throw new RuntimeException(e);
}
return rfd;
}
/**
*Speichern Sie die Definition des MF-Datensatzformats als Datei.
*
* @param rf MF-Datensatzdefinitionsformat.
* @param rfml
*Dateipfad für die Definition des MF-Datensatzformats. Beachten Sie, dass die Definitionsdatei später nicht gelesen werden kann, wenn der Klassenpfad keine Definitionsdatei enthält.
*/
void saveRecordFormat(RecordFormat rf, File rfml) {
FileOutputStream fos = null;
try {
RecordFormatDocument rfd = new RecordFormatDocument(rf);
fos = new FileOutputStream(rfml);
rfd.toXml(fos);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (XmlException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
*Endian Bestätigung.
*
*Native Bytereihenfolge:LITTLE_ENDIAN<br>
*Ursprünglicher Wert:0A0B0C0D12345678<br>
* LITTLE_ENDIAN:0D0C0B0A BIG_ENDIAN:0A0B0C0D<br>
* LITTLE_ENDIAN:78563412 BIG_ENDIAN:12345678<br>
*/
@Test
public void testEndian() {
System.out.println("testEndian:");
//Standardausgabe der nativen Bytereihenfolge.
//In der internen Verarbeitung von Java ist es ein Big Endian, aber da die Intel-CPU ein kleiner Engel ist, wenn Sie die folgende Methode auf der Java-VM der Intel-CPU ausführen,
//"Native Bytereihenfolge:LITTLE_"ENDIAN" wird angezeigt.
System.out.println("Native Bytereihenfolge:" + ByteOrder.nativeOrder());
byte[] mfData = new byte[] { 0xA, 0xB, 0xC, 0xD, 0x12, 0x34, 0x56, 0x78 };
StringUtil.dump("Ursprünglicher Wert:", mfData, "");
ByteArrayInputStream bis = null;
try {
bis = new ByteArrayInputStream(mfData);
byte[] buffer = new byte[4];
int len = -1;
while ((len = bis.read(buffer)) != -1) {
if (len != buffer.length) {
throw new IOException("Überprüfen Sie die Beziehung zwischen der Länge des Lesepuffers und dem Eingabewert.");
}
//Mit wenig Tolandian konvertiert.
ByteBuffer byteBuff = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN);
int i = byteBuff.getInt();
System.out.print(ByteOrder.LITTLE_ENDIAN);
System.out.print(":" + StringUtil.toHexString(BigInteger.valueOf(i).toByteArray()));
System.out.print("\t");
//Mit Big Endian konvertiert.
byteBuff = ByteBuffer.wrap(buffer).order(ByteOrder.BIG_ENDIAN);
i = byteBuff.getInt();
System.out.print(ByteOrder.BIG_ENDIAN);
System.out.print(":" + StringUtil.toHexString(BigInteger.valueOf(i).toByteArray()));
System.out.println();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
;
}
}
}
}
}
Recommended Posts