I have a double(float/Decimal) value and I want to get the same byte array as produced by Java ByteBuffer in C#.
However the byte array produced by using ByteBuffer.PutDouble in Java and BinaryWriter in C# is different. Can someone please explain the implementation detail difference between the two.
Java:
ByteBuffer bytes = ByteBuffer.allocate(8).putDouble(0,1.12346);
bytes[] = {63, -15, -7, -83, -45, 115, -106, 54};
C#:
double value = 1.12346;
byte[] arr;
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(value);
arr = stream.ToArray();
}
}
arr[] = {153, 211, 101, 49, 177, 249, 241, 63};
ByteBuffer is big endian by default and bytes are signed.
In C#, it's little endian by default and bytes are unsigned.
You have the same data in the opposite order, from a serialization point of view, the sign of the bytes is not important except it is a little confusing.
In C# you can use the EndianBinaryWriter BinaryWriter Endian issue
Related
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();
}
Hi I have some problem with type conversion.
First, with python3.7, I read data from imagefile and encoded it as base64 which is then bytes type.
Then, I converted the bytes data to string with type conversion
Python codes are below.
f = open("monitor-1.png", "rb")
data = f.read()
encoded_string = str(base64.b64encode(data))
Then I sent it to java program using socket
To view image from java program,
need to get byte array from the received data. But what should I do? Type conversion of python makes me confused..
Maybe you should provide a snippet which can be used to reproduce your issue.
Following snippets are working
import base64
f = open("monitor-1.png", "rb")
data = f.read()
encoded_string = str(base64.b64encode(data))
print(encoded_string)
f.close()
output
b'iVBORw0KGgoAAAANSUhEUgAAAAIAAAABAQMAAADO7O3JAAAABlBMVEUAAAD///+l2Z/dAAAACklEQVQI12NoAAAAggCB3UNq9AAAAABJRU5ErkJggg=='
using the Base64 encoded string in Java jshell
jshell> byte[] bytes = Base64.getDecoder().decode("iVBORw0KGgoAAAANSUhEUgAAAAIAAAABAQMAAADO7O3JAAAABlBMVEUAAAD///+l2Z/dAAAACklEQVQI12NoAAAAggCB3UNq9AAAAABJRU5ErkJggg==")
bytes ==> byte[85] { -119, 80, 78, 71, 13, 10, 26, 10, 0, 0 ... 8, 68, -82, 66, 96, -126 }
jshell> Files.write(Paths.get("out.png"), bytes)
$2 ==> out.png
creates the file out.png
The file monitor-1.png and out.png are equal
$ md5sum monitor-1.png out.png
49b0cecce3c3ce0966afd6c13b03a4b5 monitor-1.png
49b0cecce3c3ce0966afd6c13b03a4b5 out.png
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]
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();
I am currently facing an error called Bad Base64Coder input character at ...
Here is my code in java.
String nonce2 = strNONCE;
byte[] nonceBytes1 = Base64Coder.decode(nonce2);
System.out.println("nonceByte1 value : " + nonceBytes1);
The problem now is I get Bad Base64Coder input character error and the nonceBytes1 value is printed as null. I am trying to decode the nonce2 from Base64Coder. My strNONCE value is 16
/** Generating nonce value */
public static String generateNonce() {
try {
byte[] nonce = new byte[16];
Random rand;
rand = SecureRandom.getInstance ("SHA1PRNG");
rand.nextBytes(nonce);
//convert byte array to string.
strNONCE = new String(nonce);
}catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return strNONCE;
}
//convert byte array to string.
strNONCE = new String(nonce);
That is not going to work. You need to base64 encode it.
strNONCE = Base64Coder.encode(nonce);
It simply look like you're confusing some independent concepts and are pretty new to Java as well. Base64 is a type of encoding which converts "human unreadable" byte arrays into "human readable" strings (encoding) and the other way round (decoding). It is usually used to transfer or store binary data as characters there where it is strictly been required (due to the protocol or the storage type).
The SecureRandom thing is not an encoder or decoder. It returns a random value which is in no way to be corelated with a certain cipher or encoder. Here are some extracts from the before given links:
ran·dom
adj.
1. Having no specific pattern, purpose, or objective
Cipher
In cryptography, a cipher (or cypher)
is an algorithm for performing
encryption or decryption — a series
of well-defined steps that can be
followed as a procedure.
Encoding
Encoding is the process of
transforming information from one
format into another. The opposite
operation is called decoding.
I'd strongly recommend you to align those concepts out for yourself (click the links to learn more about them) and not to throw them in one big and same hole. Here's at least an SSCCE which shows how you can properly encode/decode a (random) byte array using base64 (and how to show arrays as string (a human readable format)):
package com.stackoverflow.q2535542;
import java.security.SecureRandom;
import java.util.Arrays;
import org.apache.commons.codec.binary.Base64;
public class Test {
public static void main(String[] args) throws Exception {
// Generate random bytes and show them.
byte[] bytes = new byte[16];
SecureRandom.getInstance("SHA1PRNG").nextBytes(bytes);
System.out.println(Arrays.toString(bytes));
// Base64-encode bytes and show them.
String base64String = Base64.encodeBase64String(bytes);
System.out.println(base64String);
// Base64-decode string and show bytes.
byte[] decoded = Base64.decodeBase64(base64String);
System.out.println(Arrays.toString(decoded));
}
}
(using Commons Codec Base64 by the way)
Here's an example of the output:
[14, 52, -34, -74, -6, 72, -127, 62, -37, 45, 55, -38, -72, -3, 123, 23]
DjTetvpIgT7bLTfauP17Fw==
[14, 52, -34, -74, -6, 72, -127, 62, -37, 45, 55, -38, -72, -3, 123, 23]
A base64 encoded string would only have printable characters in it. You're generating strNONCE directly from random bytes, so it will have non-printable characters in it.
What exactly is it you're trying to do?