4

I am trying to find java equivalent for python's

struct.unpack('hccccc',raw)

https://docs.python.org/2/library/struct.html

How can I do this in a clean way?

2
  • 2
    Take a look at the ByteBuffer class. Commented Apr 26, 2015 at 14:48
  • 2
    AFAIK, there is no general equivalent of Python pack and unpack in Java. You could write one, but it is more common to pack (or unpack) specific structs with help of the ByteBuffer class. Unless it is a general question, please show the actual struct you are trying to unpack. Commented Apr 26, 2015 at 17:40

4 Answers 4

2

JBBP library can help in the case

byte [] data = new byte [] {1,2,3,4,5,6,7,8};
JBBPFieldStruct parsed = JBBPParser.prepare("short; ubyte [5];").parse(new ByteArrayInputStream(data));
System.out.println("short = "+parsed.findFieldForType(JBBPFieldShort.class).getAsInt());
System.out.println("array = "+Arrays.toString(parsed.findFieldForType(JBBPFieldArrayUByte.class).getArray()));
Sign up to request clarification or add additional context in comments.

Comments

1

This is how I handled to do that, I don't think/know if its the best way to do it but after many searchs I made my own, I might be making an actual and complete/clean api for doing that. if I do so I will post it here

x stands for ignore

c for char

s for string

b for byte

import java.nio.*;

public class struct{
    public static String[] unpack(char[] packet, byte[] raw){
        String[] result = new String[packet.length];

        int pos = 0;
        int Strindex = 0;

        for (int x = 0; x < packet.length; x++){

            char type = packet[x];
            if (type == 'x'){
                pos += 1;
                continue;
            }
            else if (type == 'c'){
                char c = (char) (raw[pos] & 0xFF);
                result[Strindex] = Character.toString(c);
                Strindex += 1;
                pos += 1;
            }
            else if (type == 'h'){
                ByteBuffer bb = ByteBuffer.allocate(2);
                bb.order(ByteOrder.LITTLE_ENDIAN);
                bb.put(raw[pos]);
                bb.put(raw[pos+1]);
                short shortVal = bb.getShort(0);
                result[Strindex] = Short.toString(shortVal);
                pos += 2;
                Strindex += 1;
            }
            else if (type == 's'){
                String s = "";

                while (raw[pos] != (byte)0x00){
                    char c = (char) (raw[pos] & 0xFF);
                    s += Character.toString(c);
                    pos += 1;
                }
                result[Strindex] = s;
                Strindex += 1;
                pos += 1;
            }
            else if (type == 'b'){
                Byte p = raw[pos];
                result[Strindex] = Integer.toString(p.intValue());
                Strindex += 1;
                pos += 1;
            }
        }
        return result;
    }
}

2 Comments

the first argument of the method char[] packet, can you explain a bit what it is.
I stuck with a similar task today, while I was tuning a murmur splitting hash function. So may be it will be useful for someone. For struct.unpack('q', msg)[0] you can use ByteBuffer.wrap(msg.getBytes()).order(ByteOrder.LITTLE_ENDIAN).getLong(); because "q" is 'long long' has size -(1<<63) to (1<<63)-1 (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807) in C++ (8 bytes) that is equal 'long' in Java (8 bytes) which has also "-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807"
0

This kind of operation is called "Serialization" in Java. See http://www.tutorialspoint.com/java/java_serialization.htm for a tutorial. Since serialization works with bytes, not characters, you might want to encode those bytes afterwards to get a printable string.

4 Comments

will it work to unpack for instance a python struct.pack(ed) data?
Most likely not; if you have to exchange data between a python program and a java program, I propose you use an open format like JSON that is well documented and understood in both worlds.
I m trying to decode packet of bytes from server, I can't change the way its built
Maybe you can use Jython to do the pack/unpack stuff, and keep the rest of the program in Java?
0

I stuck with a similar task today, while I was tuning a murmur splitting hash function. So may be it will be useful for someone. For struct.unpack('q', msg)[0] you can use ByteBuffer.wrap(msg.getBytes()).order(ByteOrder.LITTLE_ENDIAN).getLong(); because "q" is 'long long' has size -(1<<63) to (1<<63)-1 (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807) in C++ (8 bytes) that is equal 'long' in Java (8 bytes) which has also "-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.