在将Java转换为python时需要帮助

时间:2019-10-10 12:20:58

标签: python-3.x

消息可变长度指示器(VLI) 发送到BizSwitch或从BizSwitch发送的每条消息之前2个字节。这两个字节称为可变长度指示符。 字节1-2指示消息中的字节数(不包括前2个字节)。 2个字节代表16位无符号 网络字节顺序的整数。请注意,如果正在发送压缩消息,则该消息必须首先是 压缩后,才能确定其长度,然后再发送。 例如,假设您仅查看构成XML消息的文本(不包括2字节的标头) 一个特定的示例,然后您计算了字符,而它们恰好相加了299个字符。如果您采取了 科学计算器(例如Windows中的计算器),并且您在299中输入了“ Dec”(用于十进制),然后选择 “十六进制”,将显示的值是“ 12B”,表示与01 2B相同,这正是人们期望的值 查看消息的前两个字节是否已将消息转储到文件中,然后使用十六进制编辑器打开。 用于计算VLI的示例Java代码:

public byte[] wrap(byte[] msg) throws Exception {
    int len = msg.length;
    if (len > 65535) {
        throw new IllegalArgumentException("Exceeds 65535 bytes.");
    }
    byte firstByte = (byte)(len >>> 8);
    byte secondByte = (byte)len;
    ByteArrayOutputStream baos = new ByteArrayOutputStream(len + 2);
    baos.write(firstByte);
    baos.write(secondByte);
    baos.write(msg);
    return baos.toByteArray();
}

public byte[] unWrap(InputStream inputStream) throws Exception {
    int firstByte = inputStream.read();
    if (firstByte == -1) {
        throw new IOException("End of Stream while trying to read vli byte 1");
    }
    int firstByteValue = firstByte << 8;
    int secondByteValue = inputStream.read();
    if (secondByteValue == -1) {
        throw new IOException("End of Stream reading vli byte 2." );
    }
    int len = firstByteValue + secondByteValue;
    byte[] message = new byte[len];
    int requestLen;
    int readLen;
    int currentIndex = 0;
    while(true) {
        requestLen = len - currentIndex;
        readLen = inputStream.read(message, currentIndex, requestLen);
        if (readLen == requestLen) {
            break; // Message is complete.
        }
        // Either data was not yet available, or End of Stream.
        currentIndex += readLen;
        int nextByte = inputStream.read();
        if (nextByte == -1) {
            throw new IOException("End of Stream at " + currentIndex 
    );
        }
        message[currentIndex++] = (byte)nextByte;
    }
return message;
}

这是我的python转换代码

import io

def wrap(msg):
    msg_len = len(msg)
    if msg_len > 65535:
        return "Message exceeds 65535 bytes."

    first_byte = bytes(msg_len >> 8)

    second_byte = bytes(msg_len)
    # create an empty bytearray
    data_frame = bytearray()
    data_frame.extend(first_byte)
    data_frame.extend(second_byte)
    data_frame.extend(msg)
    return data_frame



def un_wrap(data_frame):
    data_frame = io.BytesIO(data_frame)

    first_byte = data_frame.read()
    try:
        first_byte == -1
    except:
        raise "End of Stream while trying to read vli byte 1"

    first_byte_value = first_byte << 8

    second_byte_value = data_frame.read(1)

    try:
        second_byte_value == -1
    except:
        raise "End of Stream reading vli byte 2."

    byt_len = first_byte_value + second_byte_value

    message = bytes(byt_len)

   request_len = 0
   read_len = 0
   current_index = 0
   while True:
        request_len = byt_len - current_index
        read_len = data_frame.read(message, current_index, request_len)
        if read_len == request_len:
            return "Message is complete."
        # Either data was not yet available, or End of Stream.
        current_index += read_len
        next_byte = data_frame
        if next_byte == -1:
            return  "End of Stream at " + current_index
        message.extend(bytes(next_byte))
    return message

这是越来越错误了

    first_byte_value = first_byte << 8
    TypeError: unsupported operand type(s) for <<: 'bytes' and 'int'

这是作为消息发送的内容,但是我需要两个字节来表示消息

<ipayMsg client="PESATRANS" term="00001" seqNum="0" time="2019-10-09 10:13:20 +0300">
   <elecMsg ver="2.44">
    <vendReq>
      <ref>749761497475</ref>
      <amt cur="KES">500</amt>
      <numTokens>1</numTokens>
      <meter>01450344831</meter>
      <payType>cash</payType>
    </vendReq>
 </elecMsg>
</ipayMsg>

2 个答案:

答案 0 :(得分:0)

在此行中,代码要对bytes对象进行左移。您需要先将其转换为int。

int_value = int.frombytes(bytes_value, byteorder="big")

文档:https://docs.python.org/3/library/stdtypes.html?highlight=from_bytes#int.from_bytes

答案 1 :(得分:0)

我已经找到答案了。我遇到的主要问题是假设python字节转换与java相同。 这是我的主要挑战所在。

public byte[] wrap(byte[] msg) throws Exception {
    int len = msg.length;
    if (len > 65535) {
        throw new IllegalArgumentException("Exceeds 65535 bytes.");
    }
    byte firstByte = (byte)(len >>> 8);
    byte secondByte = (byte)len;
    ByteArrayOutputStream baos = new ByteArrayOutputStream(len + 2);
    baos.write(firstByte);
    baos.write(secondByte);
    baos.write(msg);
    return baos.toByteArray();
}

对于这种java方法,我能够针对python提出这一点

def wrap(msg):
    msg_len = len(msg)
    if msg_len > 65535:
        return "Message exceeds 65535 bytes."
    my_list = []
    first_byte = msg_len >> 8
    second_byte = msg_len
    my_list.append(first_byte)
    my_list.append(second_byte)

    # create an empty bytearray
    data_frame = bytearray([x % 256 for x in my_list])
    data_frame.extend(msg)
    return data_frame

首先,我创建了一个元素列表,然后从2s补码转换为无符号整数,然后将它们添加到字节数组中,从而实现了这一目标。

data_frame = bytearray([x % 256 for x in my_list])

原来,我不需要第二种方法。谢谢