2009-09-03 76 views
1

我正在编写一个网络应用程序,它发送和接收很多不同种类的二进制数据包,并且我试图尽可能简单地向我的应用程序添加新的数据包。读取/写入二进制结构:如何简化此代码?

现在,我创建了一个Packet类,并为每个不同类型的数据包创建它的子类。然而,它并不像看起来那么干净。我已经结束了这样的代码:

static class ItemDesc extends Packet { 
    public final int item_id; 
    public final int desc_type; 
    public final String filename; 
    public final String buf; 

    public ItemDesc(Type t, int item_id, int desc_type, String filename, String buf) { 
     super(t); // sets type for use in packet header 
     this.item_id = item_id; 
     this.desc_type = desc_type; 
     this.filename = filename; 
     this.buf = buf; 
    } 

    public ItemDesc(InputStream i) throws IOException { 
     super(i); // reads packet header and sets this.input 
     item_id = input.readInt(); 
     desc_type = input.readByte(); 
     filename = input.readStringWithLength(); 
     buf = input.readStringWithLength(); 
    } 

    public void writeTo(OutputStream o) throws IOException { 
     MyOutputStream dataOutput = new MyOutputStream(); 
     dataOutput.writeInt(item_id); 
     dataOutput.writeByte(desc_type); 
     dataOutput.writeStringWithLength(filename); 
     dataOutput.writeStringWithLength(buf); 
     super.write(dataOutput.toByteArray(), o); 
    } 
} 

什么困扰我关于这种方法是代码重复 - 我重复数据包结构四次。我很乐意避免这种情况,但我看不到一个合理的方法来简化它。

如果我在Python写我会创造一切可能的字段类型的字典,然后像这样定义新的数据包类型:

ItemDesc = [('item_id', 'int'), ('desc_type', 'byte'), ...] 

我想,我可以做任何功能性语言类似的东西。但是,我无法看到采用这种方法处理Java的方法。

(也许我只是太迂腐,或者我习惯了函数式编程和编写代码编写代码,这样我就可以避免任何重复:))

预先感谢您的任何建议。

+0

它看起来不错。我怀疑你可以减少代码。 – ChaosPandion 2009-09-04 00:06:08

回答

1

我同意@silky你目前的代码是一个很好的解决方案。有点重复(虽然没有重复)的代码不是一件坏事,IMO。

如果你想更蟒蛇般的解决方案,您可以:

  1. 具有某种保序地图结构的更换ItemDesc的成员属性,使用通用writeTo方法遍历做到系列化地图。您还需要为每个属性添加getter,并替换现有字段的所有用法。
  2. 用Properties对象替换成员属性,并使用Properties序列化代替二进制写入。
  3. 编写一个通用的writeTo方法,该方法使用Java反射访问成员属性及其类型并对它们进行序列化。

但是在所有3种情况下,代码会比当前的“丑陋”代码更慢,更复杂并且可能更脆弱。我不会这样做。

0

对我来说似乎没关系。您可能只想将数据包的一些“常规”部分提取到继承链中,因此您不需要阅读它们,但是重复格式与您一样有意义,因为您已经获得了一个从构造函数中读取原始数据,从流中读取数据并写入。我没有看到任何错误。

0

我不知道,你可以在Java的做到这一点,但也许你可以重用构建函数中的一个:

public ItemDesc(InputStream i) throws IOException { 
    super(i); // reads packet header and sets this.input 

    this(input.readInt(), input.readByte(), input.readStringWithLength(), input.readStringWithLength()); 
} 

是“这”指本类构造函数的调用,whtever语法可能。

+0

这并没有解决问题 - 我仍然需要重复数据包结构来写入数据包。 – mik01aj 2009-11-08 21:44:28