2016-06-15 8 views
0

ich verschachtelte Sprache „C“ Datenstrukturen wie diese Deserialisieren:einen Byte-Stream in eine Java-Klasse

struct xyz { 
    char a[256]; 
    char b[1024]; 
} XYZ; 

struct abc { 
    unsigned char dat1[1024]; 
    int dat2; 
} ABC; 

struct def { 
    int x; 
    int y; 
    int z; 
} DEF; 

struct tot { 
    XYZ p1; 
    ABC p2[45]; 
    DEF p3[17]; 
} TOT; 

TOT tot; 

Nach TOT bevölkern, ich schreibe es so in eine Datei im C-Programm.

fwrite ((char *) & tot, 1, sizeof (TOT), Datei);

Jetzt muss ich die gleiche Datei wieder mit einem JAVA-Programm lesen und die gleichen C-Datenstrukturen wie entsprechende JAVA-Klassen für ANDROID neu erstellen.

Also mache ich Klassen, die oben wie die C-Strukturen aussehen, enthalten diese Klassen nur die Datenelemente und keine Methoden wie diese

class XYZ { 
    byte a[]=new byte[256]; 
    byte b[]=new byte[1024]; 
} XYZ; 

class ABC { 
    byte dat1[1024]; 
    int dat2; 
}; 

class DEF { 
    int x; 
    int y; 
    int z; 
}; 

class TOT { 
    XYZ p1; 
    ABC p2[45]; 
    DEF p3[17]; 
}; 

ich weiß, gibt es einige Syntaxfehler in den Klassen oben, aber ich hoffe, dass Sie bekomme eine Vorstellung.

Also wie kann ich alle Bytes aus der Datei lesen und diese verwenden, um alle diese verschachtelten JAVA-Klassenobjekte zu erstellen, wie Sie oben sehen, um die ursprünglichen C-Strukturen an der Spitze zu entsprechen?

Ich denke, es ist wie eine De-Serialisierung in JAVA (Android), aber der Serializer war ein C-Programm mit fwrite.

Es wäre so schwer, die Bytes einzeln aus der Datei zu lesen und die JAVA-Klassenobjekte manuell einzugeben, und dabei die verschiedenen Größen der Datentypen und Byte-Reihenfolgen von Windows C zu JAVA zu berücksichtigen Gibt es einen schnelleren Weg?

Leider sind die binären Daten, die bereits in die Datei mit C geschrieben und können nicht geändert werden, so hat ich ein Java-Programm zu schreiben, es wieder zu bekommen und diese Klasse Objekte daraus zu machen.

vielen dank für alle ideen!

+1

Bad Wahl eines Serializer. Verwenden Sie einen geeigneten, der ein plattformunabhängiges Format erzeugt. C erzwingt kein bestimmtes Layout für solche Strukturen, abgesehen von einigen sehr grundlegenden Anforderungen. – Olaf

+0

Ja stimmt, es ist nicht plattformunabhängig, aber es ist sehr schwer das Dateiformat im Moment zu ändern. – programmer3

+0

Wie mache ich einen geeigneten plattformunabhängigen Serializer in C, der in JAVA deserialisiert werden kann, um die verschachtelten JAVA-Klassen neu zu erstellen? – programmer3

Antwort

0

Sie können dies relativ einfach mit einem DataInputStream, bereitgestellten der Absender ist Netzwerk-Byte-Reihenfolge verwenden.

Wenn nicht, kann ich nur vorschlagen, dass Sie das C-Ende wegwerfen und wieder mit einem richtig definierten Anwendungsprotokoll beginnen. Wie ich hier sage, verwenden Sie nicht structs als Anwendungsprotokolle. Verwenden Sie Anwendungsprotokolle als Anwendungsprotokolle. Sie könnten zum Beispiel XDR betrachten.

+0

Danke für die Kommentare Olaf und EJP, wo ist das XDR-Beispiel? – programmer3

+1

Ich wiederhole es. ** Sie ** könnten XDR * zum Beispiel betrachten. * – EJP

+0

Wie ich die Frage verstehe, ist das Format vollständig implementierungsspezifisch. Weder Endianess noch Padding oder Encoding sind tatsächlich festgelegt. Aber dein Vorschlag ist gut. Es ist jedoch egal, welches Protokoll zu verwenden ist, solange es gut definiert ist. – Olaf

0

Der einfachste Weg, um die Strukturen in dem Speicher ist die Verwendung von ByteBuffer, zu laden, da Sie die Endian-Reihenfolge steuern können.

Im folgenden Beispiel wird zuerst die gesamte Datei in den Speicher geladen, bevor die Java-Objekte erstellt werden. Da die Java-Objekte noch mehr Speicher benötigen, sollte dies kein großes Problem darstellen.

Die Felder der Klassen auch wurden korrigiert.

Der Code annimmt Little-Endian-Ordnung (x86-Prozessor), und dass die C int 4 Byte war, d.h. Zuordnung zu einem Java int.

ByteBuffer buffer = ByteBuffer.wrap(Files.readAllBytes(Paths.get("C:/fileFromC.bin"))); 
buffer.order(ByteOrder.LITTLE_ENDIAN); // if C code was run on x86 processor 
TOT tot = TOT.load(buffer); 
class XYZ { 
    byte a[] = new byte[256]; 
    byte b[] = new byte[1024]; 
    static XYZ load(ByteBuffer buffer) { 
     XYZ xyz = new XYZ(); 
     buffer.get(xyz.a); 
     buffer.get(xyz.b); 
     return xyz; 
    } 
} 
class ABC { 
    byte[] dat1 = new byte[1024]; 
    int dat2; 
    static ABC load(ByteBuffer buffer) { 
     ABC abc = new ABC(); 
     buffer.get(abc.dat1); 
     abc.dat2 = buffer.getInt(); 
     return abc; 
    } 
} 
class DEF { 
    int x; 
    int y; 
    int z; 
    static DEF load(ByteBuffer buffer) { 
     DEF def = new DEF(); 
     def.x = buffer.getInt(); 
     def.y = buffer.getInt(); 
     def.z = buffer.getInt(); 
     return def; 
    } 
} 
class TOT { 
    XYZ p1; 
    ABC[] p2 = new ABC[45]; 
    DEF[] p3 = new DEF[17]; 
    static TOT load(ByteBuffer buffer) { 
     TOT tot = new TOT(); 
     tot.p1 = XYZ.load(buffer); 
     for (int i = 0; i < tot.p2.length; i++) 
      tot.p2[i] = ABC.load(buffer); 
     for (int i = 0; i < tot.p3.length; i++) 
      tot.p3[i] = DEF.load(buffer); 
     return tot; 
    } 
} 
+0

Tut mir leid, ich bin nicht mit Java vertraut, aber wie garantieren Sie identische Kodierung, Endianess und Padding? Lassen Sie die Breite der Datentypen mit. das kann sich unterscheiden. C erzwingt keine spezifische Breite für z.B. 'int', noch' char'. – Olaf

+1

@Olaf Die 'Garantie' liegt natürlich in den Händen des Programmierers. Endianness wird durch 'buffer.order (ByteOrder.LITTLE_ENDIAN)' und 'BIG_ENDIAN' ist ebenfalls verfügbar. Padding wird durch 'get()' für die Füllbytes implementiert und weggeworfen. Die Integer-Größe wird gesteuert, indem Sie 'getShort()', 'getInt()' oder 'getLong()' aufrufen. – EJP

+1

@Olaf Wenn Sie den letzten Abschnitt meiner Antwort lesen, würden Sie sehen, dass ich 2 Annahmen über die Kodierung erwähnt habe, d. H. Endianness und Größe von "int". Sie haben Recht, ich habe Padding nicht erwähnt, da alle Byte-Arrays eine Größe haben, die ein Vielfaches von 4 ist, also sind alle Ints auf 4-Byte-Grenzen, und ohne 8-Byte-Member sind auch die Strukturen. Ergo, keine Polsterung irgendwo. – Andreas

Verwandte Themen