Lesen Sie Binärdateien in Java 2

Es ist eine Fortsetzung von 1

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

Anordnung der Strukturen

Es gibt N Strukturen. Die Anzahl der Sequenzen wird kurz vor Zubya geschrieben und nach dem Lesen die Struktur für diese Anzahl gelesen. Mit anderen Worten, die internen Werte sind ein Array, daher sieht es wie folgt aus.

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


    /**
     *Loop-Stop-Urteil
     */
    private BiPredicate<Integer,Integer> isNext;

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

    /**
     * constructor
     * @param Fabrik Fabrik
     * @param isNext Gibt an, ob zum nächsten Element gewechselt werden soll
     */
    public LIST( IntFunction<T> factory,
                 BiPredicate<Integer,Integer> isNext){

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

    /**
     *Geben Sie die Größe des Objekts zurück
     *
     * @Bytegröße des Rückgabeobjekts
     */
    @Override
    public Integer getSize() {
        return this.get().stream().mapToInt(DataTypeInterface::getSize).sum();
    }

    /**
     * 1.Notieren Sie die aktuelle Versatzposition des Puffers<br>
     * 2.Ermitteln Sie die Anzahl der Scans<br>
     * 3.Nur die Anzahl der Scans 4,Prozess 5<br>
     * 4.Führen Sie preDecompile aus, um eine Instanz zu erstellen<br>
     * 5.Führen Sie die Dekompilierungsmethode der Instanz aus<br>
     * <br>
     ** Untergeordnete Elemente, die nicht dekompiliert werden konnten, werden übersprungen<br>
     * <br>
     * @param buf buffer
     */
    @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.Notieren Sie die aktuelle Versatzposition des Puffers<br>
     * 2.Führen Sie die Kompilierungsmethode für alle untergeordneten Elemente aus<br>
     * <br>
     ** Untergeordnete Elemente, die nicht kompiliert werden konnten, werden übersprungen
     *
     * @param buf buffer
     */
    @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
     */

    /**
     *Holen Sie sich das erste Element des Arrays
     * @erstes Element zurückgeben
     */
    public T first(){
        return this.get(0);
    }

    /**
     *Holen Sie sich das zweite Element des Arrays
     * @letztes Element zurückgeben
     */
    public T second(){
        return this.get(1);
    }

    /**
     *Holen Sie sich das letzte Element des Arrays
     * @letztes Element zurückgeben
     */
    public T last(){
        return this.get().get(this.get().size() - 1);
    }

    /**
     *Fügen Sie das letzte Element des Arrays hinzu
     * @letztes Element zurückgeben
     */
    public T push(){
        return this.get(this.get().size());
    }

    /**
     *Interner Wert[index]Bekommen.
     *
     * @param index index
     * @Indexwert zurückgeben
     */
    public T get(Integer index) {
        T x;
        try {
            x = this.get().get(index);
        }catch (IndexOutOfBoundsException e){
            x = this.factory.apply(index);
            /*Füllen Sie bis zum Index*/
            while((this.get().size()) < (index+1)){
                x = this.factory.apply(this.get().size());
                this.get().add(x);
            }
        }

        return x;
    }
}

Die Punkte sind isNext und factory. Wenn Sie diese verwenden, können Sie sich auf andere Gefühle beziehen, die Lambda für die Anzahl der Sequenzen verwenden. Die Verwendung ist wie folgt.

    @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
    );

Versatz

Es ist durchaus möglich, dass zuerst der Versatzwert für die Struktur definiert wird und dann die Struktur gelesen wird, nachdem zum Versatzziel gewechselt wurde. Der Offset ist oft nicht vom Anfang der Binärdatei, sondern vom Anfang ihrer eigenen Struktur. Es ist so.


public class OFFSETW<T extends DataTypeInterface> extends CompositeDataType {

    /**
     *Verweis auf Offset
     */
    protected NumericDataType offset;

    /**
     *Verweis auf Bytelänge
     */
    protected NumericDataType lengthW;

    /**
     *Verweis auf Prüfsumme
     */
    protected NumericDataType checkSum;

    /**
     *Verweis auf Basisversatz
     */
    protected DataTypeInterface baseObject;

    /*
    structure
     */
    /**
     *Verweis auf Referenzobjekt
     */
    @PROPERTY(order = 1)
    public T reference;

    /*
    structure method
     */

    /**
     * constructor<br>
     *Definieren Sie ein Referenzobjekt, das vom Basisobjekt versetzt ist
     *
     * @param offset offset
     * @param baseObject Basisobjekt
     * @param reference Referenzobjekt
     */
    public OFFSETW(NumericDataType offset,DataTypeInterface baseObject,T reference) {
        this.offset = offset;
        this.reference = reference;
        this.baseObject = baseObject;
    }

    /**
     * constructor<br>
     *Definieren Sie ein Referenzobjekt, das vom Basisobjekt versetzt ist
     *
     * @param buf buffer
     * @param offset offset
     * @param baseObject Basisobjekt
     * @param reference Referenzobjekt
     */
    public OFFSETW(ByteBuffer buf , NumericDataType offset,DataTypeInterface baseObject,T reference) {
        this.offset = offset;
        this.reference = reference;
        this.baseObject = baseObject;
        this.decompile(buf);
    }

    /**
     * constructor
     *Definieren Sie ein Referenzobjekt, das vom Basisobjekt versetzt ist<br>
     * <br>
     ** Dieser Konstruktor ist etwas Besonderes und die Bytelänge des Zielreferenzobjekts wird auf den angegebenen Speicherort festgelegt.<br>
     *Verknüpfung Es berechnet auch eine Prüfsumme aus dieser Bytezeichenfolge und verknüpft sie mit dem angegebenen Speicherort.<br>
     *Dies ist besonders nützlich für cmap-Untertabellen und Schriftarten.<br>
     *
     * ToDO:Es ist zu überlegen, ob es sich um eine andere Klasse handelt
     *
     * @param offset offset
     * @param baseObject Basisobjekt
     * @param reference Referenzobjekt
     * @Parameter Länge Byte Länge Objekt
     * @param checkSum Prüfsummenobjekt
     */
    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;
    }

    /**
     *Konvertiert ein Objekt in einen Bytepuffer.<br>
     *Es wird nur die Offsetwertkonvertierung durchgeführt.<br>
     *Da der Offset unbekannt ist, wird 0 geschrieben.<br>
     *Der Versatz, in den der Versatzwert geschrieben wird, wird aufgezeichnet.<br>
     *
     * @param buf buffer
     */
    @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);

        /*Machen Sie es teilbar durch 4*/
        offset =  buf.position();
        Long length = offset.longValue() - this.getOffset();

        /*Unteilbar*/
        Long mod = length % 4;
        if(mod > 0){
            /*padding*/
            for(Integer j = 0; j< (4-mod) ; j++){
                buf.put((byte)0);
            }
        }
        /*Offset-Update*/
        offset =  buf.position();

        /*Wenn das Schreiben der Bytelänge angegeben ist*/
        if(this.lengthW != null){
            buf.position(this.lengthW.getOffset());
            this.lengthW.setNumber(length);
            this.lengthW.compile(buf);
            buf.position(offset);
        }
    }

    /*
    advanced method
     */

    /**
     *Holen Sie sich untergeordnete Elemente
     *
     * @untergeordnetes Element zurückgeben
     */
    @Override
    public T get() {
        return this.reference;
    }

    /**
     *Konvertiert einen Bytepuffer in ein Objekt.<br>
     *Konvertiert einen Bytepuffer in ein Objekt.<br>
     *Das Versatzziel wird gleichzeitig mit dem Lesen des Versatzwerts dekompiliert.<br>
     *Zu diesem Zeitpunkt können Sie auch den Basisversatz zum Versatzwert hinzufügen.<br>
     *Auf 0 setzen, wenn der Basisversatz nicht vorhanden ist.<br>
     *
     * @param buf buffer
     */
    @Override
    public void decompile(ByteBuffer buf){

        /**
         *Offset ist 0 ist null
         */
        if(this.offset.get().intValue() == 0){
            return ;
        }

        /**
         *Merken Sie sich den aktuellen Offset
         */
        Integer old_offset = buf.position();

        /**
         *Versatzziel aufzeichnen
         */
        this.setOffset(this.baseObject.getOffset() + this.offset.get().intValue());

        /**
         *Fliegen Sie zum versetzten Ziel
         */
        buf.position(this.getOffset());

        /**
         *dekompilieren
         */
        this.reference.decompile(buf);

        /**
         *Versatz rückgängig machen
         */
        buf.position(old_offset);
    }


}

Es ist einfach (^ ω ^).

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

    // ...

    //Schreiben Sie es in den Rücken
    @PROPERTY(order = 23)
    public OFFSETW<Geso> geso= new OFFSETW<>(
            this.gesoOffset,
            this,
            new Geso()
    );

Wenn Sie es zusammen mit LIST verwenden, können Sie lesen, dass Offset ein Array ist.

    @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
    );

Bedingte Verzweigung

Zu solchen Zeiten gibt es auch eine Lesung.

public class R<Z extends DataTypeInterface> extends CompositeDataType {

    /**
     *Dekompilierung definieren
     * buf → (new,decompile) → instance
     */
    public Function<ByteBuffer, Z> decompiler;

    /**
     *Kompilierung definieren
     * buf,Z → (compile) →
     */
    public BiConsumer<ByteBuffer, Z> compiler;

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

    /**
     *Wirksamkeit|Ungültiges Urteil
     */
    public Supplier<Boolean> enable;

    /**
     *Inhalt
     */
    public Z content;

    /**
     * constructor
     * <p>
     *Aktivieren Sie, ob dieses Objekt aktiviert oder deaktiviert werden soll
     *Bitte übergeben Sie den Lambda-Ausdruck.
     *
     * @param compiler Funktion, die zur Kompilierungszeit ausgeführt wird
     * @Funktion zum Zeitpunkt der Dekompilierung des Parameterdekompilierers ausgeführt
     * @param enable     True:Wirksamkeit,False:Ungültig
     */
    public R(
            Function<ByteBuffer, Z> decompiler,
            BiConsumer<ByteBuffer, Z> compiler,
            Supplier<Boolean> enable) {

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

    /**
     * constructor
     * <p>
     *Aktivieren Sie, ob dieses Objekt aktiviert oder deaktiviert werden soll
     *Bitte übergeben Sie den Lambda-Ausdruck.
     *
     * @param Factory Instanziierung//ToDO:Ich möchte es für die Generierung von Generika ändern ...
     * @param enable     True:Wirksamkeit,False:Ungültig
     */
    public R(
            Supplier<Z> factory,
            Supplier<Boolean> enable) {

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

    /**
     * getter
     *
     * @Inhalt zurückgeben
     */
    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;
        }
    }
}

Es kann verwendet werden, wenn die Datenstruktur je nach Formatnummer unterschiedlich ist.


    @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
    );

Durch die Kombination von LIST, R und OFFSET können auch komplexe Datenstrukturen strukturell geschrieben werden.

Ende

Recommended Posts

Lesen Sie Binärdateien in Java 1
Lesen Sie Binärdateien in Java 2
Einfaches Lesen von Textdateien in Java (Java 11 & Java 7)
Lesen Sie JSON in Java
Lesen Sie die Standardeingabe in Java
Lesen Sie die Java-Eigenschaftendatei in C #
Lesen Sie CSV in Java (Super CSV Annotation)
Erstellen Sie Binärdaten variabler Länge in Java
TCP-Kommunikation (Socket-Kommunikation) in Java (ASCII, Binär)
Partisierung in Java
Änderungen in Java 11
Java-How zum Vergleichen von Bilddateien in Binärform
Janken in Java
Lesen Sie Felica mit RC-S380 (PaSoRi) in Java
Spielen Sie RAW-, WAV- und MP3-Dateien in Java ab
Lesen Sie die xlsx-Datei in Java mit Selenium
Umfangsrate in Java
FizzBuzz in Java
Lesen und Schreiben von GZIP-Dateien in Java
Lesen Sie eine Zeichenfolge in einer PDF-Datei mit Java
Hinzufügen, Lesen und Löschen von Excel-Kommentaren mit Java
[Java] Dateien in src / main / resources lesen
Importieren Sie Dateien derselben Hierarchie in Java
Interpreter-Implementierung durch Java
Machen Sie einen Blackjack mit Java
Janken App in Java
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
Verbinden Sie Arrays in Java
"Hallo Welt" in Java
Java-Eigenschaftendatei lesen
Aufrufbare Schnittstelle in Java
Kommentare in der Java-Quelle
Azure funktioniert in Java
Formatieren Sie XML in Java
Einfache HTML-Spezialchars in Java
Boyer-Moore-Implementierung in Java
Lesen Sie die Java HashMap-Quelle
Hallo Welt in Java
Verwenden Sie OpenCV mit Java
WebApi-Memorandum mit Java
Typbestimmung in Java
Befehle in Java ausführen (Ping)
Verschiedene Threads in Java
Zabbix API in Java
ASCII-Kunst in Java
Listen in Java vergleichen
POST JSON in Java
Fehler in Java ausdrücken
Erstellen Sie JSON in Java
Datumsmanipulation in Java 8
Was ist neu in Java 8?
Verwenden Sie PreparedStatement in Java
Was ist neu in Java 9,10,11
Parallele Ausführung in Java
Lesen Sie die Paketerfassung, die von tcpdump mit Java erhalten wurde
Wie kann ich IBM Mainframe-Dateien in Java eingeben / ausgeben?
Android-Laden Sie Bilddateien in den Azure Blob-Speicher in Java hoch
So lesen Sie Ihre eigene YAML-Datei (*****. Yml) in Java