I'm trying to implement TMX files in Android and I was hoping someone could help. Based on the TMX guide, in order to get the GID's I have to
first base64 decode the string, then gunzip the resulting data if the compression attribute is set to "gzip" as in the above example. Finally, you can read 4 bytes at a time for each GID from the beginning of the data stream until the end.
I think I've figured out the base64 decoding and 'gunzip' but the result from the code below is 27,0,0,0 repeating. I think the output is supposed to be
(0,0) (1,0) (2,0) (3,0) (0,1) (1,1) (2,1) (3,1) (0,2) (1,2) (2,2) (3,2)
Thanks!
public static void main( String[] args )
{
String myString = "H4sIAAAAAAAAAO3NoREAMAgEsLedAfafE4+s6l0jolNJiif18tt/Fj8AAMC9ARtYg28AEAAA";
byte[] decode = Base64.decodeBase64(myString);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode);
GZIPInputStream gzipInputStream;
int read;
try
{
gzipInputStream = new GZIPInputStream(byteArrayInputStream);
InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader, 4);
while ( ( read = bufferedReader.read() ) != -1 )
{
System.out.println("read :" + read);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
Don't use Reader
s for anything but character data!
Use a DataInput
to read the integers. Decorate your GZIPInputStream
with a DataInputStream
and use readInt
.
If the ints are little-endian, you'll need to reverse the order of the bytes for the type. Java uses network byte order (big-endian). For integers, this can be done with Integer.reverseBytes.
You can print the hex values using:
System.out.format("%08x", (int) n);
How to read all int
values from a stream of arbitrary length:
One mechanism would be to use the available()
method which estimates the number of remaining bytes:
byte[] ints = {0x00, 0x00, 0x00, (byte) 0xFF,
(byte) 0xAA, (byte) 0xBB, (byte) 0xEE, (byte) 0xFF};
ByteArrayInputStream array = new ByteArrayInputStream(ints);
DataInputStream data = new DataInputStream(array);
while(data.available() > 0) {
int reversed = Integer.reverseBytes(data.readInt());
System.out.format("%08x%n", reversed);
}
In the general case, available()
is not a reliable mechanism. But you can augment your stream with a buffer to check data availability:
public static void main(String[] args) throws IOException {
byte[] ints = {0x00, 0x00, 0x00, (byte) 0xFF,
(byte) 0xAA, (byte) 0xBB, (byte) 0xEE, (byte) 0xFF};
ByteArrayInputStream array = new ByteArrayInputStream(ints);
BufferedInputStream buffer = new BufferedInputStream(array);
DataInputStream data = new DataInputStream(buffer);
while(hasData(data)) {
int reversed = Integer.reverseBytes(data.readInt());
System.out.format("%08x%n", reversed);
}
}
public static boolean hasData(InputStream in) throws IOException {
in.mark(1);
try {
return in.read() != -1;
} finally {
in.reset();
}
}