LocalClassIncompatible when serializing Java standard class - java

I'm having problems to serialize a custom serializable object with a generated SerialVersionUID, since i get an InvalidClassException when trying to deserialize this objetc with the following error:
< com.assistantindustries.test.Prueba; local class incompatible:
stream classdesc serialVersionUID = 6090585534595974753, local class
serialVersionUID = 6090585536173033057>
I made a junit class for testing it and this error keeps happening. Here's the code for the test:
public class TestSerializacion {
public String pruebaToString(Serializable prueba){
ByteArrayOutputStream bs= new ByteArrayOutputStream();
ObjectOutputStream os = null;
try {
os = new ObjectOutputStream (bs);
os.writeObject(prueba);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
return bs.toString();
}
public static Prueba getPruebaFromString(String prueba){
ByteArrayInputStream bs= new ByteArrayInputStream(prueba.getBytes());
ObjectInputStream is = null;
Prueba unObjetoSerializable = null;
try {
is = new ObjectInputStream(bs);
unObjetoSerializable = (Prueba)is.readObject();
is.close();
} catch (ClassNotFoundException | IOException e1) {
e1.printStackTrace();
}
return unObjetoSerializable;
}
#Test
public void testBasico(){
int i=453;
Prueba prueba=new Prueba(i);
String toSend=pruebaToString(prueba);
Prueba recibida=getPruebaFromString(toSend);
assertEquals(prueba.getPhrase(),recibida.getPhrase());
}
}
And the Class:
public class Prueba implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6090585536173033057L;
ArrayList<String> texts;
public Prueba(int semilla) {
Random r=new Random(semilla);
this.texts = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
char[] palabra=new char[10];
for (int j = 0; j < palabra.length; j++) {
palabra[j]=(char) (r.nextInt(256));
}
texts.add(new String(palabra));
}
}
public synchronized ArrayList<String> getTexts() {
return texts;
}
public synchronized void setTexts(ArrayList<String> texts) {
this.texts = texts;
}
public String getPhrase(){
String total="";
for(String s:this.texts){
total.concat(s);
}
return total;
}
}
All the answers I found about similar problems were solved by defining the serialVersionUID, but it is already defined in this class
Any help would be greatly appreciated! Thanks in advance!

Repeat after me. String is not a container for binary data. Write out 100 times. You shouldn't convert the result of serialization to a String. and back again. Pass it around as a byte[] array.

Related

How to deep serialize object using ObjectOutputStream.writeObject()+Base64 (Java)?

I need to serialize an Object in java. Currently I'm doing it by using this code, which does:
ObjectOutputStream.writeObject(obj);
Base64 encode the obj
And reversing the process.
It works fine for primitive types inside the class, such as long and int.
However, all String objects inside that object become null. I'd need them to be included as well. Is there any way to do that?
Edit: code I'm using
// Modified from source: https://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static Object FromString( String s )
{
Object o = null;
try {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
o = ois.readObject();
ois.close();
}
catch(Exception e)
{
System.out.println(e);
}
return o;
}
// Modified from source: https://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static String ToString( Serializable o )
{
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
}
catch(Exception e)
{
System.out.println(e);
}
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
EDIT: Pojo
public class SignedTimestamp implements Serializable {
private Long obj;
private byte[] signature;
private String signatureAsAString;
}
Output on the other application (receiving the data and deserializing):
obj = 1494609033621;
signature = null;
signatureAsAString = null;
I have just tested your code, and it's working okay.
I've created a source named SignedTimeStamp.java:
import java.io.*;
public class SignedTimestamp implements Serializable {
private Long obj;
private byte[] signature;
private String signatureAsAString;
public SignedTimestamp(Long obj, byte[] signature, String signatureAsAString) {
this.obj = obj;
this.signature = signature;
this.signatureAsAString = signatureAsAString;
}
public Long getObj() {
return this.obj;
}
public byte[] getSignature() {
return this.signature;
}
public String getSignatureAsAString() {
return this.signatureAsAString;
}
}
And declared another called Serializables.java, containing your code:
import java.io.;
import java.util.;
public class Serializables {
public static Object FromString(String s) {
Object o = null;
try {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
o = ois.readObject();
ois.close();
}
catch(Exception e)
{
System.out.println(e);
}
return o;
}
// Modified from source: http://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static String ToString( Serializable o ) {
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
}
catch(Exception e)
{
System.out.println(e);
}
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
}
Then, I created one main class in Serialize.java:
public class Serialize {
public static void main(String[] args) throws Exception {
SignedTimestamp o = new SignedTimestamp(100L, new byte[]{ (byte) 128 }, "Hello, world!");
System.out.println(Serializables.ToString(o));
}
}
Which returned me this result:
sh-4.3$ java Serialize
rO0ABXNyAA9TaWduZWRUaW1lc3RhbXCGTHiJ+JenzgIAA0wAA29ianQAEExqYXZhL2xhbmcvTG9uZztbAAlzaWduYXR1cmV0AAJbQkwAEnNpZ25hdHVyZUFzQVN0cmluZ3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3IADmphdmEubGFuZy
5Mb25nO4vkkMyPI98CAAFKAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAAAAABkdXIAAltCrPMX+AYIVOACAAB4cAAAAAGAdAANSGVsbG8sIHdvcmxkIQ==
sh-4.3$
Then, I created another main class in Deserialize.java:
public class Deserialize {
public static void main(String[] args) throws Exception {
String serialized =
"rO0ABXNyAA9TaWduZWRUaW1lc3RhbXCGTHiJ+JenzgIAA0wAA29ianQAEExqYXZhL2xhbmcvTG9uZztbAAlzaWduYXR1cmV0AAJbQkwAEnNpZ25hdHVyZUFzQVN0cmluZ3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3IADmphdmEubGFuZy" +
"5Mb25nO4vkkMyPI98CAAFKAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAAAAABkdXIAAltCrPMX+AYIVOACAAB4cAAAAAGAdAANSGVsbG8sIHdvcmxkIQ==";
SignedTimestamp o = (SignedTimestamp) Serializables.FromString(serialized);
System.out.println(o.getObj());
System.out.println(o.getSignature());
System.out.println(o.getSignatureAsAString());
}
}
And it returns this:
sh-4.3$ java Deserialize
100
[B#6bc7c054
Hello, world!
sh-4.3$
So, all in all, the code seems to be working perfectly.
How did you test your code? Perhaps the mistake is there.
I dont see any problem in that code. Please post your code so that we will dig further.
tried from my end:
Encoded serialized version
rO0ABXNyAAhFbXBsb3llZTLR4JLRYAw9AgAESQAGbnVtYmVyTAAHYWRkcmVzc3QAEkxqYXZhL2xhbmcvU3RyaW5nO0wADWFkZHJlc3NPYmplY3R0AAlMQWRkcmVzcztMAARuYW1lcQB+AAF4cAAAAGV0ABlQaG9ra2EgS3VhbiwgQW1iZWh0YSBQZWVyc3IAB0FkZHJlc3MkcEtPHXHTqQIAAUwACGFkZHJMaW5lcQB+AAF4cHEAfgAEdAAJUmV5YW4gQWxp
Reconstituted object
Employee [name=Reyan Ali, address=Phokka Kuan, Ambehta Peer, number=101, addressObject=Address [addrLine=Phokka Kuan, Ambehta Peer]]

why static block Cannot execute in sequence but jump into the other method in java?

We used a special database,so i want to write a database connection Pool,there is something wrong with the code, when i debug into the static block,at first JVM worked in the Properties properties = new Properties(); but next step is int i = 0; i dont know why it ingored the other code in the static block
public class GoldDataSource {
private static String goldip;
private static int goldport;
private static String username;
private static String password;
private static int maxPollSize;
private static LinkedList<Server> list = new LinkedList<Server>();
private static Logger logger = LoggerFactory.getLogger(GoldDataSource.class);
static {
try {
Properties properties = new Properties();
InputStream is = GoldDataSource.class.getClassLoader().getResourceAsStream("/conf/db/gold.properties");
properties.load(is);
goldip = properties.getProperty("gold.ip");
goldport = Integer.parseInt(properties.getProperty("gold.port"));
username = properties.getProperty("gold.username");
password = properties.getProperty("gold.password");
maxPollSize = Integer.parseInt(properties.getProperty("gold.pool.maxPollSize"));
for (int i = 0; i < maxPollSize; i++) {
Server server = new ServerImpl(goldip, goldport, username, password);
server.connect();
server.login();
list.add(server);
}
} catch (Exception e) {
....
}
}
public synchronized static Server getServer() {
try {
int i = 0;
while (true) {
Server aServer = list.removeFirst();
if (aServer != null) {
return aServer;
} else {
if (i >= 3) {
return aServer;
}
Thread.sleep(500);
i++;
}
}
} catch (Exception e) {
...
return null;
}
}
public static void closeServer(Server aServer) {
list.addLast(aServer);
}}
I used Server server = GoldDataSource.getServer(); to get connection,but when it executed Properties properties = new Properties();then jump into the code int i = 0; which in the getServer() method
I edited the code with singleton pattern,it worked ,but i still do not understand why the old code didn't worked , and i catched "java.lang.reflect.InvocationTargetException" in the first catch block old code.
public class GoldDataSource {
private static String goldip;
private static int goldport;
private static String username;
private static String password;
private static int maxPollSize;
private static LinkedList<Server> list = new LinkedList<Server>();
private static InputStream is;
private static GoldDataSource aDataSource = new GoldDataSource();
private static Logger logger = LoggerFactory.getLogger(GoldDataSource.class);
private goldDataSource() {
try {
Properties properties = new Properties();
is = GoldDataSource.class.getClassLoader().getResourceAsStream("/conf/db/gold.properties");
properties.load(is);
goldip = properties.getProperty("gold.ip");
goldport = Integer.parseInt(properties.getProperty("gold.port"));
username = properties.getProperty("gold.username");
password = properties.getProperty("gold.password");
maxPollSize = Integer.parseInt(properties.getProperty("gold.pool.maxPollSize"));
for (int i = 0; i < maxPollSize; i++) {
Server server = new ServerImpl(goldip, goldport, username, password);
server.connect();
server.login();
list.add(server);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static goldDataSource getDateSource() {
return aDataSource;
}
public synchronized Server getServer() {
try {
int i = 0;
while (true) {
Server aServer = list.removeFirst();
if (aServer != null) {
return aServer;
} else {
if (i >= 3) {
return aServer;
}
Thread.sleep(500);
i++;
}
}
} catch (Exception e) {
logger.error("get connection error:" + e.toString());
return null;
}
}
public void closeServer(Server aServer) {
list.addLast(aServer);
}
}

Why an object doesn't change when I send it through writeObject method?

I'm making networking program with Java. As the title, the object which server is trying to send is changed in client which receives it. I'm trying to change the object which exists in client before I receive the new one from server.
Here's my codes. First one is Server.sendIdea and second is Client.rcvIdea.
void sendIdea(Idea _idea) throws IOException {
objectOS.flush();
Idea idea = _idea;
//when I look into 'idea' it's fine
objectOS.writeObject(idea);
}
..
Idea rcvIdea(int _ideaCode) throws ClassNotFoundException, IOException {
objectOS.writeObject("sendIdea");
objectOS.writeObject(_ideaCode);
Idea returnValue = (Idea) objectIS.readObject();
//when I look into 'returnValue', it is not the one 'sendIdea' has sent.
return returnValue;
}
As you can see, sendIdea(Idea _idea) is sending an object from the class Idea by using writeObject method. And rcvIdea() is receiving the object by using readObject() method. (I'm sure you don't have to know about class Idea in detail). The client actually received some Ideas at start of this program by this method and there was no problem. But when I try to receive the same but slightly changed object Idea by this method, in Client class the object does not change, not like in Server class where the object which is going to be sent by sendIdea method is changed correctly. I tried about 5 hours to solve this problem. I checked all the codes line by line and found nothing. I'm pretty sure that writeObject or readObject method have problem. I tried objectOS.flush() to make clear of the stream and many other trials. I hope that I can find the problem. Below is some codes in my program
Client.class
package ideaOcean;
import java.awt.HeadlessException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import data.Idea;
import data.Opinion;
import data.Profile;
public class Client {
Socket socket;
OutputStream os;
ObjectOutputStream objectOS;
InputStream is;
ObjectInputStream objectIS;
MainWindow mainWindow;
int idCode;
String email, password;
Profile myProfile;
ArrayList<Idea> myIdeas;
ArrayList<Opinion> myOpinions;
ArrayList<Integer> newIdeasCodes, hotIdeasCodes;
ArrayList<Idea> newIdeas, hotIdeas;
String command;
static final String SERVER_IP = "127.0.0.1";//
static final int SERVER_PORT_NUM = 5000;
public static void main(String[] args) {
Client client = new Client();
client.mainWindow = new MainWindow();
client.mainWindow.setVisible(true);
client.mainWindow.showLoginPg();
try {
while (!client.loginCheck()) {// login
continue;
}
} catch (HeadlessException | NumberFormatException | ClassNotFoundException | IOException e) {
e.printStackTrace();
}
System.out.println("[login complete]");
try {
client.myProfile = client.rcvProfile(client.idCode);// get myProfile
int i;
for (i = 0; i < client.myProfile.myIdeaCode.size(); i++) {
client.myIdeas.add(client.rcvIdea(client.myProfile.myIdeaCode.get(i)));
}
for (i = 0; i < client.myProfile.myOpinionCode.size(); i++) {
client.myOpinions.add(client.rcvOpinion(client.myProfile.myOpinionCode.get(i)));
}
// ***************************
} catch (ClassNotFoundException | IOException e1) {
e1.printStackTrace();
}
try {
client.rcvNewIdeas(12);
client.mainWindow.newOcean.floatingIdeas = client.newIdeas;
client.mainWindow.newOcean.arrangeFloatingPanels();
client.rcvHotIdeas(12);
client.mainWindow.hotOcean.floatingIdeas = client.hotIdeas;
client.mainWindow.hotOcean.arrangeFloatingPanels();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
client.mainWindow.setMyPg(client.myProfile, client.myIdeas, client.myOpinions);
client.mainWindow.showMainPg();
client.start();
}
public Client() {
try {
socket = new Socket(SERVER_IP, SERVER_PORT_NUM);
System.out.println("Connected to Server!");
os = socket.getOutputStream();
objectOS = new ObjectOutputStream(os);
is = socket.getInputStream();
objectIS = new ObjectInputStream(is);
myIdeas = new ArrayList<>();
myOpinions = new ArrayList<>();
newIdeasCodes = new ArrayList<>();
hotIdeasCodes = new ArrayList<>();
newIdeas = new ArrayList<>();
hotIdeas = new ArrayList<>();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
void start() {
while (true) {
try {
if (mainWindow.newBtnClicked) {
rcvNewIdeas(12);
mainWindow.newOcean.floatingIdeas = newIdeas;
mainWindow.newOcean.arrangeFloatingPanels();
mainWindow.newBtnClicked = false;
} else if (mainWindow.hotBtnClicked) {
rcvHotIdeas(12);
mainWindow.hotOcean.floatingIdeas = hotIdeas;
mainWindow.hotOcean.arrangeFloatingPanels();
mainWindow.hotBtnClicked = false;
} else if (mainWindow.newOcean.detailBtnClicked) {
updateIdeaDetailFrame(mainWindow.newOcean.clickedIdea);
mainWindow.newOcean.detailBtnClicked = false;
} else if (mainWindow.hotOcean.detailBtnClicked) {
updateIdeaDetailFrame(mainWindow.hotOcean.clickedIdea);
mainWindow.hotOcean.detailBtnClicked = false;
} else if (mainWindow.ideaDetailFrame.saveOpinionBtnClicked) {
sendOpinion(mainWindow.ideaDetailFrame.newOpinion);
updateIdeaDetailMainPanel(rcvIdea(mainWindow.ideaDetailFrame.idea.ideaCode));
mainWindow.ideaDetailFrame.saveOpinionBtnClicked = false;
} else if (mainWindow.writeIdeaPg.postIdeaBtnClicked) {
sendIdea(mainWindow.writeIdeaPg.thisIdea);
mainWindow.writeIdeaPg.postIdeaBtnClicked = false;
} else if (mainWindow.newOcean.plusBtnClicked) {
objectOS.writeObject("plusBtnClicked");
objectOS.writeObject(mainWindow.newOcean.plusMinusClickedIdeaCode);
mainWindow.newOcean.plusBtnClicked = false;
} else if (mainWindow.newOcean.minusBtnClicked) {
objectOS.writeObject("minusBtnClicked");
objectOS.writeObject(mainWindow.newOcean.plusMinusClickedIdeaCode);
mainWindow.newOcean.minusBtnClicked = false;
} else if (mainWindow.hotOcean.plusBtnClicked) {
objectOS.writeObject("plusBtnClicked");
objectOS.writeObject(mainWindow.hotOcean.plusMinusClickedIdeaCode);
mainWindow.hotOcean.plusBtnClicked = false;
} else if (mainWindow.hotOcean.minusBtnClicked) {
objectOS.writeObject("minusBtnClicked");
objectOS.writeObject(mainWindow.hotOcean.plusMinusClickedIdeaCode);
mainWindow.hotOcean.minusBtnClicked = false;
} else if (mainWindow.myBtnClicked) {
mainWindow.setMyPg(myProfile, myIdeas, myOpinions);
mainWindow.myBtnClicked = false;
}
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
}
}
int i = 0;
Idea rcvIdea(int _ideaCode) throws ClassNotFoundException, IOException {
objectOS.writeObject("sendIdea");
objectOS.writeObject(_ideaCode);
Idea returnValue = (Idea) objectIS.readObject();
return returnValue;
}
Opinion rcvOpinion(int _opinionCode) throws ClassNotFoundException, IOException {
objectOS.writeObject("sendOpinion");
objectOS.writeObject(_opinionCode);
return (Opinion) objectIS.readObject();
}
Profile rcvProfile(int _idCode) throws IOException, ClassNotFoundException {
objectOS.writeObject("sendProfile");
objectOS.writeObject(_idCode);
return (Profile) objectIS.readObject();
}
void rcvNewIdeasCodes() throws ClassNotFoundException, IOException {
objectOS.writeObject("sendNewIdeasCodes");
newIdeasCodes = (ArrayList<Integer>) objectIS.readObject();
}
void rcvHotIdeasCodes() throws IOException, ClassNotFoundException {
objectOS.writeObject("sendHotIdeasCodes");
hotIdeasCodes = (ArrayList<Integer>) objectIS.readObject();
}
void rcvNewIdeas(int num) throws ClassNotFoundException, IOException {
int i;
rcvNewIdeasCodes();
newIdeas = new ArrayList<>();
if (num <= newIdeasCodes.size()) {
for (i = 0; i < num; i++) {
newIdeas.add(rcvIdea(newIdeasCodes.get(i)));
}
} else {
for (i = 0; i < newIdeasCodes.size(); i++) {
newIdeas.add(rcvIdea(newIdeasCodes.get(i)));
}
}
}
void rcvHotIdeas(int num) throws ClassNotFoundException, IOException {
int i;
rcvHotIdeasCodes();
hotIdeas = new ArrayList<>();
if (num <= hotIdeasCodes.size()) {
for (i = 0; i < num; i++) {
hotIdeas.add(rcvIdea(hotIdeasCodes.get(i)));
}
} else {
for (i = 0; i < hotIdeasCodes.size(); i++) {
hotIdeas.add(rcvIdea(hotIdeasCodes.get(i)));
}
}
}
void sendIdea(Idea _idea) throws IOException {
objectOS.writeObject("rcvIdea");
objectOS.writeObject(_idea);
}
void sendOpinion(Opinion _opinion) throws IOException {
objectOS.writeObject("rcvOpinion");
objectOS.writeObject(_opinion);
}
void sendProfile(Profile _profile) throws IOException {
objectOS.writeObject(_profile);
}
boolean loginCheck() throws HeadlessException, NumberFormatException, IOException, ClassNotFoundException {
objectOS.writeObject("loginCheck");// send command
while (!mainWindow.loginBtnClicked) {
continue;
}
mainWindow.loginBtnClicked = false;
email = mainWindow.emailField.getText().trim();
password = mainWindow.passwordField.getText().trim();
objectOS.writeObject(email);
objectOS.writeObject(password);
boolean valid;
valid = (boolean) objectIS.readObject();
if (valid == false) {
JOptionPane.showMessageDialog(mainWindow, "ID or Password is not correct");
mainWindow.emailField.setText("");
mainWindow.passwordField.setText("");
return false;
} else if (valid == true) {
idCode = (int) objectIS.readObject();
return true;
} else {
return false;
}
}
void updateIdeaDetailMainPanel(Idea clickedIdea) throws ClassNotFoundException, IOException {
ArrayList<Opinion> opinions = new ArrayList<>();
for (int j = 0; j < clickedIdea.opinionCode.size(); j++) {
opinions.add(rcvOpinion(clickedIdea.opinionCode.get(j)));
}
mainWindow.ideaDetailFrame.updateMainPanel(opinions);
}
void updateIdeaDetailFrame(Idea clickedIdea) throws ClassNotFoundException, IOException {
ArrayList<Opinion> opinions = new ArrayList<>();
for (int j = 0; j < clickedIdea.opinionCode.size(); j++) {
opinions.add(rcvOpinion(clickedIdea.opinionCode.get(j)));
}
mainWindow.ideaDetailFrame = new IdeaDetailFrame(clickedIdea, opinions);
mainWindow.ideaDetailFrame.setVisible(true);
}
}
Idea.class
package data;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
public class Idea implements Serializable {
private static final long serialVersionUID = 123123L;
public int idCode;
public int ideaCode;
public int plus = 0, minus = 0;
public String ideaName;
public String oneLineExp;
public String explanation;
public ArrayList<Integer> opinionCode;
public Date date;
public MyCanvas image;
int hotDegree;
public Idea(int _idCode,int _ideaCode, String _ideaName, String _oneLineExp, String _explanation, MyCanvas _image) {
this(_idCode,_ideaName,_oneLineExp,_explanation,_image);
ideaCode = _ideaCode;
}
public Idea(int _idCode, String _ideaName, String _oneLineExp, String _explanation, MyCanvas _image) {
this(_idCode,_ideaName,_oneLineExp,_explanation);
image = _image;
}
public Idea(int _idCode, String _ideaName, String _oneLineExp, String _explanation){
idCode = _idCode;
oneLineExp = new String(_oneLineExp);
ideaName = new String(_ideaName);
explanation = new String(_explanation);
date = new Date();
opinionCode = new ArrayList<>();
}
public void saveIdea() {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("Idea.dat");
oos = new ObjectOutputStream(fos);
oos.writeObject(this);
} catch (IOException e1) {
System.out.println("e1");
}
}
void addOpinionCode(int _opinion) {
opinionCode.add(opinionCode.size(), _opinion);
}
public void incPlus() {
plus++;
}
public void incMinus() {
minus++;
}
public int setHotDegree() {
hotDegree = plus - minus + opinionCode.size() * 2;
return hotDegree;
}
}
Opinion.class
package data;
import java.io.Serializable;
import java.util.Date;
public class Opinion implements Serializable{
int idCode;
public int opinionCode;//the intrinsic code of this opinion
public int commentedIdeaCode;
public String opinion;
public Date date;
int plus, minus;
public Opinion(int _idCode,int _commentedIdeaCode, String _opinion){
idCode = _idCode;
commentedIdeaCode = _commentedIdeaCode;
opinion = new String(_opinion);
date = new Date();
plus = 0;
minus = 0;
}// Opinion(int _idCode,int _commentedIdeaCode, String _opinion)
public Opinion(int _idCode,int _opinionCode,int _commentedIdeaCode, String _opinion){
this(_idCode, _commentedIdeaCode, _opinion);
opinionCode = _opinionCode;
}//Opinion(int _idCode,int _opinionCode,int _commentedIdeaCode, String _opinion)
void incPlus(){
plus++;
}
void incMinus(){
minus++;
}
}
ObjectOutputStream creates a graph of all objects already serialized, and uses references to previously serialized objects. Therefore, when you serialize an Idea instance multiple times, each time after the first, a reference to the first serialization is written instead of the full object.
You can use ObjectOutputStream.reset() after each serialization. This discards the object graph and forces ObjectOutputStream to create new object serializations, even for objects it had seen before.
Your sendIdea method should therefore look like this:
void sendIdea(Idea _idea) throws IOException {
objectOS.flush();
objectOS.reset();
Idea idea = _idea;
objectOS.writeObject(idea);
}
Very importantly, please note that after reset(), all object references are serialized anew. So if you have a complex object graph, you may end up with object duplicates after deserialization.
If you want to share transitive references for an object that is to be serialized multiple times, look into ObjectOutputStream.writeUnshared() instead.

Java warning and error (read object)

My goal: save one ArrayList to a .dat file, after read this file and in the end print this array.
To save the ArrayList, "equipas" is one ArrayList< Equipa>, I use this function:
saveMyFile("Equipas.dat", (Object) equipas);
To read:
public static ArrayList<Equipa> readMyFile(String s){
ArrayList<Equipa> novo = new ArrayList<Equipa>();
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s));
novo = (ArrayList<Equipa>) ois.readObject();
ois.close();
}
catch(IOException er) { System.out.println(er.getMessage()); }
catch(ClassNotFoundException er) { System.out.println(er.getMessage()); }
return novo;}
In this read function, I have one Compilation Warning: "…uses unchecked or unsafe operations. Recompile with - Xlint:unchecked for details."
To save:
public static void saveMyFile(String s, Object o)
{
try {
ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(s));
oos.writeObject(o);
oos.flush();
oos.close();
}
catch(IOException e) { System.out.println(e.getMessage()); }
}
Finally, I want to print the ArrayList's info:
ArrayList<Equipa> cena = new ArrayList<Equipa>();
cena=(ArrayList<Equipa>) readMyFile("Equipas.dat");
for(Equipa e:cena)
e.toString();
Error when I try to run:
" writing aborted; java.io.NotSerializableException: Equipa"
Equipa havs the Serializable:
import java.util.*;
import java.io.*;
public class Equipa implements Serializable
{
private String nome;
private Carro carro;
private ArrayList<Piloto> pilotos;
private double tempoDecorrido;
private int pontos;
private boolean desistiu;
private int voltaDesistencia;
private Piloto piloto;
/**
* Constructor for objects of class Equipa
*/
public Equipa()
{
this.nome = "NA";
this.carro = null;
this.pilotos = new ArrayList<Piloto>();
this.tempoDecorrido = 0;
this.pontos = 0;
this.desistiu = false;
this.voltaDesistencia = 0;
this.piloto = null;
}
public Equipa(String nome, Carro carro, ArrayList<Piloto> pilotos)
{
this.nome = nome;
this.carro = carro;
//this.pilotos = new ArrayList<Piloto>(pilotos);
this.pilotos = pilotos;
this.tempoDecorrido = 0;
this.pontos = 0;
this.desistiu = false;
this.voltaDesistencia = 0;
//this.piloto = pilotos.get(0);
}
public Equipa (Equipa e)
{
this.nome = e.getNome();
this.carro = e.getCarro();
this.pilotos = e.getPilotos();
this.tempoDecorrido = e.getTempoDecorrido();
this.pontos = e.getPontos();
this.desistiu = e.getDesistiu();
this.voltaDesistencia = e.getVoltaDesistencia();
//this.piloto = e.getPiloto();
}
/** Getters */
public String getNome()
{
return this.nome;
}
public Carro getCarro()
{
return this.carro;
}
public ArrayList<Piloto> getPilotos()
{
return new ArrayList<Piloto>(this.pilotos);
}
public double getTempoDecorrido()
{
return this.tempoDecorrido;
}
public int getPontos()
{
return this.pontos;
}
public boolean getDesistiu()
{
return this.desistiu;
}
public int getVoltaDesistencia()
{
return this.voltaDesistencia;
}
public Piloto getPiloto()
{
return this.piloto;
}
/** Setters */
public void setNome(String nome)
{
this.nome = nome;
}
public void setCarro(Carro carro)
{
this.carro = carro;
}
public void setPilotos(ArrayList<Piloto> pilotos)
{
this.pilotos = new ArrayList<Piloto>(pilotos);
}
public void setTempoDecorrido(double tempoDecorrido)
{
this.tempoDecorrido = tempoDecorrido;
}
public void setPontos(int pontos)
{
this.pontos = pontos;
}
public void setDesistiu(boolean desistiu)
{
this.desistiu = desistiu;
}
public void setVoltaDesistencia(int voltaDesistencia)
{
this.voltaDesistencia = voltaDesistencia;
}
public void setPiloto(Piloto piloto)
{
this.piloto = piloto;
}
/** Outros Métodos */
public Equipa clone()
{
return new Equipa(this);
}
public boolean equals(Equipa e)
{
if(this.nome == e.getNome())
return true;
else
return false;
}
public String getStringPilotos()
{
String s = new String();
for(Piloto p: this.pilotos)
s = (s + ", " + p.getNome());
return s;
}
public String toString()
{
return new String("Nome da equipa: " + nome + "; Categoria do carro: " + carro.getClass().getName() + "; Marca e modelo: " + carro.getMarca() + " " + carro.getModelo() + "; Pilotos: " + getStringPilotos())+"\n";
}
Implementing Serializable means that serialization is permitted, but not necessarily that it is possible. For it to work, everything referenced by Equipa must also be either primitive or Serializable (and so on, recursively). Is this the case?
Warning in the read function is the result of generics in java. You won't be able to suppress it, unless you use #SuppressWarnings("unchecked") to ignore it.
If you are sure you are reading an ArrayList<Equipa>, you can ignore it without any problem.
With the Equipa code, I can try to point to the Serializable problem: make sure that Carro and Piloto classes are also Serializables. You can add the code of theses classes if you are not sure.
The only type-safer way would be do a custom serialization, using writeObject(OutputStream) and readObjectInputStream say on a class ArrayListOfEquipa maybe using Equipa[] (ArrayList.toArray()).
Not really attractive, if the warning would be the only reason.

Java: accessing a List of Strings as an InputStream

Is there any way InputStream wrapping a list of UTF-8 String? I'd like to do something like:
InputStream in = new XyzInputStream( List<String> lines )
You can read from a ByteArrayOutputStream and you can create your source byte[] array using a ByteArrayInputStream.
So create the array as follows:
List<String> source = new ArrayList<String>();
source.add("one");
source.add("two");
source.add("three");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (String line : source) {
baos.write(line.getBytes());
}
byte[] bytes = baos.toByteArray();
And reading from it is as simple as:
InputStream in = new ByteArrayInputStream(bytes);
Alternatively, depending on what you're trying to do, a StringReader might be better.
You can concatenate all the lines together to create a String then convert it to a byte array using String#getBytes and pass it into ByteArrayInputStream. However this is not the most efficient way of doing it.
In short, no, there is no way of doing this using existing JDK classes. You could, however, implement your own InputStream that read from a List of Strings.
EDIT: Dave Web has an answer above, which I think is the way to go. If you need a reusable class, then something like this might do:
public class StringsInputStream<T extends Iterable<String>> extends InputStream {
private ByteArrayInputStream bais = null;
public StringsInputStream(final T strings) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
for (String line : strings) {
outputStream.write(line.getBytes());
}
bais = new ByteArrayInputStream(outputStream.toByteArray());
}
#Override
public int read() throws IOException {
return bais.read();
}
#Override
public int read(byte[] b) throws IOException {
return bais.read(b);
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
return bais.read(b, off, len);
}
#Override
public long skip(long n) throws IOException {
return bais.skip(n);
}
#Override
public int available() throws IOException {
return bais.available();
}
#Override
public void close() throws IOException {
bais.close();
}
#Override
public synchronized void mark(int readlimit) {
bais.mark(readlimit);
}
#Override
public synchronized void reset() throws IOException {
bais.reset();
}
#Override
public boolean markSupported() {
return bais.markSupported();
}
public static void main(String[] args) throws Exception {
List source = new ArrayList();
source.add("foo ");
source.add("bar ");
source.add("baz");
StringsInputStream<List<String>> in = new StringsInputStream<List<String>>(source);
int read = in.read();
while (read != -1) {
System.out.print((char) read);
read = in.read();
}
}
}
This basically an adapter for ByteArrayInputStream.
You can create some kind of IterableInputStream
public class IterableInputStream<T> extends InputStream {
public static final int EOF = -1;
private static final InputStream EOF_IS = new InputStream() {
#Override public int read() throws IOException {
return EOF;
}
};
private final Iterator<T> iterator;
private final Function<T, byte[]> mapper;
private InputStream current;
public IterableInputStream(Iterable<T> iterable, Function<T, byte[]> mapper) {
this.iterator = iterable.iterator();
this.mapper = mapper;
next();
}
#Override
public int read() throws IOException {
int n = current.read();
while (n == EOF && current != EOF_IS) {
next();
n = current.read();
}
return n;
}
private void next() {
current = iterator.hasNext()
? new ByteArrayInputStream(mapper.apply(iterator.next()))
: EOF_IS;
}
}
To use it
public static void main(String[] args) throws IOException {
Iterable<String> strings = Arrays.asList("1", "22", "333", "4444");
try (InputStream is = new IterableInputStream<String>(strings, String::getBytes)) {
for (int b = is.read(); b != -1; b = is.read()) {
System.out.print((char) b);
}
}
}
In my case I had to convert a list of string in the equivalent file (with a line feed for each line).
This was my solution:
List<String> inputList = Arrays.asList("line1", "line2", "line3");
byte[] bytes = inputList.stream().collect(Collectors.joining("\n", "", "\n")).getBytes();
InputStream inputStream = new ByteArrayInputStream(bytes);
You can do something similar to this:
https://commons.apache.org/sandbox/flatfile/xref/org/apache/commons/flatfile/util/ConcatenatedInputStream.html
It just implements the read() method of InputStream and has a list of InputStreams it is concatenating. Once it reads an EOF it starts reading from the next InputStream. Just convert the Strings to ByteArrayInputStreams.
you can also do this way create a Serializable List
List<String> quarks = Arrays.asList(
"up", "down", "strange", "charm", "top", "bottom"
);
//serialize the List
//note the use of abstract base class references
try{
//use buffering
OutputStream file = new FileOutputStream( "quarks.ser" );
OutputStream buffer = new BufferedOutputStream( file );
ObjectOutput output = new ObjectOutputStream( buffer );
try{
output.writeObject(quarks);
}
finally{
output.close();
}
}
catch(IOException ex){
fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
}
//deserialize the quarks.ser file
//note the use of abstract base class references
try{
//use buffering
InputStream file = new FileInputStream( "quarks.ser" );
InputStream buffer = new BufferedInputStream( file );
ObjectInput input = new ObjectInputStream ( buffer );
try{
//deserialize the List
List<String> recoveredQuarks = (List<String>)input.readObject();
//display its data
for(String quark: recoveredQuarks){
System.out.println("Recovered Quark: " + quark);
}
}
finally{
input.close();
}
}
catch(ClassNotFoundException ex){
fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
}
catch(IOException ex){
fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
}
I'd like to propose my simple solution:
public class StringListInputStream extends InputStream {
private final List<String> strings;
private int pos = 0;
private byte[] bytes = null;
private int i = 0;
public StringListInputStream(List<String> strings) {
this.strings = strings;
this.bytes = strings.get(0).getBytes();
}
#Override
public int read() throws IOException {
if (pos >= bytes.length) {
if (!next()) return -1;
else return read();
}
return bytes[pos++];
}
private boolean next() {
if (i + 1 >= strings.size()) return false;
pos = 0;
bytes = strings.get(++i).getBytes();
return true;
}
}

Categories