Dies ist die Methode, die ich vor einiger Zeit entwickelt habe. Keine bewährte Methode. Ich mag Objektorientierung (˘ω˘)
Extrahieren Sie zuerst aus InputStream in Byte []. Informationen zum Herausnehmen finden Sie unter hier. Wickeln Sie es ein, um einen ByteBuffer (im Folgenden buf) zu erstellen.
byte[] bin = BinUtil.readAll(stream);
ByteBuffer buf = ByteBuffer.wrap(bin);
(long)buf.getInt()
In Java gibt es kein Vorzeichenkonzept (˘ω˘).
(long)buf.getInt () & 0xffffffffL
Sie müssen in der Lage sein, Daten von buf zu erhalten und zu erhalten. Bereiten Sie das Kompilieren und Dekompilieren vor. Die Gesamtlänge und der Versatz der Datengröße (später beschrieben) sind ebenfalls erforderlich.
public interface DataTypeInterface<T> {
Integer getOffset();
void setOffset(Integer offset);
Integer getSize();
void setSize(Integer size);
void decompile(ByteBuffer buf);
void compile(ByteBuffer buf);
/**
*Holen Sie sich untergeordnete Elemente
*
* @untergeordnetes Element zurückgeben
*/
T get();
/**
*Legen Sie untergeordnete Elemente fest
*
* @param item Untergeordnetes Element
*/
void set(T item);
}
Ein Typ, dessen interner Wert durch ein Java-Grundelement (z. B. String oder Long) dargestellt werden kann.
public abstract class SingleDataType<T> implements DataTypeInterface<T>{
/**
*Interner Wert
*/
private T value;
/**
*Objektstartposition im Bytestrom
*/
private Integer offset;
/**
*Objektbyte-Größe
*/
private Integer size;
@Override
final public Integer getOffset(){
return this.offset;
}
@Override
final public void setOffset(Integer offset){
this.offset= offset;
}
@Override
final public void setSize(Integer size) {
this.size = size;
}
@Override
public Integer getSize() {
return this.size;
}
public T get() {
return this.value;
}
public void set(T value) {
this.value = value;
}
}
Nur Zahlen.
abstract public class NumericDataType<T extends Number> extends SingleDataType<T> {
@Override
final public T get() {
return super.get();
}
@Override
public void set(T val) {
super.set(val);
}
abstract public void setNumber(Number val);
}
LONG Grundsätzlich lange gemacht (゜ ∀ ゜)
public class LONG extends NumericDataType<Long> {
@Override
public void decompile(ByteBuffer buf) {
this.setOffset(buf.position());
this.set((long)buf.getInt());
}
@Override
public void compile(ByteBuffer buf) {
this.setOffset(buf.position());
buf.putInt(this.get().intValue());
}
public LONG(ByteBuffer buf) {
this.decompile(buf);
this.setSize(4);
}
public LONG(Long value) {
this.set(value);
this.setSize(4);
}
/**
*Überprüfen Sie den Wert und legen Sie ihn fest
*
* @Parameterwert Wert
* @Der Bereich der IllegalArgumentException-Werte für Würfe ist-Wenn es weniger als 2147483648L oder mehr als 2147483647L ist
*/
@Override
public void set(Long value) throws IllegalArgumentException {
/*1*/
if ( value < -2147483648L || 2147483647L < value) {
throw new IllegalArgumentException("Der Wertebereich überschreitet die maximale und minimale Länge");
}
/*2*/
super.set(value);
}
@Override
public void setNumber(Number val) {
this.set(val.longValue());
}
}
In Java gibt es kein Konzept von struct (; ω;). Ich werde etwas mit Anmerkungen und Überlegungen machen
@Retention(RetentionPolicy.RUNTIME)
public @interface PROPERTY {
int order();
}
Zählen Sie die Felder durch Reflexion auf, extrahieren Sie nur die Felder mit den obigen Anmerkungen, sortieren Sie sie in der richtigen Reihenfolge und dekompilieren Sie sie in dieser Reihenfolge.
public abstract class CompositeDataType implements DataTypeInterface<DataTypeInterface>{
protected Integer offset;
@Override
final public Integer getOffset(){
return this.offset;
}
@Override
final public void setOffset(Integer offset){
this.offset= offset;
}
@Override
public Integer getSize(){
return this.OrderedProperties()
.entrySet()
.stream()
.mapToInt(item -> item.getValue().getSize())
.sum();
}
@Override
@Deprecated
public void setSize(Integer size) {
throw new RuntimeException("Sie können die Größe eines zusammengesetzten Objekts nicht festlegen.");
}
@Override
public void decompile(ByteBuffer buf){
this.setOffset(buf.position());
for (Map.Entry<String, DataTypeInterface> item: this.OrderedProperties().entrySet()) {
try {
item.getValue().decompile(buf);
}catch (IllegalArgumentException e){
System.out.println("Schlüssel("+ item.getKey() +")Untergeordnete Elemente von werden übersprungen");
e.printStackTrace();
}
}
}
@Override
public void compile(ByteBuffer buf) {
this.setOffset(buf.position());
for (Map.Entry<String, DataTypeInterface> item: this.OrderedProperties().entrySet()) {
try {
item.getValue().compile(buf);
}catch (IllegalArgumentException e){
System.out.println("Schlüssel("+ item.getKey() +")Untergeordnete Elemente von werden übersprungen");
e.printStackTrace();
}
}
}
protected Map<String,DataTypeInterface> OrderedProperties() {
List<Field> fields=new ArrayList<>();
Class c= this.getClass() ;
while(c != null){
fields.addAll(java.util.Arrays.asList(c.getDeclaredFields()));
c = c.getSuperclass();
}
List<Field> paramfields = fields
.stream()
.filter(f -> f.getAnnotation(PROPERTY.class) != null)
.collect(Collectors.toList());
Collections.sort(paramfields, (Field o1, Field o2) -> {
PROPERTY or1 = o1.getAnnotation(PROPERTY.class);
PROPERTY or2 = o2.getAnnotation(PROPERTY.class);
if (or1 != null && or2 != null) {
return or1.order() - or2.order();
}
return o1.getName().compareTo(o2.getName());
}
);
Map<String, DataTypeInterface> m = new LinkedHashMap<>();
try {
for (Field f : paramfields) {
f.setAccessible(true);
m.put(f.getName(), (DataTypeInterface) f.get(this));
}
} catch (IllegalAccessException e) {
throw new RuntimeException("Feld("+ fields.toString() +"Habe keinen Zugriff");
}
return m;
}
@Override
public DataTypeInterface get() {
return null;
}
@Override
public void set(DataTypeInterface item) {
}
}
Wenn Sie eine Datenstruktur haben, verwenden Sie diese wie folgt.
public class Version extends CompositeDataType {
@PROPERTY(order = 1)
public LONG version = new LONG();
@PROPERTY(order = 2)
public LONG subVersion = new LONG();
}
Sie können wiederverwenden, was Sie machen.
public class Data1 extends CompositeDataType {
@PROPERTY(order = 1)
public Version version = new Version();
@PROPERTY(order = 2)
public LONG data1 = new LONG();
}
Dies sind die Grundlagen, und 2 gilt für Array- und Offsetdaten.
Recommended Posts