Is it possible to ObjectOutputStream/ObjectInputStream an internal class? I can write it OK, and examine the created file, but when I try to read it back in using ObjectInputStream, I get an EOFException just trying to read an Object o = oos.readObject();
I use the same File object to open both streams, so that's not the problem.
It seems to be independant of the nature of the internal Class - a class with just a public int fails identically to a more complex class.
I have to move on, and create a regular class, and instantiate in the sender class, but I hate to walk away not knowing if it is possible, and if not why not.
Update: Related issues that were the cause of the problem:
A. You cannot re-open a file written with an ObjectOutputStream and append: a second header is written and corrupts the file.
B. Serializing a HashMap using ByteOutputStream to do a hash digest doesn't work, because when you read the HashMap back in from a ObjectOutputStream file, you may very well get a different byte[] from ByteOutputStream because of variations in pair order: the content is the same, but the byte[] (and so the hash disgest) is not.
Hope this helps someone save some time.
This one works for me. Please look for any differences to your solution.
public class Example implements Serializable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
new Example().run();
}
private void run() throws IOException, ClassNotFoundException {
Inner inner = new Inner();
inner.x = 5;
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream( out );
outputStream.writeObject( inner );
ByteArrayInputStream in = new ByteArrayInputStream( out.toByteArray() );
ObjectInputStream inputStream = new ObjectInputStream( in );
Inner inner2 = (Inner) inputStream.readObject();
System.out.println( inner2.x );
}
class Inner implements Serializable {
int x;
}
}
Can you include a small bit of sample code? The most obvious explanation is that you're not closing / flushing the output stream before you try to read it back in.
Related
I have this DownloadFile.java and downloads the file as it should:
import java.io.*;
import java.net.URL;
public class DownloadFile {
public static void main(String[] args) throws IOException {
String fileName = "setup.exe";
// The file that will be saved on your computer
URL link = new URL("http://onlinebackup.elgiganten.se/software/elgiganten/setup.exe");
// The file that you want to download
// Code to download
InputStream in = new BufferedInputStream(link.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1 != (n = in.read(buf))) {
out.write(buf, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(response);
fos.close();
// End download code
System.out.println("Finished");
}
}
I want to execute this from a mouse event in Gui.java.
private void jLabel17MouseClicked(java.awt.event.MouseEvent evt){
}
How do I do this?
Your current method is a static method, which is fine, but all the data that it extracts is held tightly within the main method, preventing other classes from using it, but fortunately this can be corrected.
My suggestion:
re-write your DownloadFile code so that it is does not simply a static main method, but rather a method that can be called by other classes easily, and that returns the data from the file of interest. This way outside classes can call the method and then receive the data that the method extracted.
Give it a String parameter that will allow the calling code to pass in the URL address.
Give it a File parameter for the file that it should write data to.
Consider having it return data (a byte array?), if this data will be needed by the calling program.
Or if it does not need to return data, perhaps it could return boolean to indicate if the download was successful or not.
Make sure that your method throws all exceptions (such as IO and URL excptions) that it needs to throw.
Also, if this is to be called by a Swing GUI, be sure to call this type of code in a background thread, such as in a SwingWorker, so that this code does not tie up the Swing event thread, rendering your GUI frozen for a time.
Is there a semantic difference between the following two options? Is any one of them more secure than the other in terms of automatic resource management?
Option1:
try ( ObjectInputStream in = new ObjectInputStream(new
FileInputStream("fooFile")) ) {
...
}
Option2:
try (FileInputStream fin = new FileInputStream("fooFile");
ObjectInputStream in = new ObjectInputStream(fin)) {
...
}
See here: http://www.stackoverflow.com/a/21348893/1419315
The argument there is, essentially, that with the first variant, FileInputStream.close () will not get called when construction of the ObjectInputStream fails.
I'm trying to print objects into file.
Then I want to import them back to my program.
ObjectOutputStream not working, What am I missing? (try, catch not visible here but they're doing their job)
Map< Account, Customer> customerInfo = new HashMap< Account, Customer>();
File bankFile = new File("Bank.txt");
FileOutputStream fOut = new FileOutputStream( bankFile);
ObjectOutputStream objOut = new ObjectOutputStream(fOut);
for(Map.Entry<Account, Customer> e : bank.customerInfo.entrySet())
{
objOut.writeObject(e.getValue());
objOut.writeObject(e.getKey());
}
objOut.flush();
objOut.close();
fOut.close();
My problem here is that ObjectOutputStream is not working properly, it prints some weird code. I've used other methods to print out to file and they work just fine.
I've tried printing to different file extensions,
I tried changing the encoding for both the file and eclipse.
I tried different methods for getting the info from the Map using ObjectOutputStream. Is there a reason why ObjectOutputStream prints weird characters that I haven't think of? The entire file is almost impossible to read. Thanks!
Ps. some of the weird print, don't know if it helps.
¬ísrCustomerDìUðkJ
personalIdNumLnametLjava/lang/String;xpthellosr
SavingAccountUÞÀÀ;>ZfreeWithdrawDwithdrawalInterestRateLaccountTypeq~xrAccount é=UáÐI
accountNumberDbalanceDinterestRateLaccountTypeq~L transListtLjava/util/List;xpé?záG®{tsrjava.util.ArrayListxÒÇaIsizexpw
x?záG®{tSaving Accountq~sr
CreditAccountÝ
*5&VcLaccountTypeq~xq~ê?záG®{q~sq~ w
xtCredit Account
It's really quite simple. First things first, create a class that implements Serializable. Serializable is a marker interface, so you don't need to implement any methods for it:
public class Shoe implements Serializable { ... }
NOTE: If Shoe has other classes in it, for example Heel, or Buckle, those classes also need to implement the Serializable interface.
Next step is to write that to a file, using an ObjectOutputStream.
FileOutputStream out = new FileOutputStream("myfile.txt");
// Create the stream to the file you want to write too.
ObjectOutputStream objOut = new ObjectOutputStream(out);
// Use the FileOutputStream as the constructor argument for your object.
objOut.writeObject(new Shoe("Prada"));
// Write your object to the output stream.
objOut.close();
// MAKE SURE YOU CLOSE to avoid memory leaks, and make sure it actually writes.
There you have it. The serialized object is written to the txt file. Now to read it, it's just a case of using the ObjectInputStream.
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("myfile.txt");
Object obj = objIn.readObject();
if(obj instanceof Shoe)
{
Shoe shoe = (Shoe)obj;
}
And you've got an object you can use.
Is it possible to write objects in Java to a binary file? The objects I want to write would be 2 arrays of String objects. The reason I want to do this is to save persistent data. If there is some easier way to do this let me know.
You could
Serialize the Arrays, or a class
that contains the arrays.
Write the arrays as two lines in a formatted
way, such as JSON,XML or CSV.
Here is some code for the first one (You could replace the Queue with an array)
Serialize
public static void main(String args[]) {
String[][] theData = new String[2][1];
theData[0][0] = ("r0 c1");
theData[1][0] = ("r1 c1");
System.out.println(theData.toString());
// serialize the Queue
System.out.println("serializing theData");
try {
FileOutputStream fout = new FileOutputStream("thedata.dat");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(theData);
oos.close();
}
catch (Exception e) { e.printStackTrace(); }
}
Deserialize
public static void main(String args[]) {
String[][] theData;
// unserialize the Queue
System.out.println("unserializing theQueue");
try {
FileInputStream fin = new FileInputStream("thedata.dat");
ObjectInputStream ois = new ObjectInputStream(fin);
theData = (Queue) ois.readObject();
ois.close();
}
catch (Exception e) { e.printStackTrace(); }
System.out.println(theData.toString());
}
The second one is more complicated, but has the benefit of being human as well as readable by other languages.
Read and Write as XML
import java.beans.XMLEncoder;
import java.beans.XMLDecoder;
import java.io.*;
public class XMLSerializer {
public static void write(String[][] f, String filename) throws Exception{
XMLEncoder encoder =
new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream(filename)));
encoder.writeObject(f);
encoder.close();
}
public static String[][] read(String filename) throws Exception {
XMLDecoder decoder =
new XMLDecoder(new BufferedInputStream(
new FileInputStream(filename)));
String[][] o = (String[][])decoder.readObject();
decoder.close();
return o;
}
}
To and From JSON
Google has a good library to convert to and from JSON at http://code.google.com/p/google-gson/ You could simply write your object to JSOn and then write it to file. To read do the opposite.
You can do it using Java's serialization mechanism, but beware that serialization is not a good solution for long-term persistent storage of objects. The reason for this is that serialized objects are very tightly coupled to your Java code: if you change your program, then the serialized data files become unreadable, because they are not compatible anymore with your Java code. Serialization is good for temporary storage (for example for an on-disk cache) or for transferring objects over a network.
For long-term storage, you should use a standard and well-documented format (for example XML, JSON or something else) that is not tightly coupled to your Java code.
If, for some reason, you absolutely want to use a binary format, then there are several options available, for example Google protocol buffers or Hessian.
One possibility besides serialization is to write Objects to XML files to make them more human-readable. The XStream API is capable of this and uses an approach that is similar to serialization.
http://x-stream.github.io/
If you want to write arrays of String, you may be better off with a text file. The advantage of using a text file is that it can be easily viewed, edited and is usuable by many other tools in your system which mean you don't have to have to write these tools yourself.
You can also find that a simple text format will be faster and more compact than using XML or JSON. Note: Those formats are more useful for complex data structures.
public static void writeArray(PrintStream ps, String... strings) {
for (String string : strings) {
assert !string.contains("\n") && string.length()>0;
ps.println(strings);
}
ps.println();
}
public static String[] readArray(BufferedReader br) throws IOException {
List<String> strings = new ArrayList<String>();
String string;
while((string = br.readLine()) != null) {
if (string.length() == 0)
break;
strings.add(string);
}
return strings.toArray(new String[strings.size()]);
}
If your start with
String[][] theData = { { "a0 r0", "a0 r1", "a0 r2" } {"r1 c1"} };
This could result in
a0 r0
a0 r1
a0 r2
r1 c1
As you can see this is easy to edit/view.
This makes some assumptions about what a string can contain (see the asset). If these assumptions are not valid, there are way of working around this.
You need to write object, not class, right? Because classes are already compiled to binary .class files.
Try ObjectOutputStream, there's an example
http://java.sun.com/javase/6/docs/api/java/io/ObjectOutputStream.html
I am able to serialize an object into a file and then restore it again as is shown in the next code snippet. I would like to serialize the object into a string and store into a database instead. Can anyone help me?
LinkedList<Diff_match_patch.Patch> patches = // whatever...
FileOutputStream fileStream = new FileOutputStream("foo.ser");
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(patches1);
os.close();
FileInputStream fileInputStream = new FileInputStream("foo.ser");
ObjectInputStream oInputStream = new ObjectInputStream(fileInputStream);
Object one = oInputStream.readObject();
LinkedList<Diff_match_patch.Patch> patches3 = (LinkedList<Diff_match_patch.Patch>) one;
os.close();
Sergio:
You should use BLOB. It is pretty straighforward with JDBC.
The problem with the second code you posted is the encoding. You should additionally encode the bytes to make sure none of them fails.
If you still want to write it down into a String you can encode the bytes using java.util.Base64.
Still you should use CLOB as data type because you don't know how long the serialized data is going to be.
Here is a sample of how to use it.
import java.util.*;
import java.io.*;
/**
* Usage sample serializing SomeClass instance
*/
public class ToStringSample {
public static void main( String [] args ) throws IOException,
ClassNotFoundException {
String string = toString( new SomeClass() );
System.out.println(" Encoded serialized version " );
System.out.println( string );
SomeClass some = ( SomeClass ) fromString( string );
System.out.println( "\n\nReconstituted object");
System.out.println( some );
}
/** Read the object from Base64 string. */
private static Object fromString( String s ) throws IOException ,
ClassNotFoundException {
byte [] data = Base64.getDecoder().decode( s );
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream( data ) );
Object o = ois.readObject();
ois.close();
return o;
}
/** Write the object to a Base64 string. */
private static String toString( Serializable o ) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject( o );
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
}
/** Test subject. A very simple class. */
class SomeClass implements Serializable {
private final static long serialVersionUID = 1; // See Nick's comment below
int i = Integer.MAX_VALUE;
String s = "ABCDEFGHIJKLMNOP";
Double d = new Double( -1.0 );
public String toString(){
return "SomeClass instance says: Don't worry, "
+ "I'm healthy. Look, my data is i = " + i
+ ", s = " + s + ", d = " + d;
}
}
Output:
C:\samples>javac *.java
C:\samples>java ToStringSample
Encoded serialized version
rO0ABXNyAAlTb21lQ2xhc3MAAAAAAAAAAQIAA0kAAWlMAAFkdAASTGphdmEvbGFuZy9Eb3VibGU7T
AABc3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwf////3NyABBqYXZhLmxhbmcuRG91YmxlgLPCSilr+w
QCAAFEAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cL/wAAAAAAAAdAAQQUJ
DREVGR0hJSktMTU5PUA==
Reconstituted object
SomeClass instance says: Don't worry, I'm healthy. Look, my data is i = 2147483647, s = ABCDEFGHIJKLMNOP, d = -1.0
NOTE: for Java 7 and earlier you can see the original answer here
How about writing the data to a ByteArrayOutputStream instead of a FileOutputStream?
Otherwise, you could serialize the object using XMLEncoder, persist the XML, then deserialize via XMLDecoder.
Thanks for great and quick replies. I will gives some up votes inmediately to acknowledge your help. I have coded the best solution in my opinion based on your answers.
LinkedList<Patch> patches1 = diff.patch_make(text2, text1);
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(patches1);
String serialized_patches1 = bos.toString();
os.close();
ByteArrayInputStream bis = new ByteArrayInputStream(serialized_patches1.getBytes());
ObjectInputStream oInputStream = new ObjectInputStream(bis);
LinkedList<Patch> restored_patches1 = (LinkedList<Patch>) oInputStream.readObject();
// patches1 equals restored_patches1
oInputStream.close();
} catch(Exception ex) {
ex.printStackTrace();
}
Note i did not considered using JSON because is less efficient.
Note: I will considered your advice about not storing serialized object as strings in the database but byte[] instead.
Java8 approach, converting Object from/to String, inspired by answer from OscarRyz. For de-/encoding, java.util.Base64 is required and used.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Base64;
import java.util.Optional;
final class ObjectHelper {
private ObjectHelper() {}
static Optional<String> convertToString(final Serializable object) {
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(object);
return Optional.of(Base64.getEncoder().encodeToString(baos.toByteArray()));
} catch (final IOException e) {
e.printStackTrace();
return Optional.empty();
}
}
static <T extends Serializable> Optional<T> convertFrom(final String objectAsString) {
final byte[] data = Base64.getDecoder().decode(objectAsString);
try (final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
return Optional.of((T) ois.readObject());
} catch (final IOException | ClassNotFoundException e) {
e.printStackTrace();
return Optional.empty();
}
}
}
XStream provides a simple utility for serializing/deserializing to/from XML, and it's very quick. Storing XML CLOBs rather than binary BLOBS is going to be less fragile, not to mention more readable.
How about persisting the object as a blob
If you're storing an object as binary data in the database, then you really should use a BLOB datatype. The database is able to store it more efficiently, and you don't have to worry about encodings and the like. JDBC provides methods for creating and retrieving blobs in terms of streams. Use Java 6 if you can, it made some additions to the JDBC API that make dealing with blobs a whole lot easier.
If you absolutely need to store the data as a String, I would recommend XStream for XML-based storage (much easier than XMLEncoder), but alternative object representations might be just as useful (e.g. JSON). Your approach depends on why you actually need to store the object in this way.
Take a look at the java.sql.PreparedStatement class, specifically the function
http://java.sun.com/javase/6/docs/api/java/sql/PreparedStatement.html#setBinaryStream(int,%20java.io.InputStream)
Then take a look at the java.sql.ResultSet class, specifically the function
http://java.sun.com/javase/6/docs/api/java/sql/ResultSet.html#getBinaryStream(int)
Keep in mind that if you are serializing an object into a database, and then you change the object in your code in a new version, the deserialization process can easily fail because your object's signature changed. I once made this mistake with storing a custom Preferences serialized and then making a change to the Preferences definition. Suddenly I couldn't read any of the previously serialized information.
You might be better off writing clunky per property columns in a table and composing and decomposing the object in this manner instead, to avoid this issue with object versions and deserialization. Or writing the properties into a hashmap of some sort, like a java.util.Properties object, and then serializing the properties object which is extremely unlikely to change.
The serialised stream is just a sequence of bytes (octets). So the question is how to convert a sequence of bytes to a String, and back again. Further it needs to use a limited set of character codes if it is going to be stored in a database.
The obvious solution to the problem is to change the field to a binary LOB. If you want to stick with a characer LOB, then you'll need to encode in some scheme such as base64, hex or uu.
You can use the build in classes sun.misc.Base64Decoder and sun.misc.Base64Encoder to convert the binary data of the serialize to a string. You das not need additional classes because it are build in.
Simple Solution,worked for me
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(obj);
return out.toByteArray();
}
Today the most obvious approach is to save the object(s) to JSON.
JSON is readable
JSON is more readable and easier to work with than XML.
A lot of Non-SQL databases that allow storing JSON directly.
Your client already communicates with the server using JSON. (If it doesn't, it is very likely a mistake.)
Example using Gson.
Gson gson = new Gson();
Person[] persons = getArrayOfPersons();
String json = gson.toJson(persons);
System.out.println(json);
//output: [{"name":"Tom","age":11},{"name":"Jack","age":12}]
Person[] personsFromJson = gson.fromJson(json, Person[].class);
//...
class Person {
public String name;
public int age;
}
Gson allows converting List directly. Examples can be easily
googled. I prefer to convert lists to arrays first.
you can use UUEncoding