Android

时间:2015-09-30 05:39:04

标签: java android

我正在尝试为

编写toString()一个稍高级的课程

为了完成我想要做的事情,我需要能够在执行toString()时更改某些变量的分配。

为了简单起见,我将删除一些东西,除了允许它工作的东西。

public enum PacketElementType {
    NONE((byte)0, "None"),
    BYTE((byte)1, "Byte"),
    SHORT((byte)2, "Short"),
    INT((byte)3, "Int"),
    LONG((byte)4, "Long"),
    FLOAT((byte)5, "Float"),
    STRING((byte)6, "String"),
    BIN((byte)7, "Bin");

    private final byte typeValue;
    private final String typeName;

    PacketElementType(byte type, String name)
    {
        this.typeValue = type;
        this.typeName = name;
    }

    public String getTypeName() {
        return typeName;
    }

    public byte getTypeValue() {
        return typeValue;
    }
}

public class Packet {
    private final int DEFAULT_SIZE = 1024 * 2;
    private final int ADD_SIZE = 1024;

    private byte[] _buffer = new byte[1];
    private int _ptr = 0;
    private int _bodyStart = 0;
    private int _elements, _bodyLen = 0;

    private int op;
    private long id;

    public Packet(int op, long id) {
        setOp(op);
        setId(id);

        _buffer = new byte[DEFAULT_SIZE];
    }

    public int getOp() {
        return op;
    }

    public void setOp(int op) {
        this.op = op;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public PacketElementType peek() {
        int pie = _ptr;
        if (pie + 2 > _buffer.length)
            return PacketElementType.NONE;
        return PacketElementType.values()[_buffer[_ptr]];
    }

    protected Packet putSimple(PacketElementType type, byte... val) {
        int len = val.length + 1;
        this.ensureSize(len);

        _buffer[++_ptr] = type.getTypeValue();
        System.arraycopy(val, 0, _buffer, _ptr, val.length);
        _ptr += val.length;

        _elements++;
        _bodyLen += len;

        return this;
    }

    public Packet putByte(byte val) {
        return this.putSimple(PacketElementType.BYTE, val);
    }

    public Packet putByte(boolean val) {
        return this.putByte(val ? (byte) 1 : (byte) 0);
    }

    public byte getByte() throws Exception {
        if (this.peek() != PacketElementType.BYTE)
            throw new Exception("Expected Byte, got " + this.peek().getTypeName() + ".");

        _ptr += 1;
        return _buffer[++_ptr];
    }

    protected void ensureSize(int required) {
        if (_ptr + required >= _buffer.length) {
            byte[] b = new byte[_buffer.length + Math.max(ADD_SIZE, required * 2)];
            System.arraycopy(_buffer, 0, b, 0, _buffer.length);
            _buffer = b;
        }
    }

    private boolean isValidType(PacketElementType type)
    {
        return (type.getTypeValue() >= PacketElementType.BYTE.getTypeValue() && type.getTypeValue() <= PacketElementType.BIN.getTypeValue());
    }

    protected String toStringHack()
    {
        StringBuilder result = new StringBuilder();
        int prevPtu = _ptr;
        _ptr = _bodyStart;

        try {
            result.append(String.format("Op: %1$08d %3$s, Id: %2$016d\r\n", this.getOp(), this.getId(), Op.getName(this.getOp())));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return result.append("Failed to convert packet to string").toString();
        }

        PacketElementType type;
        for (int i = 1; (this.isValidType(type = this.peek()) && _ptr < _buffer.length); ++i)
        {
            if (type == PacketElementType.BYTE)
            {
                byte data = 0;
                try {
                    data = getByte();
                } catch (Exception e) {
                    e.printStackTrace();
                    result.append("Failed to parse element at position ").append(i);
                    continue;
                }
                result.append(String.format("%1&03d [%2$s] Byte   : %3$s", i, String.format("%1$016d", data), data));
            }
        }

        return result.toString();
    }

    //TODO: toString
    @Override
    public String toString()
    {
        return toStringHack();
    }
}


public class Op {

    public class Msgr
    {

    }

    public static String getName(int op) throws IllegalAccessException {
        for (Field field : Op.class.getFields())
        {
            if ((int)field.get(null) == op)
                return field.getName();
        }

        for (Field field : Op.Msgr.class.getFields())
        {
            if ((int)field.get(null) == op)
                return field.getName();
        }

        return "?";
    }
}

debug view close [debug view far (after some instructions) 2

调试时,_ptr未设置toString(),未调试时,_ptr未在putSimple()中设置。

我离我的头发很近,拜托,谢谢,如果你能帮助我,我真的很高兴!请再次感谢你!

要测试此错误,请查看以下示例:

Packet p = new Packet(1, 10001).putByte(true);
Toast.makeText(this, p.toString(), Toast.LENGTH_LONG).show();

对我来说,我首先在内置的测试类中抛出它,然后在主活动的onCreate中尝试它。

toString()只返回Op和Id,因为_ptr处于,peek()将尝试读取从该位置开始而不是0的字节,它将找到我们的1字节

修改

似乎...... _ptr = _bodyStart;被视为除了作业以外的其他内容,这可能吗?

2 个答案:

答案 0 :(得分:1)

您看到的结果是正确的 - 调试器在评估之前向您显示这些变量。在此之后添加一行(如日志或smth。)并在其上设置断点。

答案 1 :(得分:1)

所以事实证明我只缺少一小部分小细节.....根本不是很小,我为之前没有看到这个而道歉。由于toString()调用格式错误以及String.format()ptr完成后未能将toString()设置回原始值,result.append(String.format("%1&03d [%2$s] Byte : %3$s", i, String.format("%1$016d", data), data)); 会失败。

%1

应该是(我&之后$而不是String hello = String.format("%1$03d [%2$s] Byte : %3$d\r\n", i, StringUtils.leftPad(String.format("%02X", data), 16, '.'), (int) data);

ptr = prevPtu;

在返回字符串之前,我需要执行以下操作

{{1}}

,发生以下情况:

COrrectly Working picture :D