Comment entrer / sortir des fichiers mainframe IBM en Java?

Comment entrer / sortir des fichiers mainframe IBM en Java?

Obtenir les fichiers mainframe IBM dans et hors de Java peut être un peu compliqué:

Donc, quand je pensais créer la mienne, j'ai trouvé une classe utilitaire très pratique fournie en open source, donc je vais vous présenter comment l'utiliser. ** * Bien que cela soit pratique, il y a peu d'informations en japonais. Il est un gaspillage. ** </ font>

IBM Toolbox for Java D'après le nom, cela ressemble au cadre principal.

Installation et configuration

  • Téléchargez le fichier ZIP contenant la version OSS du fichier jar (par exemple, jtopen_9_3.zip) à partir de la page de téléchargement ci-dessous.
  • Décompressez le fichier "jtopen_9_3.zip", sortez le fichier jar "lib \ java8 \ jt400.jar" et placez-le dans le chemin de classe.

Sources d'informations sur la programmation, etc.

Définition des exigences pour l'entrée / la sortie de fichiers mainframe IBM en Java

Avant de présenter l'outil, je vais vous expliquer brièvement ce que vous attendez de cet outil, c'est-à-dire définir les exigences et expliquer comment utiliser l'outil en fonction de ces exigences.

  1. Je souhaite définir la définition du format d'enregistrement utilisée pour l'entrée / la sortie de fichiers dans le mainframe IBM en dehors du programme Java, et délimiter les enregistrements et les éléments en fonction de la définition.
  2. Je souhaite également effectuer une conversion de code de caractère.
  3. Je veux traiter les nombres décimaux dits binaires des nombres décimaux signés du pack et des nombres décimaux du pack non signés comme Big Decimal.

Exemple: fichier mainframe IBM d'entrée / sortie en Java

Il est supposé que le formateur d'enregistrements de fichier mainframe IBM suivant est une entrée / sortie en Java.

niveau Nom de l'élément de données Moule Nombre de chiffres précision Répétitif Travail à temps partiel Remarques
01 ORDER-REC 124 Enregistrement de la commande
03 REC-NO B 4 2 Numéro d'enregistrement
03 ORDER-NO C 10 10 Numéro de commande
03 ZIP-CD C 8 8 Code postal
03 ADDRESS C 20 20 adresse de rue(18 octets pour le code IBM Kanji, 20 octets pour le code de décalage)
03 PRODUCT-GR S 3 84 Élément du groupe de produits(OCCCURS 3 fois)
05 PRODUCT-CD C 15 15 Code produit
05 PRODUCT-AMT Z 5 2 5 Poids du produit(Nombre décimal de zone)
05 UNIT-PRC P 7 2 4 Prix unitaire(Décimal emballé)
05 DISCOUNT-PRC P 7 2 4 Montant de la remise(Décimal emballé)

Légende de type:

Moule La description
B Type binaire. Si vous écrivez le "numéro d'enregistrement" ci-dessus en COBOL, "S9"(4) COMP-Quatre ". Puisqu'il s'agit de 4 chiffres en binaire, le nombre d'octets est de 2 octets.
C Type de caractère. Si vous écrivez le "numéro de commande" ci-dessus en COBOL, "X"(10)」。
S Élément de groupe. Il regroupe plusieurs éléments de données.
P Pack de type décimal. Si vous écrivez le "prix unitaire" ci-dessus en COBOL, "S9"(7)V9(2) COMP-3」。
Z Type décimal de zone. Lorsque le "poids du produit" ci-dessus est écrit en COBOL, "9(5)V9(2)」。

Pour des explications sur les nombres décimaux de zone (également appelés nombres décimaux externes et nombres décimaux décimaux) et les nombres décimaux condensés (nombres décimaux internes), reportez-vous aux URL suivantes. 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

Créez un fichier de définition de format d'enregistrement (fichier RFML) et placez-le sur le chemin de classe.

Créez un fichier de définition de format d'enregistrement pour le fichier mainframe et activez l'entrée et la sortie du fichier en conséquence. Avec IBM ToolBox for Java, vous pouvez entrer et sortir des fichiers basés sur des fichiers RFML au format XML en tant que fichiers de définition de format d'enregistrement. Tout d'abord, créez-le et placez-le sur le chemin des classes. Il s'agit d'obtenir ce fichier de définition à partir du chemin de classe ultérieurement à partir du programme Java.

Vous pouvez trouver la DTD de ce fichier XML dans Programming IBM Toolbox for Java. Remarquez où il est dit "ccs id =" 930 "". Il est écrit au niveau racine et à "ADRESS". Cela spécifie le code de caractère du cadre principal, mais si vous souhaitez spécifier le code de caractère entier, écrivez-le à ce niveau racine. S'il est spécifié individuellement, il peut être spécifié pour chaque élément de données.

ORDER-FILE.rfml(Fichier de définition de format d'enregistrement mainframe)


<?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>

Sortie du fichier d'image principale partie 1 (exemple d'échec)

Voici un exemple d'échec. La structure et le tableau ne sont pas pris en charge. En d'autres termes, les éléments de groupe et OCCURS ne peuvent pas être utilisés. Que faire?

Sortie du fichier d'image principale, partie 1(Exemple d'échec)


    /**
     *Sortie du fichier d'image principale. <BR>
     *Produit le fichier mainframe selon la définition du format d'enregistrement du fichier RFML.<BR>
     * {@code
      rec.setField("PRODUCT-GR", null);}À l'endroit{@code
    com.ibm.as400.access.ExtendedIllegalArgumentException: name (PRODUCT-GR): Field was not found.
    }<BR>
     *Je reçois une exception. La documentation API suivante indique que Structure n'est pas prise en charge. Array n'est pas non plus pris en charge.<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() {
        //Recherchez et lisez la définition du format d'enregistrement à partir du chemin de classe.
        RecordFormatDocument rfd = null;
        try {
            rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
        } catch (XmlException e) {
            throw new RuntimeException(e);
        }

        //Sortie de fichier avec code de caractère du cadre principal.
        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, Tokyo");
                //↓ Une exception se produit ici, alors commentez.
                // rec.setField("PRODUCT-GR", null);
                //Tableau d'octets et sortie dans un fichier.
                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);
                }
            }
        }
    }

Sortie du fichier d'image principale, partie 2 (exemple de réussite)

Les éléments de groupe et OCCURS ne peuvent pas être utilisés, donc procédez comme suit.

  1. Les éléments de groupe et OCCURS ne se comportent pas comme prévu, considérez donc cette partie comme un tableau d'octets unique.
  2. Définissez la partie d'élément de groupe dans une autre définition de format d'enregistrement et définissez-y un objet Java pour créer un tableau d'octets de code de caractère MF.
    1. Réglez le 2 ci-dessus sur le 1 ci-dessus.

ORDER-FILE.rfml(Fichier de définition de format d'enregistrement mainframe. La partie d'élément de groupe a une définition d'enregistrement différente.)


<?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>

Sortie du fichier d'image principale, partie 2(Succès)


    /**
     *Sortie du fichier d'image principale. <BR>
     *Produit le fichier mainframe selon la définition du format d'enregistrement du fichier RFML.<BR>
     * 1.Étant donné que l'élément de groupe et OCCURS ne se comportent pas comme prévu, cette partie est considérée comme un tableau d'octets.<BR>
     * 2.Définissez la partie d'élément de groupe dans une autre définition de format d'enregistrement et définissez-y un objet Java pour créer un tableau d'octets de code de caractère MF.<br>
     *3. 3. Au-dessus de 2 au-dessus de 1.Mis à.
     */
    @Test
    public void test02MfFileOutput() {
        //Recherchez et lisez la définition du format d'enregistrement à partir du chemin de classe.
        RecordFormatDocument rfd = null;
        try {
            rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
        } catch (XmlException e) {
            throw new RuntimeException(e);
        }

        //Sortie de fichier avec code de caractère du cadre principal.
        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, Tokyo");

                //Le code de la partie OCCURS de l'élément de groupe.
                //Un flux d'octets de l'élément de groupe entier vers lequel l'élément est transféré.
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                //Longueur d'octet de la destination de transfert d'article ÷ 1 longueur d'octet pour OCCURS(PRODUCT-GR)= Nombre d'URS OCCC
                int occursCount = rec.getFieldAsBytes("PRODUCT-B").length / grp.getRecordLength();
                //OCCURS Répétez pendant quelques minutes
                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());
                }
                //Défini dans un tableau d'octets d'éléments de groupe.
                rec.setField("PRODUCT-B", baos.toByteArray());

                //Tableau d'octets et sortie dans un fichier.
                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);
                }
            }
        }
    }

Entrée du fichier d'image principale

Les éléments de groupe et OCCURS ne peuvent pas être utilisés, utilisez donc l'image affichée dans le fichier de sortie ci-dessus.

Entrée du fichier d'image principale


    /**
     *Entrée du fichier d'image principale. <BR>
     *Entrez le fichier mainframe en fonction de la définition du format d'enregistrement du fichier RFML.<BR>
     * 1.Étant donné que l'élément de groupe et OCCURS ne se comportent pas comme prévu, cette partie est considérée comme un tableau d'octets.<BR>
     * 2.Définissez la partie d'élément de groupe dans une autre définition de format d'enregistrement, définissez le tableau d'octets du code de caractère MF et faites-en un objet Java.<br>
     */
    @Test
    public void test03MfFileInput() {
        //Créez un fichier mainframe.
        this.test02MfFileOutput();

        //Recherchez et lisez la définition du format d'enregistrement à partir du chemin de classe.
        RecordFormatDocument rfd = null;
        try {
            rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
        } catch (XmlException e) {
            throw new RuntimeException(e);
        }

        //Entrez un fichier avec le code de caractère du cadre principal.
        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);
            //Obtient le nombre d'octets pour un enregistrement et crée un tableau d'octets pour le tampon de lecture.
            byte[] recordBuf = new byte[rec.getRecordLength()];
            //Il n'y a aucun caractère de saut de ligne dans le fichier MF. Par conséquent, il est lu dans la mémoire tampon pour le nombre d'octets d'un enregistrement.
            while (fis.read(recordBuf) != -1) {
                //Enregistrez à partir du tableau d'octets du tampon.
                rec.setContents(recordBuf);

                System.out.print("[" + rec.getField("REC-NO"));
                System.out.print("],[" + rec.getField("ORDER-NO"));

                //Le code de la partie OCCURS de l'élément de groupe.
                //Un flux d'octets de l'élément de groupe entier à partir duquel l'élément a été obtenu.
                ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) rec.getField("PRODUCT-B"));
                //Créez un tampon de lecture pour 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();
                }
            }
        }
    }

2017/04/19 (mercredi): Nouvelles découvertes:

rfd.toRecord ("ORDER-REC"). getRecordLength () lève l'exception suivante: 「com.ibm.as400.data.PcmlException: Value is not set. Processing element 'ORDER-REC.REC-NO'.」 Vous ne pouvez probablement pas obtenir la longueur car l'objet Record n'a pas été créé à l'intérieur de l'objet RecordFormatDocument. Je modifie l'exemple de code pour créer un objet avec getNewRecord (), puis obtenir la longueur.

2017/04/19 (mercredi): Correction de bogue:

Vous n'avez pas défini le tampon dans l'objet RecordFormatDocument après l'avoir lu dans le tampon. while (fis.read(buffer) != -1) { rfd.setValues("ORDER-REC", buffer);

2017/04/19 (mercredi): Nouvellement trouvé (la méthode getValue () trims sans permission):

Le code suivant est les deux méthodes qui récupèrent ORDER-NOTE, mais avec des résultats différents. (1) rfd.getValue("ORDER-REC.ORDER-NOTE") (2) rec.getField("ORDER-NOTE") Dans (1), l'espace de fin de String est supprimé sans autorisation. (2) reste tel quel s'il y a un espace de fin. (1) semble appeler PcmlDataValues.toObject () en interne. Parmi eux, trimString.

PcmlDataValues.toObject()


//For Strings, trim blanks and nulls appropriately
if (dataType == PcmlData.CHAR) {
    newVal = trimString((String)newVal, getTrim());
}

getValue () fait quelque chose d'égoïste, il est donc préférable d'utiliser la méthode getField ().

23/04/2017 (dim.): Nouvelles découvertes:

AS400Array peut écrire dans des fichiers RFML, mais lorsqu'il est lu dans des fichiers RFML, son numéro OCCURS n'est pas reproduit. AS400Structre ne peut pas écrire de fichiers RFML. Une exception se produit lorsque j'essaie de le lire et de l'utiliser comme fichier RFML.

2017/04/26 (mercredi): Examen des entrées / sorties des éléments du groupe:

Si Stream est utilisé pour l'entrée / la sortie de fichier, il est préférable d'utiliser Stream pour l'entrée / la sortie d'un tableau d'octets d'éléments de groupe dans son ensemble.

Autre code entier utilisé pour la confirmation

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;

/**
 *Test d'IBM Toolbox pour Java.<BR>
 *
 * <H1>Installation et configuration</H1><BR>
 *Depuis la page de téléchargement ci-dessous, le fichier ZIP contenant la version OSS du fichier jar(Par exemple, jtopen_9_3.zip)Télécharger.<br>
 * 「jtopen_9_3.zip\lib\java8\jt400.Passez "jar" à travers le chemin de classe.<br>
 * <br>
 * <H1>Sources d'informations, etc.</H1> <BR>
 *IBM Toolbox for Java. Une description générale fournie par 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>
 *Programmation d'IBM Toolbox pour Java. Fichier PDF. Explication générale des méthodes de programmation. 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. Un aperçu de la version open source. URL:<a href=
 * "http://jt400.sourceforge.net/">http://jt400.sourceforge.net/</a><BR>
 * JTOpen: The Open Source version of the IBM Toolbox for
 *Page de téléchargement Java. URL:<a href=
 * "https://sourceforge.net/projects/jt400/">https://sourceforge.net/projects/jt400/</a><BR>
 *Téléchargez l'URL pour la dernière 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>
 *Licence pour JTOpen et IBM Toolbox for Java. Les deux sont "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();

    /**
     *Sortie du fichier d'image principale. <BR>
     *Produit le fichier mainframe selon la définition du format d'enregistrement du fichier RFML.<BR>
     * {@code
      rec.setField("PRODUCT-GR", null);}À l'endroit{@code
    com.ibm.as400.access.ExtendedIllegalArgumentException: name (PRODUCT-GR): Field was not found.
    }<BR>
     *Je reçois une exception. La documentation API suivante indique que Structure n'est pas prise en charge. Array n'est pas non plus pris en charge.<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() {
        //Recherchez et lisez la définition du format d'enregistrement à partir du chemin de classe.
        RecordFormatDocument rfd = null;
        try {
            rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
        } catch (XmlException e) {
            throw new RuntimeException(e);
        }

        //Sortie de fichier avec code de caractère du cadre principal.
        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, Tokyo");
                //↓ Une exception se produit ici, alors commentez.
                // rec.setField("PRODUCT-GR", null);
                //Tableau d'octets et sortie dans un fichier.
                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);
                }
            }
        }
    }

    /**
     *Sortie du fichier d'image principale. <BR>
     *Produit le fichier mainframe selon la définition du format d'enregistrement du fichier RFML.<BR>
     * 1.Étant donné que l'élément de groupe et OCCURS ne se comportent pas comme prévu, cette partie est considérée comme un tableau d'octets.<BR>
     * 2.Définissez la partie d'élément de groupe dans une autre définition de format d'enregistrement et définissez-y un objet Java pour créer un tableau d'octets de code de caractère MF.<br>
     *3. 3. Au-dessus de 2 au-dessus de 1.Mis à.
     */
    @Test
    public void test02MfFileOutput() {
        //Recherchez et lisez la définition du format d'enregistrement à partir du chemin de classe.
        RecordFormatDocument rfd = null;
        try {
            rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
        } catch (XmlException e) {
            throw new RuntimeException(e);
        }

        //Sortie de fichier avec code de caractère du cadre principal.
        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, Tokyo");

                //Le code de la partie OCCURS de l'élément de groupe.
                //Un flux d'octets de l'élément de groupe entier vers lequel l'élément est transféré.
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                //Longueur d'octet de la destination de transfert d'article ÷ 1 longueur d'octet pour OCCURS(PRODUCT-GR)= Nombre d'URS OCCC
                int occursCount = rec.getFieldAsBytes("PRODUCT-B").length / grp.getRecordLength();
                //OCCURS Répétez pendant quelques minutes
                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());
                }
                //Défini dans un tableau d'octets d'éléments de groupe.
                rec.setField("PRODUCT-B", baos.toByteArray());

                //Tableau d'octets et sortie dans un fichier.
                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);
                }
            }
        }
    }

    /**
     *Entrée du fichier d'image principale. <BR>
     *Entrez le fichier mainframe en fonction de la définition du format d'enregistrement du fichier RFML.<BR>
     * 1.Étant donné que l'élément de groupe et OCCURS ne se comportent pas comme prévu, cette partie est considérée comme un tableau d'octets.<BR>
     * 2.Définissez la partie d'élément de groupe dans une autre définition de format d'enregistrement, définissez le tableau d'octets du code de caractère MF et faites-en un objet Java.<br>
     */
    @Test
    public void test03MfFileInput() {
        //Créez un fichier mainframe.
        this.test02MfFileOutput();

        //Recherchez et lisez la définition du format d'enregistrement à partir du chemin de classe.
        RecordFormatDocument rfd = null;
        try {
            rfd = new RecordFormatDocument("jp.golden.cat.util.ORDER-FILE.rfml");
        } catch (XmlException e) {
            throw new RuntimeException(e);
        }

        //Entrez un fichier avec le code de caractère du cadre principal.
        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);
            //Obtient le nombre d'octets pour un enregistrement et crée un tableau d'octets pour le tampon de lecture.
            byte[] recordBuf = new byte[rec.getRecordLength()];
            //Il n'y a aucun caractère de saut de ligne dans le fichier MF. Par conséquent, il est lu dans la mémoire tampon pour le nombre d'octets d'un enregistrement.
            while (fis.read(recordBuf) != -1) {
                //Enregistrez à partir du tableau d'octets du tampon.
                rec.setContents(recordBuf);

                System.out.print("[" + rec.getField("REC-NO"));
                System.out.print("],[" + rec.getField("ORDER-NO"));

                //Le code de la partie OCCURS de l'élément de groupe.
                //Un flux d'octets de l'élément de groupe entier à partir duquel l'élément a été obtenu.
                ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) rec.getField("PRODUCT-B"));
                //Créez un tampon de lecture pour 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-Objet Java de 4(Integer)Test pour convertir en.
     */
    @Test
    public void test01() {
        //Valeur d'entrée(Données d'octet MF)
        //Vous n'avez pas à vous soucier de l'ordre des octets, car les enders du mainframe IBM et de Java sont de gros enders.
        byte[] mfData = new byte[] { 0x0A, 0x0B, 0x0C, 0x0D };
        StringUtil.dump("test01:input   :", mfData, "");

        // COMP-Objet Java de 4(Integer)Convertir en.
        AS400Bin4 comp4 = new AS400Bin4();
        int actual = ((Integer) comp4.toObject(mfData, 0)).intValue();
        System.out.println("test01:actual  :" + actual);

        //Création de valeur attendue.
        int expected = 168496141;
        System.out.println("test01:expected:" + expected);

        //0x0A0B0C0D est le nombre décimal 164896141.
        assertEquals(expected, actual);
    }

    /**
     *Objet Java(Integer)De COMP-Test pour convertir en 4.
     */
    @Test
    public void test02() {
        //Valeur d'entrée(Objet Java)
        Integer javaObject = new Integer(168496141);
        System.out.println("test02:input   :" + javaObject);

        //Objet Java(Integer)De COMP-Convertissez en 4.
        AS400Bin4 comp4 = new AS400Bin4();
        byte[] actual = comp4.toBytes(javaObject);
        StringUtil.dump("test02:actual  :", actual, "");

        //Création de valeur attendue.
        byte[] expected = new byte[] { 0x0A, 0x0B, 0x0C, 0x0D };
        StringUtil.dump("test02:expected:", expected, "");

        // test
        assertArrayEquals(expected, actual);
    }

    /**
     *Format PIC X EBC DIC vers MS932(SJIS)Test pour convertir en. <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>
     *
     *Autre table de conversion Unicode pour 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 pour entrer des lettres minuscules.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
     *Un super ensemble de 5026 katakana kanji japonais avec des personnages Priorité kana demi-largeur(Les lettres minuscules demi-largeur ne peuvent pas être mélangées)。<BR>
     * CCSID=939 「4370 UDC
     *Caractères latins japonais, y compris les caractères Kanji, 5035 super set. Priorité des lettres minuscules demi-largeur(Les caractères kana demi-largeur ne peuvent pas être mélangés)。<BR>
     */
    @Test
    public void test03() {
        //Code de caractère MF, CCSID=930 「4370 UDC
        //Un super ensemble de 5026 katakana kanji japonais avec des personnages Priorité kana demi-largeur(Les lettres minuscules demi-largeur ne peuvent pas être mélangées)Tableau d'octets.
        // "123AαB"=0xF1F2F3C10E41410FC281。
        //Katakana demi-largeur"UNE"Est CCSID=930 est 0x81. C'est CCSID=C'est 939 0x56.
        //Caractères pleine largeur"α"Est le code de caractère MF 0X4141. Décalez ça(0x0E)Et passer(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:nombre d'octets d'entrée:" + mfData.length);

        // CCSID=930 「4370 UDC
        //Un super ensemble de 5026 katakana kanji japonais avec des personnages Priorité kana demi-largeur(Les lettres minuscules demi-largeur ne peuvent pas être mélangées)Tableau d'octets
        //Convertissez en Unicode.
        int ccsid = 930;
        AS400Text xtype = new AS400Text(mfData.length, ccsid);
        String unicodeString = (String) xtype.toObject(mfData);
        System.out.println("test03:unicodeString Nombre d'octets:" + unicodeString.length());
        StringUtil.dump("test03:unicodeString:", unicodeString.getBytes(), "");

        //Unicode à MS932(SJIS)Convertir en.
        String encoding = "MS932";
        String actual = this.convertString(unicodeString, encoding);
        System.out.println("test03:actual  :" + actual);
        //Sortir(0x0E)Et passer(0x0F)Parce qu'il n'y en a pas, c'est 2 octets de moins.
        System.out.println("test03:nombre réel d'octets:" + this.getStringByteLength(actual, encoding));
        StringUtil.dump("test03:actual  :", this.getStringBytes(actual, encoding), "");

        //Faites la valeur attendue.
        String expected = this.convertString("123AαB", encoding);
        System.out.println("test03:expected:" + expected);
        //Sortir(0x0E)Et passer(0x0F)Parce qu'il n'y en a pas, c'est 2 octets de moins.
        System.out.println("test03:nombre d'octets attendu:" + this.getStringByteLength(expected, encoding));
        StringUtil.dump("test03:expected:", this.getStringBytes(expected, encoding), "");

        // test
        assertEquals(expected, actual);
    }

    /**
     *Conversion de code de caractère.
     *
     * @param de La chaîne source.
     * @codage param Code de caractère après conversion.
     * @return La chaîne de caractères convertie.
     */
    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;
    }

    /**
     *Convertit le code de caractère et retourne sous forme de tableau d'octets.
     *
     * @param de La chaîne source.
     * @codage param Code de caractère après conversion.
     * @retourne le tableau Byte après la conversion.
     */
    byte[] getStringBytes(String from, String encoding) {
        byte[] res = null;
        try {
            res = from.getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        return res;
    }

    /**
     *Renvoie le nombre d'octets après la conversion du code de caractère.
     *
     * @param de La chaîne source.
     * @codage param Code de caractère après conversion.
     * @return Le nombre d'octets après la conversion du code de caractère.
     */
    int getStringByteLength(String from, String encoding) {
        return getStringBytes(from, encoding).length;
    }

    /**
     *Test de conversion de type de données complexe.
     */
    @Test
    public void test04() {
        //Objet composite Java
        Object[] javaObjects = {
                new Integer(88),
                new byte[] { 0x41 },
                new BigDecimal("-12.34"),
                "ABCDE"
        };

        //Définition des données composites MF
        AS400DataType[] mfDataType = {
                new AS400Bin4(),
                new AS400ByteArray(4),
                new AS400PackedDecimal(4, 2),
                new AS400Text(10)
        };

        //Génère un convertisseur avec la définition de données composites MF spécifiée par l'argument.
        AS400Structure converter = new AS400Structure(mfDataType);

        //Génère un tableau d'octets avec conversion de code de caractère MF à partir d'un objet composite Java.
        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], "]");    //Si 0x41 est défini pour 4 octets du côté réception, il sera défini à gauche. Remplissez le reste avec 0x00.
        System.out.println("[" + outJavaObjects[2] + "]");
        System.out.println("[" + outJavaObjects[3] + "]");  //Si vous définissez 5 caractères ABCDE pour 10 octets du côté récepteur, il sera défini avec la griffe gauche. Le reste est l'espace.

        // 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]);
    }

    /**
     *Un test qui crée un objet de définition de format d'enregistrement MF et définit ses valeurs en conséquence.
     */
    @Test
    public void test05() {
        //Définition de l'article
        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");

        //Définition du format d'enregistrement
        RecordFormat rf = new RecordFormat();
        rf.addFieldDescription(bfd);
        rf.addFieldDescription(cfd1);
        rf.addFieldDescription(cfd2);

        //Générez un enregistrement et définissez la valeur de l'objet Java.
        Record rec = rf.getNewRecord();
        rec.setField("REC-NO", new Integer(1));
        rec.setField("ORDER-NO", "170415-123");
        rec.setField("ORDER-NOTE", "HELLO WORLD");

        //Obtenez le tableau d'octets MF.
        byte[] actual = null;
        try {
            actual = rec.getContents();
        } catch (CharConversionException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //Valeur attendue.
        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);
    }

    /**
     *Générer l'objet de définition du format d'enregistrement MF et le test d'entrée / sortie du fichier binaire EBCIDIC en conséquence.
     */
    @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 génération d'enregistrements
            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 peut être spécifié comme argument de getContents.
                //Idiomly os.write(rec.getContents())Je l'utilise beaucoup, donc je vais y aller.
                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();
            //Obtenez le nombre d'octets pour un enregistrement et générez un tableau d'octets.
            int len = rec.getRecordLength();
            byte[] buffer = new byte[len];

            //Il n'y a aucun caractère de saut de ligne dans le fichier MF. Par conséquent, il lit dans la mémoire tampon le nombre d'octets d'un enregistrement.
            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();
                }
            }
        }
    }

    /**
     *Générez un objet de définition de format d'enregistrement MF à partir du fichier de définition de format d'enregistrement MF et testez la sortie du fichier binaire EBCDIC en conséquence..
     *
     * @lève une exception de format d'enregistrement XmlException
     * @jette une exception IOException IO File
     */
    @Test
    public void test07() throws XmlException, IOException {
        //Générer la définition du format d'enregistrement MF.
        RecordFormat rf = this.createOrderRecordFormat();

        //Enregistrez la définition du format d'enregistrement MF sur le chemin de classe.
        this.saveRecordFormat(rf, new File("src/test/java/jp/golden/cat/util/ORDER.rfml"));

        //Recherchez et lisez la définition du format d'enregistrement MF à partir du chemin de classe.
        RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.ORDER.rfml");

        //Écrivez en EBCDIC.
        File ioFile = new File("./data/AS400_2.dat");
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(ioFile);
            //10 génération d'enregistrements
            for (int i = 1; i < 11; i++) {
                //J'ai l'habitude de spécifier des éléments. "Nom de la définition du format d'enregistrement.Spécifiez l'élément dans "Nom de l'élément".
                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);
                }
            }
        }
    }

    /**
     *Générez un objet de définition de format d'enregistrement MF à partir du fichier de définition de format d'enregistrement MF et testez l'entrée du fichier binaire EBCDIC en conséquence..
     *
     * @lève une exception de format d'enregistrement XmlException
     * @jette une exception IOException IO File
     */
    @Test
    public void test08() throws XmlException, IOException {
        //Recherchez et lisez la définition du format d'enregistrement MF à partir du chemin de classe.
        RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.ORDER.rfml");

        //Lisez le fichier EBCDIC.
        File ioFile = new File("./data/AS400_2.dat");
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(ioFile);

            // rfd.toRecord("ORDER-REC").getRecordLength()Lèvera l'exception suivante.
            // com.ibm.as400.data.PcmlException: Value is not set. Processing
            // <data> element 'ORDER-REC.REC-NO'.
            //La longueur ne peut probablement pas être obtenue car l'objet Record n'est pas créé dans l'objet RecordFormatDocument.
            //Par conséquent, getNewRecord()Créez un objet avec, puis obtenez la longueur.
            // int len = rfd.toRecord("ORDER-REC").getRecordLength();

            //Obtenez le nombre d'octets pour un enregistrement et générez un tableau d'octets.
            int len = rfd.toRecordFormat("ORDER-REC").getNewRecord().getRecordLength();
            byte[] buffer = new byte[len];

            //Il n'y a aucun caractère de saut de ligne dans le fichier MF. Par conséquent, il lit dans la mémoire tampon le nombre d'octets d'un enregistrement.
            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"));

                //Le code suivant est à la fois ORDER-Il s'agit d'une méthode pour récupérer NOTE, mais le résultat est différent.
                // (1) rfd.getValue("ORDER-REC.ORDER-NOTE")
                // (2) rec.getField("ORDER-NOTE")
                // (1)L'espace de fin de la chaîne est supprimé sans autorisation.(2)Restera intact s'il y a un espace de fin.
                // (1)En interne PcmlDataValues.toObject()Semble appeler. Parmi eux, trimString.
                /*
                 * //For Strings, trim blanks and nulls appropriately if
                 * (dataType == PcmlData.CHAR) { newVal = trimString((String)
                 * newVal, getTrim()); }
                 */
                // getValue()Fait des choses égoïstes, alors getField()Il vaut mieux utiliser la méthode.
                System.out.print("],[" + rec.getField("ORDER-NOTE"));
                System.out.println("]");
            }
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     *La structure OCCURS peut-elle être une définition de format d'enregistrement? => Je ne peux pas.
     *
     * @lève une exception de format d'enregistrement XmlException
     * @jette une exception IOException IO File
     */
    @Test
    public void test09() throws XmlException, IOException {
        //Définition du type de données AS400
        AS400DataType[] as400Types = new AS400DataType[] {
                new AS400Text(10),
                new AS400PackedDecimal(4, 2),
        };
        AS400Structure as400Structure = new AS400Structure(as400Types);
        AS400Array as400Array = new AS400Array(as400Structure, 3);

        //Objet Java => Tableau d'octets de données AS400
        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, "");

        //Type de données AS400(Structure+Array)Les définitions de format d'enregistrement peuvent-elles être enregistrées au format XML? => Je ne peux pas.
        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 {
            //Dans RecordFormat, AS400Structure ne peut pas être enregistré en tant que fichier RFML avec l'exception suivante:
            // com.ibm.as400.data.XmlException: Data type AS400Structure is not
            // supported by RFML.
            //La documentation de l'API indiquait également qu'elle n'était pas prise en charge. Je veux également voir l'AS400Array multidimensionnel.
            // 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 ne peut pas être transformé en fichier RFML, donc conservez-le jusqu'à ce que le nombre d'octets soit compté et enregistrez-le dans le fichier RFML.
     *
     */
    @Test
    public void test10() {
        //Définition du type de données AS400
        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+Créez une définition de AS400ByteArray pour le nombre d'octets de AS400Structure.
        AS400ByteArray as400ByteArray = new AS400ByteArray(as400Array.getByteLength());

        //Créez une définition de format d'enregistrement.
        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 pour le nombre d'octets de 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);

        //Enregistrer dans un fichier RFML.
        File rfml = new File("src/test/java/jp/golden/cat/util/ORDER3.rfml");
        this.saveRecordFormat(rf, rfml);
    }

    /**
     * AS400Array+Étant donné que AS400Structure ne peut pas être transformé en fichier RFML, l'enregistrement est généré sous la forme d'un fichier RFML qui exprime cette partie dans un tableau d'octets..
     *
     * @lève une exception de format d'enregistrement XmlException
     * @jette une exception IOException IO File
     */
    @Test
    public void test11() throws XmlException, IOException {
        //Définition du type de données AS400
        AS400DataType[] types = new AS400DataType[] {
                new AS400Text(10),
                new AS400PackedDecimal(4, 2),
        };
        AS400Structure as400structure = new AS400Structure(types);
        AS400Array as400array = new AS400Array(as400structure, 3);

        //Générez un objet d'enregistrement à partir d'un fichier RFML.
        RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.ORDER3.rfml");
        Record rec = rfd.toRecordFormat("ORDER3-REC").getNewRecord();

        //Sortie de fichier MF
        File ioFile = new File("./data/AS4003.dat");
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(ioFile);
            //10 génération d'enregistrements
            for (int i = 1; i < 11; i++) {
                rec.setField("REC-NO", new Integer(i));
                rec.setField("ORDER-NO", "170415-123");

                // AS400Array+Créer un tableau d'octets pour la partie Structure AS400
                //Tout d'abord, créez un objet Java à définir
                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"),
                    };
                }
                //Image de création d'un tableau d'octets à partir d'un objet Java bidimensionnel
                byte[] as400bytes = as400array.toBytes(inJavaObject);
                System.out.println("test11:" + as400bytes.length);
                //Définir ce tableau d'octets
                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 ne peut pas être converti en fichier RFML, considérez donc AS400Structure comme un enregistrement, convertissez-le en fichier RFML et lisez-le.
     *
     * @lève une exception de format d'enregistrement XmlException
     * @jette une exception IOException IO File
     */
    @Test
    public void test12() throws IOException, XmlException {
        //Générez un objet d'enregistrement à partir d'un fichier RFML.
        RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.ORDER4.rfml");
        Record rec1 = rfd.toRecordFormat("ORDER4-REC").getNewRecord();
        //Enregistrer la définition pour 1 OCCURS. Je veux vraiment utiliser AS400 Structure, mais ce n'est pas pris en charge.
        Record rec2 = rfd.toRecordFormat("AMOUNTS").getNewRecord();

        //Entrée de fichier MF
        File ioFile = new File("./data/AS4003.dat");
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(ioFile);
            //Obtenez le nombre d'octets pour un enregistrement et générez un tableau d'octets.
            int len = rec1.getRecordLength();
            byte[] buffer = new byte[len];
            //Il n'y a aucun caractère de saut de ligne dans le fichier MF. Par conséquent, il lit dans la mémoire tampon le nombre d'octets d'un enregistrement.
            while (fis.read(buffer) != -1) {
                rec1.setContents(buffer);

                System.out.print("[" + rec1.getField("REC-NO"));
                System.out.print("],[" + rec1.getField("ORDER-NO"));

                //Obtenez un tableau d'octets pour l'ensemble des OCCURS
                byte[] amounts = (byte[]) rec1.getField("AMOUNTS");
                //Longueur d'octet de l'ensemble OCCURS ÷ 1 longueur d'octet pour OCCURS = Nombre d'OCCURS
                int occursCount = amounts.length / rec2.getRecordLength();
                //OCCURS Répétez pendant quelques minutes
                for (int i = 0; i < occursCount; i++) {
                    //Crop 1 OCCURS à partir du tableau d'octets montants.
                    rec2.setContents(amounts, i * rec2.getRecordLength());
                    //1 ORDRE qui compose OCCURS-Sortie standard de CNO et 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();
                }
            }
        }

    }

    /**
     *Test de comportement de AS400Array.
     *
     *La ventilation de AS400Array est un total de 30 octets de structure de données de type X 10 octets x 3 OCCURS.
     *Enregistrez-le dans un fichier RFML. Compter en XML="3"Devrait être produit avec. Jusqu'à présent, cela a fonctionné.
     *Cependant, lorsque je lis le fichier RFML, crée un objet Record et obtient la longueur, il est de 10 octets. OCCURS n'est pas reproduit.
     *
     *Conclusion:Il est possible d'écrire count dans le fichier RFML, mais n'utilisez pas count dans le fichier RFML car il sera perdu lors de la lecture.
     *
     * @lève une exception de format d'enregistrement XmlException
     * @jette une exception IOException IO File
     */
    @Test
    public void test13() throws IOException, XmlException {
        //Définition de l'article
        AS400Array as400Array = new AS400Array(new AS400Text(10), 3);
        ArrayFieldDescription afd = new ArrayFieldDescription(as400Array, "ORDER-NOTE");

        //Enregistrez la définition du format d'enregistrement sous forme de fichier.
        RecordFormat rf = new RecordFormat("TEST13-REC");
        rf.addFieldDescription(afd);
        //Valeur attendue:10*3=30byte.
        int expected = rf.getNewRecord().getRecordLength();
        // count="3"Il est enregistré au format.
        this.saveRecordFormat(rf, new File("src/test/java/jp/golden/cat/util/TEST13.rfml"));

        //Générez un objet d'enregistrement à partir d'un fichier RFML.
        RecordFormatDocument rfd = this.loadRecordFormatDocument("jp.golden.cat.util.TEST13.rfml");
        // 10*3=J'attends 30 octets, mais pour une raison quelconque, 10 est renvoyé. le nombre est ignoré.
        int actual = rfd.toRecordFormat("TEST13-REC").getNewRecord().getRecordLength();
        //Lorsque j'essaye de le sauvegarder comme après, le décompte disparaît et il est sauvegardé.
        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);

    }

    /**
     *Créer une définition de format d'enregistrement de commande.
     *
     * @return Créer une définition de format d'enregistrement de commande.
     */
    RecordFormat createOrderRecordFormat() {
        //Définition de l'article
        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");

        //Définition du format d'enregistrement
        RecordFormat rf = new RecordFormat("ORDER-REC");
        rf.addFieldDescription(bfd);
        rf.addFieldDescription(cfd1);
        rf.addFieldDescription(pfd);
        rf.addFieldDescription(cfd2);

        return rf;
    }

    /**
     *Obtient la définition du format d'enregistrement MF à partir du chemin d'accès aux classes.
     *
     * @param rfmlClassPath。
     * @renvoie la définition du format d'enregistrement MF.
     */
    RecordFormatDocument loadRecordFormatDocument(String rfmlClassPath) {
        RecordFormatDocument rfd = null;
        try {
            rfd = new RecordFormatDocument(rfmlClassPath);
        } catch (XmlException e) {
            throw new RuntimeException(e);
        }
        return rfd;
    }

    /**
     *Enregistrez la définition du format d'enregistrement MF dans un fichier.
     *
     * @param rf Format de définition d'enregistrement MF.
     * @param rfml
     *Chemin du fichier de définition du format d'enregistrement MF. Notez que s'il n'y a pas de fichier de définition sur le chemin de classe, le fichier de définition ne peut pas être lu ultérieurement.
     */
    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);
                }
            }
        }
    }

    /**
     *Confirmation endian.
     *
     *Ordre des octets natif:LITTLE_ENDIAN<br>
     *valeur initiale:0A0B0C0D12345678<br>
     * LITTLE_ENDIAN:0D0C0B0A BIG_ENDIAN:0A0B0C0D<br>
     * LITTLE_ENDIAN:78563412 BIG_ENDIAN:12345678<br>
     */
    @Test
    public void testEndian() {
        System.out.println("testEndian:");
        //Sortie standard de l'ordre des octets natif.
        //Dans le traitement interne de Java, c'est un gros boutiste, mais comme le processeur Intel est un petit ange, si vous exécutez la méthode suivante sur la machine virtuelle Java du processeur Intel,
        //"Ordre des octets natif:LITTLE_"ENDIAN" s'affiche.
        System.out.println("Ordre des octets natif:" + ByteOrder.nativeOrder());

        byte[] mfData = new byte[] { 0xA, 0xB, 0xC, 0xD, 0x12, 0x34, 0x56, 0x78 };
        StringUtil.dump("valeur initiale:", 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("Vérifiez la relation entre la longueur du tampon de lecture et la valeur d'entrée.");
                }
                //Converti avec peu de tolandien.
                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");

                //Converti avec Big Endian.
                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

Comment entrer / sortir des fichiers mainframe IBM en Java?
[Java] Comment sortir et écrire des fichiers!
Comment désassembler un fichier de classe Java
Comment apprendre JAVA en 7 jours
Enregistrer la sortie dans un fichier en Java
Comment décompiler un fichier de classe Java
Comment utiliser les classes en Java?
Comment nommer des variables en Java
Comment concaténer des chaînes avec Java
Comment implémenter le calcul de la date en Java
Comment implémenter le filtre de Kalman par Java
Prise en charge multilingue de Java Comment utiliser les paramètres régionaux
Comment faire une conversion de base en Java
Comment sortir une chaîne Java sur l'écran de la console
Convertir des fichiers SVG en fichiers PNG en Java
Comment appliquer les conventions de codage en Java
Comment intégrer Janus Graph dans Java
Comment obtenir la date avec Java
Comment colorer la sortie de la console de code dans Eclipse
Comment afficher une page Web en Java
Comment obtenir une classe depuis Element en Java
Comment mettre à jour un fichier prédéfini dans un conteneur Docker
Comment masquer les champs nuls en réponse en Java
J'ai essayé de sortir quatre-vingt-dix-neuf en Java
Comment résoudre les problèmes d'expression en Java
Comment écrire Java String # getBytes dans Kotlin?
Comment appeler des fonctions en bloc avec la réflexion Java
[Ruby] Comment utiliser la sortie standard dans le branchement conditionnel
Comment créer un URI de données (base64) en Java
Android-Télécharger des fichiers image vers Azure Blob Storage en Java
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
Comment gérer les fichiers TSV et les fichiers CSV dans Ruby
Comment convertir un fichier en tableau d'octets en Java
Comment Git gérer les projets Java EE dans Eclipse
Comment mettre en évidence la syntaxe d'un fichier comme Dockerfile.production avec Pycharm
Résumé de la mise en œuvre des arguments par défaut en Java
Comment mettre l'ancien Java (série 8) dans macOS 10.15 Catalina
Remarques sur l'utilisation des expressions régulières en Java
Lire des fichiers binaires en Java 1
[Java] Comment utiliser Map
Comment désinstaller Java 8 (Mac)
Java - Comment créer JTable
Comment utiliser java Facultatif
Comment réduire les images Java
Comment rédiger un commentaire java
Comment utiliser la classe Java
Lire l'entrée standard en Java
[Java] Comment utiliser removeAll ()
[Java] Comment afficher les Wingdings
Comment utiliser Java Map
Comment définir des constantes Java
Lire des fichiers binaires dans Java 2