关于java:如何在不创建新对象LibGDX的情况下使用Input/OutputStream读取/写入数据

How to use Input/OutputStream to read/write data without creating new objects LibGDX

我正在使用 LibGDX,自从我开始使用这个库以来,我一直遵循他们的建议,并且从未在运行时使用池和成员变量创建新对象以防止触发垃圾收集器。但是,在网络方面,我很难在不创建新的 Data(Input/Output)Stream 对象的情况下从 InputStream 读取(并从 OutputStream 写入)。

我需要一种方法使这些对象可重复使用,以防止在每次收到玩家移动时创建新对象。
或者,我需要一种在不使用此对象的情况下从 Input/OutputStream 读取整数、浮点数和 UTF 字符串的方法。

目前,我的低效代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * Represents a packet sent from client to server
 * Used when a client sends a chat message to the server
 * Created by winter on 25/03/16.
 */

public class PacketInChat extends Packet
{
    private String message;

    public PacketInChat() { }

    public PacketInChat(String message) {
        this.message = message;
    }

    @Override
    public void readFrom(InputStream stream) throws IOException {
        message = new DataInputStream(stream).readUTF(); //problem here
    }

    @Override
    public void writeTo(OutputStream stream) throws IOException {
        new DataOutputStream(stream).writeUTF(message); //problem here
    }

    //getters/setters for fields
}

我还通过读取它的名称来检测它是哪个套接字,所以这里也有问题:

1
2
3
String packetName = new DataInputStream(socket.getInputStream()).readUTF();
Packet packet = Pools.obtain((Class<? extends Packet>)Class.forName("package me.winter.socialplatformer.server.packet." + packetName));
packet.readFrom(socket.getInputStream());

有什么想法吗?谢谢

编辑:EJP 指出我无法在不创建新对象的情况下从 DataInputStream 中读取字符串,因此我的示例几乎没用。我设法在没有 DataInputStream 的情况下从字节中读取整数和浮点数,并且可以使用 StringBuffer(或 StringBuilder)读取字符串,但是我必须进行这种优化的唯一重要情况是在 Player 移动数据包中,它不包含任何字符串。我还通过读取 id 而不是名称来从枚举中获取数据包类型,因此不再有问题。

但是,我仍然对如何重用 DataInputStream/DataOutputStream 感到好奇,并会接受一个可以解释我如何做到这一点的答案。


根据我的评论,只需使用 WeakHashMap<InputStream, DataInputStream>,输出流也类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class PacketInChat extends Packet
{
    private Map<InputStream, DataInputStream> map = new WeakHashMap<>();
    private String message;

    public PacketInChat() { }

    public PacketInChat(String message) {
        this.message = message;
    }

    @Override
    public void readFrom(InputStream stream) throws IOException {
        DataInputStream din;
        synchronized (map)
        {
            if ((din = map.get(stream)) == null)
            {
                map.put(din, in = new DataInputStream(stream));
            }
        }
        message = din.readUTF();
    }

}

和输出类似。 WeakHashMap 将确保数据流在其package的流消失时被释放。

或者只是重组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class PacketInChat
{
    DataInputStream din;
    DataOutputStream dout;

    public PacketInChat(InputStream in, OutputStream out)
    {
        this.din = new DataInputStream(in);
        this.dout = new DataOutputStream(out);
    }

    public String readMessage() throws IOException { return din.readUTF(); }
    public int readInt() throws IOException { return din.readInt(); }
    // etc
    public void writeMessage(String msg) throws IOException
    {
        dout.writeUTF(msg);
    }
    // etc
}

这样您就可以为每个输入/输出流对创建其中一个,并将它们保存在某处的地图中。