Lire des fichiers binaires dans Java 2

C'est une continuation de 1

https://qiita.com/gnagaoka/items/1a1c862b9def660abb77

Disposition des structures

Il existe N structures. Le nombre de séquences est écrit peu de temps avant Zubya, et après l'avoir lu, lisez la structure de ce nombre. En d'autres termes, les valeurs internes sont un tableau, donc cela ressemble à ce qui suit.

public class LIST<T extends DataTypeInterface> extends SingleDataType<ArrayList<T>> {


    /**
     *Jugement d'arrêt de boucle
     */
    private BiPredicate<Integer,Integer> isNext;

    /**
     *Usine 2
     */
    private IntFunction<T> factory;

    /**
     * constructor
     * @usine d'usine param
     * @param isNext S'il faut passer à l'élément suivant
     */
    public LIST( IntFunction<T> factory,
                 BiPredicate<Integer,Integer> isNext){

        this.factory    = factory;
        this.isNext     = isNext;
        this.set(new ArrayList<>());
    }

    /**
     *Renvoie la taille de l'objet
     *
     * @Taille d'octet de l'objet de retour
     */
    @Override
    public Integer getSize() {
        return this.get().stream().mapToInt(DataTypeInterface::getSize).sum();
    }

    /**
     * 1.Enregistrer la position de décalage actuelle du tampon<br>
     * 2.Obtenez le nombre de scans<br>
     * 3.Seul le nombre de scans 4,Processus 5<br>
     * 4.Effectuer une pré-décompilation pour créer une instance<br>
     * 5.Exécuter la méthode de décompilation de l'instance<br>
     * <br>
     ** Les éléments enfants qui n'ont pas pu être décompilés sont ignorés<br>
     * <br>
     * @tampon de param buf
     */
    @Override
    public void decompile(ByteBuffer buf){
        this.setOffset(buf.position());

        Integer index  = 0;
        Integer length = 0;

        while (this.isNext.test(index, length)) {
            try {
                T s = this.factory.apply(index);
                s.decompile(buf);
                this.get().add(s);
            } catch (LISTSkipException e) {
                continue;
            } catch (LISTStopException e) {
                break;
            } finally {
                index++;
                length = buf.position() - this.getOffset();
            }
        }
    }

    /**
     * 1.Enregistrer la position de décalage actuelle du tampon<br>
     * 2.Exécuter la méthode de compilation sur tous les éléments enfants<br>
     * <br>
     ** Les éléments enfants qui n'ont pas pu être compilés sont ignorés
     *
     * @tampon de param buf
     */
    @Override
    public void compile(ByteBuffer buf) throws IllegalStateException,IllegalArgumentException {
        this.setOffset(buf.position());

        for(T s : this.get()){
            try {
                s.compile(buf);
            } catch (LISTSkipException e) {
                continue;
            } catch (LISTStopException e) {
                break;
            }
        }
    }

    /*
    advanced method
     */

    /**
     *Récupère le premier élément du tableau
     * @retourne le premier élément
     */
    public T first(){
        return this.get(0);
    }

    /**
     *Récupère le deuxième élément du tableau
     * @return Dernier élément
     */
    public T second(){
        return this.get(1);
    }

    /**
     *Récupère le dernier élément du tableau
     * @return Dernier élément
     */
    public T last(){
        return this.get().get(this.get().size() - 1);
    }

    /**
     *Ajouter le dernier élément du tableau
     * @return Dernier élément
     */
    public T push(){
        return this.get(this.get().size());
    }

    /**
     *Valeur interne[index]Obtenir.
     *
     * @index d'index de paramètre
     * @valeur d'index de retour
     */
    public T get(Integer index) {
        T x;
        try {
            x = this.get().get(index);
        }catch (IndexOutOfBoundsException e){
            x = this.factory.apply(index);
            /*Remplissez pour indexer*/
            while((this.get().size()) < (index+1)){
                x = this.factory.apply(this.get().size());
                this.get().add(x);
            }
        }

        return x;
    }
}

Les points sont isNext et factory. En les utilisant, vous pouvez vous référer à d'autres sensations en utilisant lambda pour le nombre de séquences. L'utilisation est la suivante.

    @PROPERTY(order = 5)
    public USHORT numHoge= new USHORT();

    @PROPERTY(order = 6)
    public LIST<HogeObject> items = new LIST<>(
            (i)     -> new HogeObject(),
            (i,len) -> this.numHoge.get() > i
    );

décalage

Il est tout à fait possible que la valeur de décalage de la structure soit définie en premier, puis que la structure soit lue après le déplacement vers la destination de décalage. Le décalage provient souvent du début de sa propre structure, et non du début du binaire. C'est comme ça.


public class OFFSETW<T extends DataTypeInterface> extends CompositeDataType {

    /**
     *Référence au décalage
     */
    protected NumericDataType offset;

    /**
     *Référence à la longueur d'octet
     */
    protected NumericDataType lengthW;

    /**
     *Référence à la somme de contrôle
     */
    protected NumericDataType checkSum;

    /**
     *Référence au décalage de base
     */
    protected DataTypeInterface baseObject;

    /*
    structure
     */
    /**
     *Référence à l'objet de référence
     */
    @PROPERTY(order = 1)
    public T reference;

    /*
    structure method
     */

    /**
     * constructor<br>
     *Définir un objet de référence qui est décalé par rapport à l'objet de base
     *
     * @offset de paramétrage
     * @param baseObject Objet de base
     * @référence param Objet de référence
     */
    public OFFSETW(NumericDataType offset,DataTypeInterface baseObject,T reference) {
        this.offset = offset;
        this.reference = reference;
        this.baseObject = baseObject;
    }

    /**
     * constructor<br>
     *Définir un objet de référence qui est décalé par rapport à l'objet de base
     *
     * @tampon de param buf
     * @offset de paramétrage
     * @param baseObject Objet de base
     * @référence param Objet de référence
     */
    public OFFSETW(ByteBuffer buf , NumericDataType offset,DataTypeInterface baseObject,T reference) {
        this.offset = offset;
        this.reference = reference;
        this.baseObject = baseObject;
        this.decompile(buf);
    }

    /**
     * constructor
     *Définir un objet de référence qui est décalé par rapport à l'objet de base<br>
     * <br>
     ** Ce constructeur est un peu spécial et la longueur d'octet de l'objet de référence cible est définie à l'emplacement spécifié.<br>
     *Lien Il calcule également une somme de contrôle à partir de cette chaîne d'octets et la lie à l'emplacement spécifié.<br>
     *Ceci est particulièrement utile pour les sous-tables cmap et les tables de polices.<br>
     *
     * ToDO:Il faut se demander s'il faut en faire une classe différente
     *
     * @offset de paramétrage
     * @param baseObject Objet de base
     * @référence param Objet de référence
     * @objet de longueur d'octet de longueur de paramètre
     * @param checkSum Objet Checksum
     */
    public OFFSETW(NumericDataType offset,
                   NumericDataType length,
                   NumericDataType checkSum,
                   DataTypeInterface baseObject,
                   T reference
    ) {

        this.offset = offset;
        this.reference = reference;
        this.baseObject = baseObject;
        this.lengthW = length;
        this.checkSum = checkSum;
    }

    /**
     *Convertit un objet en tampon d'octets.<br>
     *Seule la conversion de la valeur de décalage est effectuée.<br>
     *Le décalage étant inconnu, 0 est écrit.<br>
     *Le décalage sur lequel la valeur de décalage est écrite est enregistré.<br>
     *
     * @tampon de param buf
     */
    @Override
    public void compile(ByteBuffer buf) {
        this.setOffset(buf.position());
        Integer offset =  buf.position();
        buf.position(this.offset.getOffset());

        this.offset.setNumber(offset - baseObject.getOffset());

        this.offset.compile(buf);
        buf.position(offset);
        this.reference.compile(buf);

        /*Rendez-le divisible par 4*/
        offset =  buf.position();
        Long length = offset.longValue() - this.getOffset();

        /*Indivisible*/
        Long mod = length % 4;
        if(mod > 0){
            /*padding*/
            for(Integer j = 0; j< (4-mod) ; j++){
                buf.put((byte)0);
            }
        }
        /*Mise à jour de l'offset*/
        offset =  buf.position();

        /*Lorsque l'écriture de longueur d'octet est spécifiée*/
        if(this.lengthW != null){
            buf.position(this.lengthW.getOffset());
            this.lengthW.setNumber(length);
            this.lengthW.compile(buf);
            buf.position(offset);
        }
    }

    /*
    advanced method
     */

    /**
     *Obtenir des éléments enfants
     *
     * @retourner l'élément enfant
     */
    @Override
    public T get() {
        return this.reference;
    }

    /**
     *Convertit un tampon d'octets en objet.<br>
     *Convertit un tampon d'octets en objet.<br>
     *La destination de décalage est décompilée en même temps que la valeur de décalage est lue.<br>
     *À ce moment-là, vous pouvez également ajouter le décalage de base à la valeur de décalage.<br>
     *Mis à 0 si le décalage de base n'existe pas.<br>
     *
     * @tampon de param buf
     */
    @Override
    public void decompile(ByteBuffer buf){

        /**
         *offset est 0 est nul
         */
        if(this.offset.get().intValue() == 0){
            return ;
        }

        /**
         *Souvenez-vous du décalage actuel
         */
        Integer old_offset = buf.position();

        /**
         *Enregistrer la destination du décalage
         */
        this.setOffset(this.baseObject.getOffset() + this.offset.get().intValue());

        /**
         *Volez vers la destination offset
         */
        buf.position(this.getOffset());

        /**
         *décompiler
         */
        this.reference.decompile(buf);

        /**
         *Annuler le décalage
         */
        buf.position(old_offset);
    }


}

C'est facile (^ ω ^).

    @PROPERTY(order = 1)
    public USHORT gesoOffset = new USHORT();

    // ...

    //Ecrivez-le au dos
    @PROPERTY(order = 23)
    public OFFSETW<Geso> geso= new OFFSETW<>(
            this.gesoOffset,
            this,
            new Geso()
    );

En l'utilisant avec LIST, vous pouvez lire que Offset est un tableau.

    @PROPERTY(order = 1)
    public USHORT hogeCount = new USHORT()

    @PROPERTY(order = 2)
    public LIST<HogeRecord> hogeRecords= new LIST<>(
            (i)     -> new HogeRecord(this),
            (i,len) -> this.hogeCount.get() > i
    );

    @PROPERTY(order = 3)
    public LIST<OFFSETW<HogeHoge>> scripts = new LIST<>(
            (i) -> new OFFSETW<>(
                    this.hogeRecords.get().get(i).offset,
                    this,
                    new HogeHoge()
            ),
            (i,len) -> this.hogeCount.get() > i
    );

Branche conditionnelle

Il y a aussi une lecture à de tels moments.

public class R<Z extends DataTypeInterface> extends CompositeDataType {

    /**
     *Définir la décompilation
     * buf → (new,decompile) → instance
     */
    public Function<ByteBuffer, Z> decompiler;

    /**
     *Définir la compilation
     * buf,Z → (compile) →
     */
    public BiConsumer<ByteBuffer, Z> compiler;

    /**
     * factory
     * → (new) → instance
     */
    protected Supplier<Z> factory;

    /**
     *Efficacité|Jugement invalide
     */
    public Supplier<Boolean> enable;

    /**
     *Contenu
     */
    public Z content;

    /**
     * constructor
     * <p>
     *permettre d'activer ou de désactiver cet objet
     *Veuillez transmettre l'expression lambda.
     *
     * @param compilateur Fonction exécutée au moment de la compilation
     * @Fonction exécutée au moment du décompilateur de param decomile
     * @param enable     True:Efficacité,False:Invalide
     */
    public R(
            Function<ByteBuffer, Z> decompiler,
            BiConsumer<ByteBuffer, Z> compiler,
            Supplier<Boolean> enable) {

        this.decompiler = decompiler;
        this.compiler = compiler;
        this.enable = enable;
    }

    /**
     * constructor
     * <p>
     *enable pour activer ou désactiver cet objet
     *Veuillez transmettre l'expression lambda.
     *
     * @instanciation d'usine de param//ToDO:Je veux le changer pour la génération des génériques ...
     * @param enable     True:Efficacité,False:Invalide
     */
    public R(
            Supplier<Z> factory,
            Supplier<Boolean> enable) {

        this.factory= factory;
        this.enable = enable;
    }

    /**
     * getter
     *
     * @retourner le contenu
     */
    public Z get() {
        if(this.content == null){
            this.content =  this.factory.get();
        }

        return this.content;
    }

    @Override
    public void decompile(ByteBuffer buf) {
        this.setOffset(buf.position());
        if (this.enable.get()) {
            if(this.decompiler != null ){
                this.content = this.decompiler.apply(buf);
            }else{
                this.content = this.factory.get();
                this.content.decompile(buf);
            }
        }
    }

    @Override
    public void compile(ByteBuffer buf) {
        this.setOffset(buf.position());
        if (this.enable.get()) {
            if(this.compiler != null ){
                this.compiler.accept(buf,this.content);
            }else{
                this.content.compile(buf);
            }
        }
    }

    @Override
    public Object exports() {
        if (this.enable.get()) {
            return this.content.exports();
        } else {
            return null;
        }
    }
}

Il peut être utilisé lorsque la structure des données diffère en fonction du numéro de format.


    @PROPERTY(order = 1)
    public USHORT formatNum = new USHORT();

    @PROPERTY(order = 2)
    public R<GesoGesoFormat1> gesogesoFormat1= new R<>(
            ()-> new GesoGesoFormat1(this),
            ()-> this.formatNum.get() == 1
    );

    @PROPERTY(order = 2)
    public R<GesoGesoFormat2> gesogesoFormat2= new R<>(
            ()-> new GesoGesoFormat2(this),
            ()-> this.formatNum.get() == 2
    );

En combinant LIST, R et OFFSET, même des structures de données complexes peuvent être écrites structurellement.

fin

Recommended Posts

Lire des fichiers binaires en Java 1
Lire des fichiers binaires dans Java 2
Lisez facilement les fichiers texte en Java (Java 11 et Java 7)
Lire JSON en Java
Lire l'entrée standard en Java
Lire le fichier de propriétés Java en C #
Lire CSV en Java (annotation Super CSV)
Créer des données binaires de longueur variable en Java
Communication TCP (communication socket) en Java (ASCII, Binaire)
Partition en Java
Changements dans Java 11
Java-Comment comparer des fichiers image en binaire
Janken à Java
Lire Felica en utilisant RC-S380 (PaSoRi) en Java
Lecture de fichiers RAW, WAV, MP3 en Java
Lire le fichier xlsx en Java avec Selenium
Taux circonférentiel à Java
FizzBuzz en Java
Lire et écrire des fichiers gzip en Java
Lire une chaîne dans un fichier PDF avec Java
Ajouter, lire et supprimer des commentaires Excel à l'aide de Java
[Java] Lire les fichiers dans src / main / resources
Importer des fichiers de la même hiérarchie en Java
Implémentation de l'interpréteur par Java
Faites un blackjack avec Java
Application Janken en Java
Programmation par contraintes en Java
Mettez java8 dans centos7
Joindre des tableaux en Java
"Hello World" en Java
Lire le fichier de propriétés Java
Interface appelable en Java
Commentaires dans la source Java
Fonctions Azure en Java
Formater XML en Java
Simple htmlspecialchars en Java
Implémentation Boyer-Moore en Java
Lire la source Java HashMap
Hello World en Java
Utiliser OpenCV avec Java
Mémorandum WebApi avec Java
Détermination de type en Java
Exécuter des commandes en Java (ping)
Divers threads en java
API Zabbix en Java
Art ASCII à Java
Comparer des listes en Java
POST JSON en Java
Exprimer l'échec en Java
Créer JSON en Java
Manipulation de la date dans Java 8
Nouveautés de Java 8
Utiliser PreparedStatement en Java
Nouveautés de Java 9,10,11
Exécution parallèle en Java
Lire la capture de paquets obtenue par tcpdump avec Java
Comment entrer / sortir des fichiers mainframe IBM en Java?
Android-Télécharger des fichiers image vers Azure Blob Storage en Java
Comment lire votre propre fichier YAML (*****. Yml) en Java