Java: parsing unsigned binary data - java

I have a well defined binary data and I want to write Java API for it.
The file format is like
File Signature char[4] 4 bytes
File Source ID unsigned short 2 bytes
Header Size unsigned long 4 bytes
Max double 8 bytes
I am using DataInputStream for parsing the data. char is easy to parse, no problem. But unsigned cannot be parsed correctly. I know Java has no unsigned number. How do I convert it? (Please take unsigned long as example).
EDIT
Here is the code I worte:
File file = new File("lidar.las");
DataInputStream in= new DataInputStream(new FileInputStream(file));
in.skipBytes(6);
long read = (long) (in.readInt() & 0xFFFFFFFFL);
System.out.println("read " + read);
the output is
read 3288596480
my expected number is 1220
.I do not know the code that wrote this binary record, probably in c. All I want is writing a Java version to read data out.
Solved
I am not sure I can answer my own question. LOL
Anyway, Here is the solutions.
private static int getSignedInt( final int unsignedInt ){
ByteBuffer bb=ByteBuffer.allocate(1024*4);
bb.putInt(unsignedInt).flip();
int result =bb.order(ByteOrder.LITTLE_ENDIAN).getInt();
bb.clear();
return result;
}

DataInputStream reads bytes in Big Endian orientation, but check this out:
3288596480 = 0xC4040000
Reversing the bytes, you get 0x04C4 = 1220
You just have to read the values in Little Endian. The question about the sign turns out to be a red herring.

Just read them as short (2 bytes - Java) and int (4 bytes - Java) in your
Java code. You will not lose any information. If you need to output them later,
do a conversion so that you don't output signed numbers.
Given their names: File Source ID and Header Size I doubt you
will do any arithmetic operations on them. If you do, be careful.
Alternatively, you can read them both in long (8 bytes in Java),
and not worry about arithmetic operations as they will not cause issues.
Alternatively, you can read your values as byte arrays in Java,
and then transform them to the proper types in your Java code.
This is probably the most explicit and clean solution.
But it requires more coding.

Related

convert a binary string contains "0101010101001" for instance to actual binary file

The question sound dumb but it's like that
I had a binary string which contains a series of "0" and "1". If I store its as textfile it'll be huge since each character take about 8 bytes. But actually it should be much lesser since "0" or "1" is just actually 1 bit (1 byte/8). My question is how could to do that in Java?
Edited to avoid confuse
I've used an algorithm to encode all the data down to "0" and "1" sequence string. So 1 chunk of data could become quite big ... a few A4 paper of 1 string contains "0" and "1".
I'm stuck at the step to write down that string (which just "0" and "1") to an actual binary data file ... and it should be much lesser than just store down the text file which contains "0" and "1" as I assumed
Without talking implementation, a simple encoding scheme would be to store the decimal value of your binary string. That way, your computer will simply store the binary string as the bits in a number of the appropriate size (int/short/long/etc). Dunno if that would have the most elegant read/write process, though.
If you store in binary, it's 2 symbols you have.
If you store it in hexadecimal, it's 16 symbols you have.
More symbols, less chars in a text file.
What most people would do, if storage is importante for you, is to store your data in a binary format, and then compressing it (with DataOutputStream and ZipOutputStream).
Zip is pretty fast ;-)
update after the downvote (don't shoot the messenger - or at least explain your downvote... help us help you)
or you can use something like this
BigInteger bigInt = new BigInteger("100010001000100010001000100010011000011100010001000100010001000100010011000011111111111111111111111111111111111111111111111100",2);
BigDecimal bigDec = new BigDecimal(bigInt);
I've done more googling and below is the solution in my case... I've put down the solution there incase that someone would have the same question as mine :)
After read convert a binary string representation to a byte array in C#. I've decided to implement its Java version
int numOfBytes = binarytring.length() / 8;
byte[] bytes = new byte[numOfBytes];
//store it down as 1 byte (8bits) each
for(int i = 0; i < numOfBytes; ++i) {
// thanks https://stackoverflow.com/questions/6658388/why-java-throws-a-numberformatexception for help me out of the exception.
bytes[i] = (byte) (Integer.parseInt(encoded.substring(8 * i, (8 * i) + 8), 2) & 0xFF);
}
FileOutputStream fos = new FileOutputStream("outputfilename");
fos.write(bytes);
fos.close();

Java: How do I pass a int value higher than 128 in a Outputstream

I have an embedded system I have to integrate my Java application with. So far my work has been going well except now I have come across a problem where I need to send the number 160 as a bit. The OutputStream will only accept a byte[] and when I try to insert 160 (hex value 0xA0) into the array it is converted to -96. I understand that Java byte only supports signed values (-127 to 128), so I was wondering if anyone else has had a similar problem dealing with embedded systems and what their solution was.
Here is some sample code:
OutputStream oStream = mmSocket.getOutputStream();
byte attributeCode = (byte)0xA0;
byte[] buffer = new byte[bufferSize];
buffer[command.length + 1] = attributeCode;
oStream.write(buffer);
The embedded system is written in C and has been around for years, so no chance to have that changed.
The byte is exactly the same whether it's being treated as a signed byte with value -96, or an unsigned byte with value 160. This won't have any adverse effect on the C program on the other end; the only difference is what happens when you try printing out the value in Java.
In other words, you have no problem.

How to read file created by C++ program in java?

I have one file created by c++ program which is in encrypted format. I want to read it in my java program. In case of decryption of file contents, decryption algorithm is performing operations on byte[which is unsigned char-BYTE in c/c++]. I used same decryption algorithm which I have used in my c/c++ program. This algorithm contains ^, %, * and - operations on byte. But byte datatype of java is signed because of which I am facing problems in decryption. How can I read file or process read data with 1byte at a time which is unsigned?
thanks in advance.
byte b = <as read from file>;
int i = b & 0xFF;
Perform operations on i as required
The standard method InputStream.read() reads one byte and fits it into a int, so in practice it is an unsinged byte. There are no unsigned primitive data types in java, so the only approach is to fit it in an upper primitive.
That being said you should have no trouble performing encryption/decryption over data bytes read from the file, since the bytes are the same, no matter if they are interpreted as signed or unsigned (0xFF can be 255 or -1). You say the alghorithm contains "^, %, *", etc. That is an interpretation of raw bytes, taking into account a character encoding (that fits 8 bit per character I suppose). You should not perform encryption/decryption operations over other than raw bytes.
First, InputStream.read() returns an int but it holds a byte; it uses an int so -1 can be returned if the EOF is reached. If the int is not -1, you can cast it to byte.
Second, there are read() metods that allow storing the bytes directly in a byte[]
And last, if you are going to use the file as a byte[] (and it is not too big) maybe it would be interesting copying the data from FileInputStream and write it into a ByteArrayOutputStream. You can get the resulting byte[] from the late object (note: do not use the .read() method, use .read(byte[], int, int) for performance).
Since there is no unsigned primitive type in Java, I think what you can do is to convert signed byte into integer (which will virtually be unsigned because the integer will always be positive). You can follow the code in here: Can we make unsigned byte in Java for the conversion.

Similar functionality for java to struct for python

I have a program that I made in Python to find specific tags in TIFF IFD's and return the values. It was just a proof of concept thing in python, and now I need to move the functionality to java. I think I can just use the String(byteArray[]) constructor for the ASCII data types, but I still need to get Unsigned short (2 byte) and unsigned long (4 byte) values. I don't need to write them back to the file or modify them, all I need to do is get a Java Integer or Long object from them. This is easy in python with the struct and mmap classes, does any one know of a similar way in java? I looked at the DataInput class, but the readUnsignedLong method reads 8 bytes.
DataInputStream allows you to read shorts and longs. You should mask them with the appropriate bit mask (0xFFFF for short, 0xFFFFFFFF for 32 bit) in order to account for the difference between signed/unsigned types.
e.g.
// omits error handling
FileInputStream fis = ...;
DataInputStream stream = new DataInputStream(fis);
int short_value = 0xFFFF & stream.readShort();
long long_value = 0xFFFFFFFF & stream.readInt();
If you're sure that the data won't be towards the high end of the 2 byte field, or 4 byte field, you can forego the bit masking. Otherwise, you need to use a wider data type to account for the fact that unsigned values hold a larger range of values than their signed counterparts.
I looked at the DataInput class, but the readUnsignedLong method reads 8 bytes.
Java does not have unsigned types. It takes 4 bytes to make an int, and 8 bytes to make a long, unsigned or otherwise.
If you don't want to use DataInput, you can read the bytes into byte arrays (byte[]) and use a ByteBuffer to turn those byte values into ints and longs with left padding. See ByteBuffer#getInt() and ByteBuffer#getLong().
DataInput would be the preferred method. You can use readUnsignedShort for the two byte values. For the 4 byte values you'll have to use this workaround...
long l = dis.readInt() & 0xffffffffL;
You could use Javolution's Struct class which provides structure to regions of data. You set up a wrapper and then use the wrapper to access the data. Simples. Java really needs this super-useful class in its default classpath TBQH.
Preon Library is good to create struct in Java. I have tried Javolution's Struct but it was not help full my case. It is open source and very good library.

Facing problem from getting double and int value from binary file

Can anybody please tell me how to get double and int value from a binary file. I have tried alot but its giving me wrong values. Here is my code.
InputStream iStream = getApplicationContext().getResources().openRawResource(R.raw.map);
DataInputStream input;
input = new DataInputStream(iStream);
try {
double mapFileFormatVersionNumber, IntendedSoftwareVersion;
int DemoDays;
mapFileFormatVersionNumber =input.readDouble();
IntendedSoftwareVersion = input.readDouble();
DemoDays = input.readInt();
thanks in advance.
Tthere are a gazillion possible representations of integers and doubles. Hence you simply can't expect DataInputStream to be compatible with whatever bizarre binary format. You'll have to go through the specs of .AMF file format and roll your own conversion.
There is no difference in C++ and Java integer types. They are both signed 32-bit numeric types. However, its binary representation might be different depending on the byte order. For example, integer might be represented in file in little endian byte order and reading it assuming it is in big endian will result in wrong data. You might want to experiment with byte order if you don't know exactly how it is stored in the file. Take a look at ByteBuffer Java class, it supports different byte orders.

Categories