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?

kguest
  • 3,804
  • 3
  • 29
  • 31
Arnaud Aliès
  • 1,079
  • 13
  • 26
  • 2
    Take a look at the [ByteBuffer](http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html) class. – RealSkeptic Apr 26 '15 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](http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html) class. Unless it is a general question, please show the actual struct you are trying to unpack. – Serge Ballesta Apr 26 '15 at 17:40

4 Answers4

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()));
Igor Maznitsa
  • 833
  • 7
  • 12
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;
    }
}
Arnaud Aliès
  • 1,079
  • 13
  • 26
  • the first argument of the method char[] packet, can you explain a bit what it is. – ozmank Aug 02 '17 at 06:57
  • 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" – Yuri Glushenkov Jul 23 '19 at 16:08
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.

Erich Kitzmueller
  • 36,381
  • 5
  • 80
  • 102
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".