0

I need to serialize an array of doubles to base64 in Java. I have following method from C#

public static string DoubleArrayToBase64( double[] dValues ) {
    byte[] bytes = new byte[dValues.Length * sizeof( double )];
    Buffer.BlockCopy( dValues, 0, bytes, 0, bytes.Length );
    return Convert.ToBase64String( bytes );
}

How do I do that in Java? I tried

Byte[] bytes = new Byte[abundaceArray.length * Double.SIZE];
System.arraycopy(abundaceArray, 0, bytes, 0, bytes.length);
abundanceValues = Base64.encodeBase64String(bytes); 

however this leads to an IndexOutofBoundsException.

How can I achieve this in Java?

EDIT:

Buffer.BlockCopy copies on byte level, the last paramter is number of bytes. System.arraycopy last parameter is number of elements to copy. So yes it should be abundaceArray.length but then a ArrayStoreException is thrown.

EDIT2:

The base64 string must be the same as the ine created with the c# code!

beginner_
  • 7,230
  • 18
  • 70
  • 127
  • Duplicate of either [How can I convert a byte array into a double and back?](http://stackoverflow.com/questions/2905556/how-can-i-convert-a-byte-array-into-a-double-and-back) or [Best and efficient way to convert double value into a byte array in Java](http://stackoverflow.com/questions/14062904/best-and-efficient-way-to-convert-double-value-into-a-byte-array-in-java) which both suggest to use `ByteBuffer` if you do not want to convert `double` to `long` and `long` to `byte[]` manually. – Oleg Estekhin Jun 17 '14 at 12:46

4 Answers4

3

You get an ArrayStoreException when the array types on the method are not the same primitive, so double to byte will not work. Here is a workaround i patched up that seems to work. I do not know of any method in the java core that does automatic conversion from primitive to byte block :

public class CUSTOM {
    public static void main(String[] args) {
        double[] arr = new double[]{1.1,1.3};
        byte[] barr = toByteArray(arr);
        for(byte b: barr){
            System.out.println(b);
        }
    }
    public static byte[] toByteArray(double[] from) {
        byte[] output = new byte[from.length*Double.SIZE/8]; //this is reprezented in bits
        int step = Double.SIZE/8;
        int index = 0;
        for(double d : from){
            for(int i=0 ; i<step ; i++){
                long bits = Double.doubleToLongBits(d); // first transform to a primitive that allows bit shifting
                byte b = (byte)((bits>>>(i*8)) & 0xFF); // bit shift and keep adding
                int currentIndex = i+(index*8);
                output[currentIndex] = b;
            }
            index++;
        }
        return output;
    }
}
omu_negru
  • 4,642
  • 4
  • 27
  • 38
1

The Double.SIZE get 64 which is number of bits I suggest to initialize the array like this

Byte[] bytes = new Byte[abundaceArray.length * 8];
0

Not sure what this C# function does, but I suspect you should replace this line

System.arraycopy(abundaceArray, 0, bytes, 0, bytes.length);

with this

System.arraycopy(abundaceArray, 0, bytes, 0, abundaceArray.length);
Ray
  • 3,084
  • 2
  • 19
  • 27
0

I'm guessing you're using the apache commons Base64 class. That only has methods accepting an array of bytes (the primitive type), not Bytes (object wrapper around primitive type).

It's not clear what type your 'abundaceArray' is - whether it's doubles or Doubles.

Either way, you can't use System.arraycopy to copy between arrays of difference primitive types.

I think your best bet is to serialise your array object to a byte array, then base64 encode that.

eg:

ByteArrayOutputStream b = new ByteArrayOutputStream(); // to store output from serialization in a byte array
ObjectOutputStream o = new ObjectOutputStream(b); // to do the serialization
o.writeObject(abundaceArray);   // arrays of primitive types are serializable
String abundanceValues = Base64.encodeBase64String(b.toByteArray());

There is of course an ObjectInputStream for going in the other direction at the other end.

JonathanS
  • 211
  • 1
  • 4
  • This actually will work if instead of String abundanceValues = Base64.encodeBase64String(b.toByteArray()); you do this byte[] vals = b.toByteArray() – omu_negru Jun 17 '14 at 13:19
  • The end-result of the original question was a base64 encoded string, not an array of bytes, was just trying to duplicate that ... – JonathanS Jun 17 '14 at 15:40