tags:

views:

53

answers:

3

Given a generic array T[], where T extends java.lang.Number, I would like to write the array to a byte[], using ByteArrayOutputStream. java.io.DataOutput (and an implementation such as java.io.DataOutputStream appears close to what I need, but there is no generic way to write the elements of the T[] array. I want to do something like

ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(out);

for (T v : getData()) {
  dataOut.write(v); // <== uh, oh
}

but there is no generic <T> void write(T v) method on DataOutput.

Is there any way to avoid having to write a whole bunch of isntanceof spaghetti?

Clarification

The byte[] is being sent to a non-Java client, so object serialization isn't an option. I need, for example, the byte[] generated from a Float[] to be a valid float[] in C.

+4  A: 

No, there isn't. The instanceof "spaghetti" would have to exist somewhere anyway. Make a generic method that does that:

public <T> void write(DataOutputStream stream, T object) {
   // instanceofs and writes here
}
Bozho
+3  A: 

You can just use an ObjectOutputStream instead of a DataOutputStream, since all Numbers are guaranteed to be serializable.

Roland Illig
But how do you deserialize then not knowing what type your objects are?
InsertNickHere
Unfortunately, I left a significant constraint out of the first version of the question (now clarified above). Object serialization won't work, since this `byte[]` must be transferable to other languages (e.g. C).
Barry Wark
In that case, you should really think about what you mean by `Number`s and why you want them to have arbitrary format. What kind of numbers do you expect? Only integers? floating point? rational? complex? When interfacing with other languages, you have to be more specific.
Roland Illig
+1  A: 

Regarding to the last edit, I would try this approach (if its ugly or not).

1) Check per instanceof which type you have
2) Store it into a primitive and extract the bytes you need (eg integer) like this (for the first two bytes)

    byte[] bytes = new byte[2];
    bytes[0]=(byte)(i>>8);
    bytes[1]=(byte)i;

3) Send it via the byte[] array
4) Get stuck because different c implementations use different amout of bytes for integer, so nobody can guarantee that the results will equal your initial numbers. e.g. how do you want to handle the 4 byte integer of java with 2 byte integers of c? How do you handle Long?

So...i don't see a way to do, but, im not an expert in this area....

Please correct me if im wrong. ;-)

InsertNickHere
We're transmitting bytes-per-value, endian, and format (e.g. IEEE 754) with the byte[], so we handle all of the conversion on the C side. I just want to be able to parse primitive values instead of implementing Java object deserialization in C ;-)
Barry Wark
@Barry if i understand you correctly, than all you need to know is how to convert int/float into bytes? Or is it just that you dont like the instanceof thing, which you cant avoid in my knowledge?
InsertNickHere
Just wondering if there was a way to avoid the `instanceof` dance. A chain of if/else `instanceof` tests smells. It's too bad Number doesn't implement a `toByteArray()` method.
Barry Wark