I have a class called Parameters, which implements Serializable. But when I use writeObject(p), I got the error message. I checked the status of p. It says it is already Serialized.
package Server.Interface;
import java.util.*;
import java.io.Serializable;
public class Parameters implements Serializable{
private String command;
private String location;
private ArrayList<Integer> numbers;
public Parameters(String command, String location,ArrayList<Integer> numbers) {
this.command = command;
this.location = location;
this.numbers = numbers;
}
public String getCommend() {
return command;
}
public void setCommend(String c) {
this.command = c;
}
public String getLocation() {
return location;
}
public void setNumbers(ArrayList<Integer> numbers) {
this.numbers = numbers;
}
}
The code of client:
public void sendMessage(Parameters p) {
try {
if(p instanceof Serializable){
System.out.println("can be serialized");
}
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(p);
InputStream is=socket.getInputStream();
int attempts = 0;
while(is.available() == 0 && attempts < 1000)
{
System.out.println(attempts);
attempts++;
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("============================");
BufferedReader br=new BufferedReader(new InputStreamReader(is));
System.out.println("============================");
String info=null;
while((info=br.readLine())!=null&&info.length()>0){
System.out.println(info);
break;
}
}
catch (IOException e) {
System.out.println("IOError");
e.printStackTrace();
}
}
This is the message:
can be serialized
IOError
java.io.NotSerializableException: Client.TCPClient
It clearly says that the object is serialized. But writeObject(p) fails. I also tried set the arraylist of p to be null, and it passed. But ArrayList is serializable in default right? It should not affect the serialization.
Related
The streams used to work, but suddenly just stopped two days ago, and I can't get it fixed.
The client creates and successfully sends a User object and a Message object (serialize by the client and deserialize by the server). When the clients receives any of the two classes (serialized by the server and deserialized by the client), I get exceptions, mainly:
java.io.UTFDataFormatException
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTFSpan(ObjectInputStream.java:3704)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3658)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:3458)
at java.base/java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1239)
at java.base/java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:804)
at java.base/java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:988)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2032)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1907)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2209)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
at Model.MessageClient$1.run(MessageClient.java:69)
at java.base/java.lang.Thread.run(Thread.java:833)
Every so often, I get:
java.io.InvalidClassException: Model.Message; class invalid for deserialization
at java.base/java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:174)
at java.base/java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:921)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2210)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
Client side - streams
public MessageClient(String ip, int port, String usernameStr, ImageIcon icon, Controller controller) {
this.user = new User(usernameStr, icon);
this.controller = controller;
this.port = port;
this.ip = ip;
this.messageBuffer = new Buffer<>();
this.contacts = new ArrayList<>(); //(ArrayList<Model.User>) readObjectFromFile("files/contacts");
setUpStreams();
setUpThreads();
}
public void setUpStreams(){
try {
s = new Socket(ip, port);
try {
ois = new ObjectInputStream(s.getInputStream());
oos = new ObjectOutputStream(s.getOutputStream());
oos.writeObject(user);
oos.flush();
users = new ArrayList<>();
setUpThreads();
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void setUpThreads(){
t1 = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
try {
Object o = ois.readObject();
if (o.getClass().isAssignableFrom(Message.class)) {
receiveMessage((Message) o);
}
if (o.getClass().isAssignableFrom(ArrayList.class)) {
updateUsers((ArrayList<Model.User>) o);
}
} catch(EOFException e){
System.out.println("stopped");
t2.stop();
t1.stop();
} catch(IOException | ClassNotFoundException e){
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}
}
}
});
t2 = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
try {
Message currMessage = messageBuffer.get();
oos.writeObject(currMessage);
oos.flush();
} catch(IOException | InterruptedException e){
e.printStackTrace();
}
}
}
});
t1.start();
t2.start();
}
Server-side streams
#Override
public synchronized void run() {
while (socket.isConnected() && !socket.isClosed()) {
try {
Object o = ois.readObject();
ih.addToBuffer((Model.Message) o);
} catch (EOFException e) {
try {
socket.close();
t2.stop();
t1.stop();
} catch (IOException ex) {
ex.printStackTrace();
}
} catch (IOException | ClassNotFoundException e) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
chm.put(user, null);
clients.remove(this);
sendAll(new Message(user.getUsername() + " has disconnected", null));
}
private class InputHandler implements Runnable{
private Buffer<Model.Message> inputBuffer;
public InputHandler(){
inputBuffer = new Buffer<>();
}
public void addToBuffer(Message msg){
inputBuffer.put(msg);
}
#Override
public synchronized void run() {
Object o = null;
while (!Thread.interrupted()) {
Message temp = null;
Message sendable = null;
try {
temp = inputBuffer.get();
sendable = new Message(temp.getText(), temp.getIcon(), temp.getRecipients(), temp.getSender());
sendable.setCurrID();
sendable.setUploaded(new Timestamp(System.currentTimeMillis()));
sendSelect(sendable ,sendable.getSender());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void sendSelect(Message msg, User selectedUser){
Client currClient;
if(!chm.containsKey(selectedUser)) {
try {
oos.writeObject(new Message(selectedUser.getUsername() + "not found", null));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
} else if ((currClient = chm.get(selectedUser)) != null) {
try {
currClient.oos.writeObject((Model.Message) msg);
currClient.oos.flush();
msg.setDownloaded(new Timestamp(System.currentTimeMillis()));
callback.downloadTimestamp(msg);
} catch (IOException e) {
e.printStackTrace();
}
} else {
addUnsent(selectedUser, msg);
}
}
The classes I serialized copy and pasted.
The classpath is the same, all fields are serializable and the have no-arg constructors. I also made sure both encoding on are set to UTF-8
Message
package Model;
import javax.swing.*;
import java.io.*;
import java.sql.Timestamp;
import java.util.LinkedList;
public class Message implements Serializable{
#Serial
private static final long serialVersionUID = -3930131856060689940L;
private static int nextID = 0;
private int currID;
private final String text;
private final ImageIcon icon;
private Timestamp uploaded;
private Timestamp downloaded;
private final User sender;
private final LinkedList<User> recipients;
public Message(){
currID = nextID;
nextID++;
this.text = null;
this.icon = null;
sender = null;
recipients = null;
}
public Message(String text, User sender){
currID = nextID;
nextID++;
this.text = text;
this.icon = null;
this.sender = sender;
this.recipients = null;
}
public Message(String text, ImageIcon icon, User sender) {
currID = nextID;
nextID++;
this.text = text;
this.icon = icon;
this.sender = sender;
this.recipients = null;
}
public Message(String text, ImageIcon icon, LinkedList<User> recipients, User sender) {
currID = nextID;
nextID++;
this.text = text;
this.icon = icon;
this.sender = sender;
this.recipients = recipients;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Message){
if( ((Message) obj).getCurrID() == this.currID ){
return true;
}
}
return false;
}
public String getText() {
return text;
}
public ImageIcon getIcon() {
return icon;
}
public Timestamp getUploaded() {
return uploaded;
}
public Timestamp getDownloaded() {
return downloaded;
}
public Model.User getSender(){return sender;}
public int getCurrID(){return currID;}
public void setCurrID(){currID = nextID; nextID++;}
public LinkedList<User> getRecipients(){
return recipients;
}
public void setUploaded(Timestamp uploaded) {
this.uploaded = uploaded;
}
public void setDownloaded(Timestamp downloaded) {
this.downloaded = downloaded;
}
}
User
package Model;
import javax.swing.*;
import java.io.Serial;
import java.io.Serializable;
public class User implements Serializable{
#Serial
private static final long serialVersionUID = -5886308724572898536L;
private String username;
private ImageIcon image;
public User(String username, ImageIcon image){
this.username = username;
this.image = image;
}
public int hashCode() {
return username.hashCode();
}
public boolean equals(Object obj) {
if(obj!=null && obj instanceof User)
return username.equals(((User)obj).getUsername());
return false;
}
public String getUsername() {
return username;
}
#Override
public String toString(){
return username;
}
}
The issue was I called setUpThread() twice, messing with the input stream. So if you get this kind of problem, make sure you don't initialize your threads (that are reading input stream from the sockets) more than once.
I'm trying to write couple of object using ObjectOutputStream to a file. After that, I read the file with ObjectInputStream. The problem is, I can only read first object in the file. When I opened the file with notepad++, I can see the entries for other objects.
Here writer part
public class FileProcess {
private ObjectOutputStream output;
private Accounts account;
public FileProcess() {}
public void WriteObject(Accounts account) {
this.account = account;
openFile();
addRecords();
closeFile();
}
private void openFile() {
try {
output = new ObjectOutputStream(Files.newOutputStream(Paths.get("record_files.txt"),CREATE,APPEND));
}catch (Exception e) {
System.out.println("\nError opening file");
}
}
private void addRecords() {
try {
output.writeObject(account);
}
catch (Exception e) {
System.out.printf("Error writing file %s",e);
}
}
private void closeFile() {
try {
if(output != null)
output.close();
} catch (Exception e) {
System.out.println("\nError closing file");
}
}
}
And Reader part
abstract class User {
private String userID;
private int password;
private String position;
private ObjectInputStream input;
public User(String userID, int password, String position) {
this.userID = userID;
this.password = password;
this.position = position;
}
boolean signIn() {
boolean found_check = false;
openFile();
found_check = checkRecords();
closeFile();
return found_check;
}
private void closeFile() {
try {
if(input != null)
input.close();
} catch (Exception e) {
System.out.println("Error closing file");
}
}
private boolean checkRecords() {
try {
while(true) {
Accounts account = (Accounts) input.readObject();
System.out.printf("%s %d %s",account.getUserID(),account.getPassword(),account.getPosition());
}
}
catch (Exception e) {
System.out.println("\nError reading file");
return false;
}
return false;
}
private void openFile() {
try {
input = new ObjectInputStream(Files.newInputStream(Paths.get("record_files.txt")));
}catch (Exception e) {
System.out.println("Error opening file");
}
}
}
Accounts class implements Serializable
public class Accounts implements Serializable {
private String userID;
private int password;
private String position;
public Accounts(String userID, int password, String position) {
try {
this.userID = userID;
this.password = password;
this.position = position;
}
catch (Exception e) {
System.out.printf(e.toString());
}
}
}
Your code is throwing the following exception: java.io.StreamCorruptedException: invalid type code: AC.
There's a good question and answer here
This was discovered by adding e.printStackTrace(); to the exception handler in User.checkRecords.
On my serialized XML File is only one attribute of my Object saved, although four should be saved. I think this is due to y XStream Object registering only one converter, although he should register four.
My Converters are all functioning individually. I tested them one by one.
My XML File:
<object-stream>
<model.Product>13</model.Product>
</object-stream>
My Product class which should be saved:
public class Product implements Externalizable, Serializable {
private static final long serialVersionUID = -8437751114305532162L;
#XStreamConverter(converter.NameConverter.class)
private SimpleStringProperty name;
#XStreamConverter(converter.PriceConverter.class)
private SimpleDoubleProperty price;
#XStreamConverter(converter.CountConverter.class)
private SimpleIntegerProperty quantity;
#XStreamConverter(converter.IDConverter.class)
private long id;
public Product(String name, int quantity, double price, long id)
{
this.name=new SimpleStringProperty(name);
this.quantity=new SimpleIntegerProperty(quantity);
this.price=new SimpleDoubleProperty(price);
this.id=id;
//Getter and Setter and implentation of Externalizable
My XStream class
XStream xstream;
ObjectInputStream ois;
ObjectOutputStream oos;
#Override
public void close() throws IOException {
if (oos != null) {
oos.close();
}
if (ois != null) {
ois.close();
}
}
#Override
public void writeObject(Product obj) throws IOException {
try {
oos.writeObject(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
public void open(InputStream input, OutputStream output) throws IOException {
xstream = createXStream(model.Product.class);
converter.ConverterManager con=new ConverterManager();
con.registerAllConverters(xstream);
if (input != null) {
if (input.available() > 0) {
ois = xstream.createObjectInputStream(input);
}
}
if (output != null) {
oos = xstream.createObjectOutputStream(output);
}
}
}
My ConverterManager:
import com.thoughtworks.xstream.XStream;
public class ConverterManager {
public void registerAllConverters(XStream xstream)
{
xstream.aliasAttribute("Product Price", "price");
xstream.registerConverter(new PriceConverter());
xstream.aliasAttribute("Product ID", "id");
xstream.registerConverter(new IDConverter());
xstream.aliasAttribute("Product Name", "name");
xstream.registerConverter(new NameConverter());
xstream.aliasAttribute("Product quantity", "quantity");
xstream.registerConverter(new CountConverter());
}
}
My writeObject, open and close methods are called from this method from another class:
private void saveModel() {
XStreamStrategy s=new XStreamStrategy();
try {
s.open(getFilePath());
} catch (IOException e) {
e.printStackTrace();
}
for(fpt.com.Product p: model)
{
try {
s.writeObject(p);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I have a programm which communicates with MPlayer through Input and Outputstream of the Process.
It works quite good, but I can only communicate with the Process in the Main Thread, and not in any other. Is there a posibility to get arround that?
synchronized-Methods or blocks didn't brought a solution
private String getProperty(String property) {
System.out.println("CurThread: " + Thread.currentThread().getName());
String cmd = "";
cmd = String.format("pausing_keep_force get_property %s", property);
mplayerIn.println(cmd);
mplayerIn.flush();
String rightAnswer = String.format("ANS_%s=", property);
String errorAnswer = "ANS_ERROR";
String answer;
String value = "";
try {
while ((answer = mplayerOut.readLine()) != null) {
if (answer.startsWith(rightAnswer)) {
value = answer.substring(rightAnswer.length());
break;
}
if (answer.startsWith(errorAnswer)) {
value = "";
break;
}
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("Property Error:" + property);
}
return value;
}
edit: ProcessCommunicator
public class ProcessCommunicator extends Thread {
private String cmd;
private BufferedReader is;
private PrintStream os;
List<MessageReceivedListener> listeners;
public boolean addListener(MessageReceivedListener listener) {
return listeners.add(listener);
}
public boolean removeListener(MessageReceivedListener listener) {
if (listeners.contains(listener)) {
return listeners.remove(listener);
}
return false;
}
public ProcessCommunicator(String cmd) {
this.cmd = cmd;
listeners = new ArrayList<>();
}
public void write(String cmd) {
System.out.println(cmd);
os.println(cmd);
os.flush();
}
public void fireEvent(String msg) {
for (MessageReceivedListener listener : listeners) {
listener.received(msg);
}
}
Process p;
#Override
public void run() {
try {
p = Runtime.getRuntime().exec(cmd);
is = new BufferedReader(new InputStreamReader(p.getInputStream()));
os = new PrintStream(p.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
String line;
try {
while ((line = is.readLine()) != null) {
System.err.println(line);
fireEvent(line.trim());
}
} catch (IOException e) {
e.printStackTrace();
}
}
boolean waitForProperty;
String propertyResult;
public String readProperty(String property) {
final String rightAnswer = String.format("ANS_%s=", property);
propertyResult = "";
MessageReceivedListener messageListener = new MessageReceivedListener() {
#Override
public void received(String s) {
if (s.startsWith(rightAnswer)) {
waitForProperty = false;
propertyResult = s.substring(rightAnswer.length());
} else if (s.startsWith("ANS_ERROR")) {
waitForProperty = false;
propertyResult = "";
}
}
};
addListener(messageListener);
waitForProperty = true;
write(String.format("pausing_keep_force get_property %s", property));
int i = 5;
while (waitForProperty && i > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(".");
i--;
}
System.out.println("END");
removeListener(messageListener);
return propertyResult;
}
}
I try to read data from file "sinhvien.dat" then push into array of Student.
My code:
private Student[] docFile() {
Student[] std = null;
FileInputStream f = null;
ObjectInputStream inStream = null;
try {
f = new FileInputStream("student.dat");
inStream = new ObjectInputStream(f);
std = (Student[]) inStream.readObject();// this line throw error
} catch (ClassNotFoundException e) {
System.out.println("Class not found");
} catch (IOException e) {
System.out.println("Error Read file");
} finally {
if (inStream != null) {
try {
inStream.close();
} catch (IOException ex) {
}
}
if (f != null) {
try {
f.close();
} catch (IOException ex) {
}
}
}
return std;
}
Class Student
public class Student implements Serializable { private String studName; Student(String name) { this.studName = name; } public Student() { } public String getStudName() { return studName; } public void setStudName(String studName) { this.studName = studName; } #Override public String toString() { return "Student Name :" + studName; } }
I don't know how to fix this error.
sorry for bad english :(
Exception in thread "Thread-3" java.lang.ClassCastException: btvn_l5.Student cannot be cast to [Lbtvn_l5.Student;
This means, that you cannot cast a single Student-obect into an array of Student-objects.
I think you serialize a Student and try to deserialize a Student[]. Th prefix [L indicates an array.
Take a look at you serializer.