byte getting read wrong from file? - java

So, I am trying to store 3 longs to a file, but it will a lot of data so I convert them to byte arrays and save them. My current method for saving them:
try (FileOutputStream output = new FileOutputStream(path, true)) {
//Put the data into my format
byte[] data = new byte[24];
main.getLogger().log(Level.INFO, "Saving most sig bits");
System.arraycopy(ByteUtils.longToBytes(uuid.getMostSignificantBits()), 0, data, 0, 8);
System.arraycopy(ByteUtils.longToBytes(uuid.getLeastSignificantBits()), 0, data, 8, 8);
System.arraycopy(ByteUtils.longToBytes(player.getTokens()), 0, data, 16, 8);
//Write data in the format
output.write(data);
}
longToBytes method:
private static ByteBuffer buffer = ByteBuffer.allocate(8);
public static byte[] longToBytes(long x) {
System.out.println(x);
buffer.putLong(0, x);
return buffer.array();
}
The byte array gets saved to the file, but the first byte gets truncated. the print statement in longToByes prints 8 three times.
The original longs are:
-9089798603852198353, -5339652910133477779, 5992
If I print the byte array I get:
-127, -38, -116, 84, 97, -116, 78, 47, -75, -27, -67, -8, 11, -100, -2, 109, 0, 0, 0, 0, 0, 0, 23, 104 (24 bytes)
But in the file I see:
ÚŒTaŒN/µå½ø(VT symbol)œþm(nul)(nul)(nul)(nul)(nul)(nul)(etb)h
which is 23 bytes (the first box doesn't show in notepad++)
but if I read it using
bytes = IOUtils.toByteArray(new FileReader(file));
I see:
64, -38, -116, 84, 97, -116, 78, 47, -75, -27, -67, -8, 11, -100, -2, 109, 0, 0, 0, 0, 0, 0, 23, 104 (24 bytes)
-127 is replaced with 64 somehow.
I concat the byte with "" to print it btw.

Do not use FileReader to read raw bytes from file. Use FileInputStream instead.
The problem with FileReader is that it reads chars, not bytes, from the file, by trying to decode the bytes using some character encoding (the default one if none was given).
bytes = IOUtils.toByteArray(new FileInputStream(file));
Alternatively you can use DataOutputStream to write long directly to an output stream and use DataInputStream to read from an input stream.
try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
out.writeLong(uuid.getMostSignificantBits());
out.writeLong(uuid.getLeastSignificantBits());
out.writeLong(player.getTokens());
}
try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
long uuidMSB = in.readLong();
long uuidLSB = in.readLong();
long tokens = in.readLong();
}

Related

Java store and read byte array from property file yaml

I am working on an application that reads data from a database. There are already encrypted entries in the DB. I have the key as a byte array and want to load it from a yaml file.
Is there a way i can populate an array like this
private static final byte[] iv = { 13, -11, -88, 20, -110, 113, -2, -8, -15, -99, -23, -10, -10, -74, 1, 11 }
Directly from a yaml file?
yaml file:
iv: 13,-11,-88
Since I cannot autowire the class where I need to use the key, i cannot use #value annotation (from my understanding). So I was looking to use a util class like so:
public static byte[] getKeyFor(Class type) {
return context.getEnvironment().getProperty("iv");
}
Below should work:
application.yml:
iv: 12,32,12,32
In the class where you want the values, bind it like below:
#Value("${iv}") byte[] iv;
You got some string with your byte data in String format.
String iv = someCall(); //"13, -11, -88, 20, -110, 113, -2, -8, -15, -99, -23"
String[] byteStrings = iv.split(",");
byte[] byteData = new byte[byteStrings.length];
for (int i = 0; i < byteData.length; i++){
byteData[i] = Byte.parseByte(byteStrings[i], 8);
}

Apache codec base64 encode/decode - not getting expected result

I did a POC using apache codec base64 library, where I encrypted a string using SHA. (This can be ignored).
Step 1 - I printed byte array for that string.
Step 2 - Encoded the byte array and printed its value.
Step 3 - Decoded the encoded value and printed it.
public static void main(String[] args)
{
MessageDigest messageDigest = null;
String ALGORITHM = "SHA";
try
{
messageDigest = MessageDigest.getInstance(ALGORITHM);
byte[] arr = "admin1!".getBytes();
byte[] arr2 = messageDigest.digest(arr);
System.out.println(arr2);
String encoded = Base64.encodeBase64String(arr2);
System.out.println(encoded);
byte[] decoded = Base64.decodeBase64(encoded);
System.out.println(decoded);
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
}
Expected result : Step 1 and Step 3 should produce same output. But I am not getting that.
Output :
[B#5ca801b0
90HMfRqqpfwRJge0anZat98BTdI=
[B#68d448a1
Your program is all good and fine. Just one mistake.
System.out.println(byteArray); prints hashCode of byte array object. (Note: Arrays are object in Java not primitive type)
You should use System.out.println(Arrays.toString(byteArray)); instead and you will get same value for both steps 1 and 3.
As per javadocs Arrays.toString(byte[] a) returns a string representation of the contents of the specified array.
Your code after changes will be :
public static void main(String[] args)
{
MessageDigest messageDigest = null;
String ALGORITHM = "SHA";
try
{
messageDigest = MessageDigest.getInstance(ALGORITHM);
byte[] arr = "admin1!".getBytes();
byte[] arr2 = messageDigest.digest(arr);
System.out.println(Arrays.toString(arr2));
String encoded = Base64.encodeBase64String(arr2);
System.out.println(encoded);
byte[] decoded = Base64.decodeBase64(encoded);
System.out.println(Arrays.toString(decoded));
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
}
and output will be :
[-9, 65, -52, 125, 26, -86, -91, -4, 17, 38, 7, -76, 106, 118, 90, -73, -33, 1, 77, -46]
90HMfRqqpfwRJge0anZat98BTdI=
[-9, 65, -52, 125, 26, -86, -91, -4, 17, 38, 7, -76, 106, 118, 90, -73, -33, 1, 77, -46]
Note value of byte array is same.

InputStream.read() is either missing or adding a value in my buffer - How come?

I've created the following procedure in the run() method of the ConnectedThread taken from the BluetoothChat sample.
// Read from the InputStream
byte[] buffer = new byte[16];
int offset = 0;
while(buffer.length-offset != 0)
{
int bytesRead += mmInStream.read(buffer, offset, buffer.length-offset);
offset += bytesRead;
}
// Do stuff with the contents of the buffer
The buffer is loaded in with 16 bytes gradually as expected but for some reason at the 10th byte in the array a 0 is inserted and shifts the remaining part of the package(and as such corrupting the entire package)
Here is an example of what is happening
The following is sent from the other client :
[-11, 126, -16, -30, -92, 110, -26, 13, 22, 91, -31, 32, 54, -125, -112, 45]
This is what I receive :
[-11, 126, -16, -30, -92, 110, -26, 13, 22, 91, 0, -31, 32, 54, -125, -112]
As you can see, an extra 0 is pushed in as the 10th byte and the rest of the package is shifted to the right(cutting off the last byte)
As part of the debugging process we tried having a breakpoint at bytesRead += mmInStream.read(buffer, offset, buffer.length-offset) and to our surprise the entire original message was received. What gives?
How does the "break" in reads correct this issue? What am I doing wrong or not understanding?
Probably you meant
bytesRead = mmInStream.read(buffer, offset, buffer.length-offset);
offset += bytesRead;
instead of
bytesRead += ...
Throw it all away and use DataInputStream.readFully().

Convert short array to signed byte array in Java

As input I'm getting a short array like {20, 250, 12, 255}.
I need to convert it to byte[] {20,-6,12,-1}
I tried to use ByteBuffer:
short[] data = {20, 250, 12, 255};
ByteBuffer dbuf = ByteBuffer.allocate(data.length*2);
dbuf.asShortBuffer().put(data);
byte[] array = dbuf.array();
But the output formatted as:
{0,20,0,-6,0,12,0,-1}
How to get signed byte array like {20,-6,12,-1}?
Just simply use byte[] which is signed because byte in java is singed. There is no need to convert to short if you want output like that.
Below is just conversion mechanism if you cant.
Loop over the array and do a down cast.
short[] data = { 20, 250, 12, 255 };
byte[] bytes = new byte[data.length];
int count = 0;
for (short i : data) {
bytes[count++] = (byte)i;
}
System.out.println(Arrays.toString(bytes));
Output:
[20, -6, 12, -1]

Reading a wav file java vs matlab

I am trying to read data of a .wav file both in java and matlab and save as an array of bytes.
In java the code looks as follows:
public byte[] readWav2(File file) throws UnsupportedAudioFileException, IOException {
AudioFormat audioFormat;
AudioInputStream inputAIS = AudioSystem.getAudioInputStream(file);
audioFormat = inputAIS.getFormat();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Read the audio data into a memory buffer.
int nBufferSize = BUFFER_LENGTH * audioFormat.getFrameSize();
byte[] abBuffer = new byte[nBufferSize];
while (true) {
int nBytesRead = inputAIS.read(abBuffer);
if (nBytesRead == -1) {
break;
}
baos.write(abBuffer, 0, nBytesRead);
}
byte[] abAudioData = baos.toByteArray();
return abAudioData;
}
In matlab I am using the wavread function:
[Y, FS] = wavread('sound.wav', 'native');
But the results I am getting are different.
In java the first 20 bytes:
53, 0, 19, 0, -71, -1, -80, -1, -99, -1, 10, 0, 87, 0, -69, -1, 123, -1, -77, -1
In matlab:
53, 19, -71, -80, -99, 10, 87, -69, -133, -77, 38, 143, 13, -100, 39, 45, -52, -83, -82, 56
Why every second byte in java is 0 or -1 where in matlab there isn't? Even though I skip the 0's and -1's where in java there is 123 for matlab there is -133? Why is it different?
Java is returning you 16-bit signed PCM data. Since each sample is 16 bits and a byte holds 8 bits, each sample spans two bytes in Java. What Matlab returns you is an array of the 16-bit samples directly.
Basically, the data is the same. It's just laid out differently in memory.
To access the samples in an easier way from Java you could do some bitwise arithmetic, like this:
int firstSample = (abAudioData[0]&0xFF) | (abAudioData[1]<<8);
Another way to read the samples is with the java.nio buffers:
ByteBuffer bb = ByteBuffer.wrap(abAudioData);
bb.order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer sb = bb.asShortBuffer();
int firstSample = sb.get();

Categories