I have this bundle:
Bundle bundle = new Bundle();
bundle.putString("u", mp); // String mp
bundle.putSerializable("m", mealplan); // String[7][6][4][5] mealplan
save.putExtra("b", bundle);
I need to put it inside a blob column but I don't know how exactly.
Bundle objects support Parcels, but the Parcel.marshall() documentation says:
The data you retrieve here must not be placed in any kind of persistent storage (on local disk, across a network, etc). For that, you should use standard serialization or another kind of general serialization mechanism. The Parcel marshalled representation is highly optimized for local IPC, and as such does not attempt to maintain compatibility with data created in different versions of the platform.
The easist serialization mechanism probably is JSON, which is a readable text format.
To create a JSON string, you have to construct a tree of JSONObject/JSONArray objects:
// write
JSONObject json = new JSONObject();
json.put("u", mp);
JSONArray mealplan_json = new JSONArray();
mealplan_json.put(...); // fill arrays recursively
json.put("m", mealplan_json);
String text = json.toString();
// read
JSONObject json = new JSONObject(text);
mp = json.getString("u");
JSONArray mealplan_json = json.getJSONArray("m");
...
If you want to save space with a binary encoding, you have to use serialization, which supports basic types and any object that correctly implements java.io.Serializable:
// write
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(mp);
oos.writeObject(mealplan);
oos.close();
byte[] bytes = bos.toByteArray();
// read
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
mp = (String) ois.readObject();
mealplan = (String[][][][]) ois.readObject();
Please note that this binary serialization does not store any key names ("u", "m"), so you have to ensure that all versions of your app write and read the same objects in the same order.
If you want to have a key/value structure, you have to implement your own helper functions that write values with a separate key string in front, and that read an arbitrary number of key/value pairs into a map.
Alternatively, create your own serializable object that contains the desired elements (and take care that this class stays compatible in future versions of your app):
class MealPlanData implements Serializable {
String u;
String[][][][] mp;
};
If you have only a Bundle object and do not know its structure, you have to handle the keys/values manually:
// write
oos.writeInt(bundle.size());
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
oos.writeObject(key);
oos.writeObject(value);
}
// read
int size = ios.readInt();
Map<String, Object> map = new ArrayMap<String, Object>();
for (int i = 0; i < size; i++) {
String key = (String) ios.readObject();
Object value = ios.readObject();
map.put(key, value);
}
Related
Hi and thanks in advance,
So I'm trying to take an array of JList items and convert them to a string array (which I think I've gotten right), and then I'm trying to send that string array over to my client who will then attempt to display them back into a JList on their side.
I've tried a few different things but none are working.
Here is my latest code attempt to send the string array over:
String[] FilesList = (String[]) lClient1Files.getSelectedValues();
FilesBuffer = FilesList.getBytes();
DatagramPacket DGPFilesResponse = new DatagramPacket(FilesBuffer,FilesBuffer.length, DGP.getAddress(), DGP.getPort());
SeederSocket.send(DGPFilesResponse);
The line: FilesBuffer = FilesList.getBytes(); is causing the issue because getBytes() isn't applicable here.
So my questions are:
1) How do I send the array of JList items(they are names) over to the client (it doesn't particularly have to be a string array), and
2) How would I receive the list on the clients side, so that I can use it?
Thank you.
One must make a binary format for the string array.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(baos)) {
dos.writeInt(filesList.length);
for (String files : filesList) {
dos.writeUTF(files);
}
}
byte[] bytes = baos.toByteArray();
This internally for a String writes first the length in bytes, and uses String.getBytes("UTF-8") so any string can be written.
Reading goes with the reversed input classes.
If you think of having many clients out there, maybe with different versions,
then add in the message a version number.
On the other side
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
try (DataInputStream dis = new DataInputStream(baos)) {
int stringsCount = dis.readInt();
String[] filesList = new String[stringsCount];
for (int i = 0; i < stringsCount; ++i) {
filesList[i] = dis.readUTF();
}
return filesList;
}
The UDP payload has to be a byte[]. You need to choose a way to encode your data into a byte[], such that it can be converted back at the receiving end.
So you need to write encode() and decode() so that unit tests like this work:
#Test
public void encodesAndDecodesStringArray() {
String[] strings = new String[] { "foo", "bar" };
byte[] encoded = Encoder.encode(strings);
String[] decoded = Encoder.decode(encoded);
assertThat(decoded, is(strings));
}
There are literally hundreds of encoding schemes you could choose from. Delimiter-separated, length-separated, JSON, XML, BSON, ASN.1 ... take a look at Wikipedia's List of data serialization formats.
A very simple option that might work for you is delimiter-separation:
public byte[] encode(String[] strings) {
return String.join(",", strings).getBytes(UTF_8);
}
public String[] decode(byte[] encodedArray) {
return new String(encodedArray, UTF_8).split(",");
}
But note that this very basic scheme fails if any of the input strings contains a "," (or whatever delimiter you choose). Pick a scheme that works for you.
Consider using JSON -- there are easy to use libraries to read and write JSON. Readable ASCII in network traces is often convenient. The space overhead is not that high. It's ready for arbitrarily complex hierarchical data structures.
Consider that if you change the structure of the data produced by your sender, the receiver must also change. If that matters, consider encoding a protocol version into what you send (it might be enough to just say "the first two bytes are the version", and always stick a 0x0001 in there to start with).
I have a code where I am converting array list to byte array and then saving that byte array as a BLOB in MySQL database. Below is code:-
Object temp = attributes.get(columnName);
if (temp instanceof List && temp != null) {
List extraAttributes = (ArrayList) temp;
resultStmt.setBytes(currentIndex, createByteArray(extraAttributes));
The method createByteArray is defined as below:
private byte [] createByteArray( Object obj)
{
byte [] bArray = null;
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream objOstream = new ObjectOutputStream(baos);
objOstream.writeObject(obj);
bArray = baos.toByteArray();
}
catch (Exception e)
{
TraceDbLog.writeError("Problem in createByteArray", e);
}
return bArray;
}
Well the above code was written earlier for writing HashMap to BLOB i am using same for converting ArrayList if HashMap to BLOB.
The problem which is occurring in read code when i am reading the blob.
private Object readBytes (ResultSet rs, String columnName)
throws SQLException
{
ObjectInputStream ois = null;
byte [] newArray;
Object obj = null;
try
{
newArray = rs.getBytes(columnName);
ois = new ObjectInputStream (new ByteArrayInputStream(newArray));
obj = ois.readObject ();
}
In the read part the object is not coming as arrayList of hasMap and in debug perspective in eclipse eclipse is also not able to inspect the object which is coming.
I have also tried typecasting the object to List but still no success in getting the right response.
Please tell me whether there is any flaw in reading/writing the above BLOB.
I have added sample coding for convert ArrayList to byte[].
One reasonable way would be to use UTF-8 encoding like DataOutputStream does for each string in the list. For a string it writes 2 bytes for the length of the UTF-8 encoding followed by the UTF-8 bytes.
This would be portable if you're not using Java on the other end. Here's an example of encoding and decoding an ArrayList:
// example input list
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list.add("baz");
// write to byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baos);
for (String element : list) {
out.writeUTF(element);
}
byte[] bytes = baos.toByteArray();
// read from byte array
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
DataInputStream in = new DataInputStream(bais);
while (in.available() > 0) {
String element = in.readUTF();
System.out.println(element);
}
The easiest way is to convert it to json string and then to bytes
Gson gson = new Gson();
Type type = new TypeToken<List<Alarm>>() {}.getType();
String json = gson.toJson(list, type);
byte[] bytes = json.getBytes();
In xmlrpc objects need to be serialized before they can be transmitted across a network, so this is what I am trying to do.
addAuthorName = txtAddAuthorName.getText();
int addArticleNumber = Integer.parseInt(txtAddArticleNumber.getText());
newArticle = new Article(addAuthorName, addArticleNumber);
ObjectOutputStream oos;
oos = new ObjectOutputStream(
new ByteArrayOutputStream());
oos.writeObject(newArticle);
Vector<Object> addArticleArglist = new Vector<Object>();
addArticleArglist.addElement(oos);
System.out.println(oos);
// make the call
String callit = ("GetSize.addHash");
articleID = (Integer) client.execute(callit, addArticleArglist);
The problem I am getting is that my program will not accept the outputstream that is contained in the vector the error given is
unsupported Java type: class java.io.ObjectOutputStream
You can only serialize objects that implement the java.io.Serializable interface. Below statement adds ObjectOutputStream to the Vector which doesn't implement that interface.
addArticleArglist.addElement(oos);
I doesn't see any reason why you have to add that to Vector.
The serialization happens automatically. You don't need to undertake further action to serialize the object—just use it as a param, and it will automatically be serialized.
I was trying to serialize and deserialize a gov.nist.javax.sip.stack.SIPDialog object into Cassandra. But the equals comparison on the deserialized object fails when I compare it with the original SIPDialog object I serialized. SO looks like I am missing something here in serialisation. I am using a ByteArraySerializer to read/write the bytes into Cassandra.
//Saving Dialog
MutationBatch mutationBatch = createMutator();
byte[] dialogBytes = SIPDialogEntity.serializeDialog(dialog);
mutationBatch.withRow(SIPDIALOGS, dialogId)
.putColumn("dialog".getBytes(),dialogBytes,null);
mutationBatch.execute();
public static byte[] serializeDialog(SIPDialog dialog) throws IOException {
ByteArrayOutputStream bStream = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bStream);
oos.writeObject(dialog);
oos.close();
byte[] bytes = bStream.toByteArray();
bStream.close();
return bytes;
}
//Reading Dialog
Column<byte[]> result;
result = getKeySpace().prepareQuery(SIPDIALOGS).getKey(dialogId).getColumn("dialog").execute().getResult();
sipDialog = SIPDialogEntity.deserializeDialog(result.getByteArrayValue());
public static SIPDialog deserializeDialog(byte[] byteArrayDialog) throws IOException, ClassNotFoundException {
System.out.println("DEBUG Reading Dialog Bytes:" + byteArrayDialog );
ByteArrayInputStream bStream = new ByteArrayInputStream(byteArrayDialog);
ObjectInputStream ois = new ObjectInputStream(bStream);
SIPDialog dialog = (SIPDialog) ois.readObject();
ois.close();
bStream.close();
return dialog;
}
The SIPDialog class doesn't override the equals method which is why it fails the comparison. Please open an issue in jain sip at http://java.net/jira/browse/JSIP
hmmmm, If SipDialog is your class, you could just skip all the work and use PlayOrm for cassandra ;). Then you don't need to deal with serializing/deserializing.
If it is not your class, I think I will get them to add a way to add 3rd party beans to be converted to an entity much like Guice does in a binding file so it can bind to an entity that can be saved by PlayOrm. IF you open a ticket on PlayOrm with a request, we could get the feature in probably in as little as 1 week.
hello i have a basic client-server system running using java sockets.
my problem is, that an object that i send from the client to the server does not contain the correct data after it has been sent once.
the first time i send it, it arrives with the correct values, but when i send it another time with different values, it still arrives at the server with the same values as the first time. it also happens if i send a completely different instance of that class. it always arrives with the data, which have been sent the very first time.
when i try this with other objects like java.lang.String it seems to work.
the problematic class looks like this:
public class Vector3f implements Serializable {
private static final long serialVersionUID = 2838034155614698213L;
public float x, y, z;
}
i use objectinputstream and objectoutputstream on both the server and the client to send and receive objects.
let me know, if you need any more information about the system.
thanks!
My guess is that you're changing the values of the fields and then retransmitting the same object. The ObjectOutputStream will notice that it's already sent the original object, and just send a reference the second time.
You could avoid this by calling reset() on the ObjectOutputStream - but I'd be tempted to just use separate instances anyway, possibly even making the class immutable. (Public mutable fields are almost never a good idea.)
The best way in case of serialization you should convert the object into a byte array object and then write into the socket.
// Serialize to a file
ObjectOutput out = new ObjectOutputStream(new FileOutputStream("filename.ser"));
out.writeObject(object);
out.close();
// Serialize to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
out = new ObjectOutputStream(bos) ;
out.writeObject(object);
out.close();
// Get the bytes of the serialized object
byte[] buf = bos.toByteArray();
// Deserialize from a file
File file = new File("filename.ser");
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
// Deserialize the object
Object obj = (Object) in.readObject();
in.close();
// Get some byte array data
byte[] bytes = getBytesFromFile(file);
// see Reading a File into a Byte Array for the implementation of this method
// Deserialize from a byte array
in = new ObjectInputStream(new ByteArrayInputStream(bytes));
in.close();