Cannot read multiple externalizable objects from InputStream [duplicate] - java

This question already has an answer here:
StreamCorruptedException: invalid type code: AC
(1 answer)
Closed 8 years ago.
I have a trouble with reading multiple objects from InputStream(i.e. from file). I receive the exception:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1379)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.socket.Client.readFromFile(Client.java:63)
at com.socket.Client.main(Client.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
I have managed to read/write only one object, it's OK. I can write many objects, it's OK too. But I cannot read more than one object from file. Why does it happen so?
EDIT:
NB! It seems I have faced with the problem of implementing of List in Externalazible class. How to implement it correcly?
My 'Main' code:
public class Client {
public static void main(String[] args) {
if (args[0] == null || args[1] == null) {
System.out.println("No arguments entered!");
System.exit(0);
}
try (Socket clientSocket = new Socket("localhost", 3000);
OutputStream outbound = clientSocket.getOutputStream();
BufferedReader inbound = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));) {
outbound.write((args[0] + "\n").getBytes());
outbound.write("End\n".getBytes());
List<StockQuote> stockQuotes = new ArrayList<>();
String quote;
while (true) {
quote = inbound.readLine();
if (quote != null && quote.equals("End"))
break;
stockQuotes.add(new StockQuote(args[0], new Double(quote)));
}
writeInFile(args[1], stockQuotes);
stockQuotes.clear();
stockQuotes = readFromFile(args[1]);
if (stockQuotes != null)
for (StockQuote stockQuote : stockQuotes)
System.out.println("The " + stockQuote.getSymbol() + " price is " + stockQuote.getPrice());
} catch (UnknownHostException e) {
System.out.println("No such host available!");
} catch (IOException e) {
System.out.println("Server not reachable or down!!");
}
}
private static List<StockQuote> readFromFile(String filename) {
File file = new File(filename);
try (ObjectInputStream readFromFile = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));) {
return (List<StockQuote>) readFromFile.readObject();
} catch (FileNotFoundException e) {
System.out.println("'" + filename + "' is not found in " + file.getPath());
} catch (IOException e) {
e.printStackTrace();
System.out.println("Something gone wrong in the process of reading from '" + file + "'");
} catch (ClassNotFoundException e) {
System.out.println("Cast to class is wrong!");
}
return null;
}
private static void writeInFile(String filename, List<StockQuote> stockQuotes) {
File file = new File(filename);
try (ObjectOutputStream writeInFile = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file, true)));) {
writeInFile.writeObject(stockQuotes);
} catch (FileNotFoundException e) {
System.out.println("'" + filename + "' is not found in " + file.getPath());
} catch (IOException e) {
System.out.println("Something gone wrong in the process of writing to '" + file + "'");
}
}
}
Externalizable 'StockQuote' class:
public class StockQuote implements Externalizable {
private String symbol;
private double price;
private List<StockQuote> stockQuoteList;
public StockQuote() {
}
public StockQuote(String symbol, double price) {
this.symbol = symbol;
this.price = price;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(stockQuoteList);
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
stockQuoteList = (List<StockQuote>) in.readObject();
}
}
Result:
As the result, I receive something like "The null price is 0.0". It says that I serialize my List but my Objects inside it are not serialized, why?
NB!
And could you take me one more tip, how is better to write strings, list and so on in Externalizable classes as out.writeObject or there is beter way to do it?

Your reads and writes are not symmetric.
To write two stock quotes, you
open a new ObjectOutputStream
write a StockQuote
close the ObjectOutputStream
open a new ObjectOutputStream
write a StockQuote
close the ObjectOutputStream
To read these two StockQuotes, you
open an ObjectInputStream
read a StockQuote
read a StockQuote
close the ObjectInputStream
Each time you open a new ObjectOutputStream, a serialization header is written to the underlying stream.
My advice: store all the StockQuotes to a list, and write this list to the ObjectOutputStream when you're done. On the receiver end, read the list.

Related

create a java server socket that waits for messages from client using Thread Pool

#FXML
private TextArea textarea;
#FXML
private ImageView imagev;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
Serverth Server = new Serverth();
Server.start();
}
class Serverth extends Thread {
#Override
public void run() {
try {
final int NUM_THREAD = 99;
ServerSocket socket = new ServerSocket(8078);
ExecutorService exec = Executors.newFixedThreadPool(NUM_THREAD);
System.out.println("SERVER SOCKET CREATED");
while (!isInterrupted()) {
Socket in = socket.accept();
Runnable r = new ThreadedHandler(in);
exec.execute(r);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
class ThreadedHandler implements Runnable {
private Socket incoming;
public ThreadedHandler(Socket in) {
incoming = in;
}
public void run() {
try {
try {
ObjectInputStream is=new ObjectInputStream(incoming.getInputStream());
while(true) {
if (is.available() > 0) {
String line = is.readUTF();
textarea.appendText("\n" + "[" + new java.util.Date() + "] : " + line);
if (line.contains("inviato")) {
Object obj = is.readObject();
Email ema = (Email) obj;
try {
SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy-hh-mm-ss");
FileOutputStream fileOut = new FileOutputStream("src/Server/" + ((Email) obj).getDestinat() + "/" + formatter.format(((Email) obj).getData()) + ".txt");
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(ema);
objectOut.flush();
objectOut.close();
System.out.println("The Object was succesfully written to a file");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
} catch(IOException ex) {
ex.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
incoming.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Inside the run method (in Serveth class), I create a server socket and call exec.execute method.
Inside the run method (in ThreadedHandler class), the server is waiting for messages from the client (in this specific case, it creates a new .txt file but it is not important).
Everything works but causes excessive use of the CPU and lag!!!
InputSteam.available method returns a value instantly, telling you no bytes are available to be read, so this code runs a very "hot" spin loop:
while(true) {
if (is.available() > 0) {
...
}
}
The available method is rarely useful and often gives confusing results (see for example inputstream.available() is 0 always). I would suggest you get rid of the if statement altogether:
while(true) {
String line = is.readUTF();
textarea.appendText("\n" + "[" + new java.util.Date() + "] : " + line);
...
}
There's no way for this your code to exit the loop normally. You may want to add a mechanism for the client to disconnect from the server.

TCP client and server; cmd prompt using object streams issue [duplicate]

I have one client file clientRPC.java and server file serverRPC.java. Both communicate using TCP protocol and use objectinput and output stream to transfer data.
my client file:
public class clientRPC {
public static void main(String args[]) {
Socket s = null;
try {
int serverPort = 8888;
s = new Socket("localhost", serverPort);// server name is local host
//initializing input and output streams object and referencing them to get input and output
ObjectInputStream in = null;
ObjectOutputStream out = null;
out = new ObjectOutputStream(s.getOutputStream());
in = new ObjectInputStream(s.getInputStream());
MathsTutor mt = new MathsTutor();
out.writeObject(mt);
out.flush();
System.out.println("Welcome to Maths Tutor Service. The available maths exercises are:\n"
+ "Addition: Enter 'A' or 'a'\n"
+ "Subtraction: Enter 'S' or 's'\n"
+ "Multiplication: Enter 'M' or 'm'\n"
+ "Division: Enter 'D' or 'd'\n"
+ "Enter 'Q' or 'q' to quit");
//System.out.println();
MathsTutor mt1 = (MathsTutor) in.readObject();
String response = in.readUTF();
System.out.println(response);
} catch (UnknownHostException e) {
System.out.println("Socket:" + e.getMessage());
} catch (EOFException e) {
System.out.println("EOF:" + e.getMessage());
} catch (IOException e) {
System.out.println("readline:" + e.getMessage());
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} finally {
if (s != null) {
try {
s.close();
} catch (IOException e) {
System.out.println("close:" + e.getMessage());
}
}
}
}
}
and my server file :
public class serverRPC extends Thread {
String request;
String response;
public static void main(String args[]) {
try {
int serverPort = 8888;
ServerSocket listen_socket = new ServerSocket(serverPort);
while (true) {
Socket clientSocket = listen_socket.accept();
Connection c = new Connection(clientSocket);
}
} catch (IOException e) {
System.out.println("Listen socket:" + e.getMessage());
}
public serverRPC(String s) {
request = s;
}
}
class Connection extends Thread {
ObjectInputStream in;
ObjectOutputStream out;
Socket clientSocket;
public Connection(Socket aClientSocket) {
try {
clientSocket = aClientSocket;
in = new ObjectInputStream(clientSocket.getInputStream());
out = new ObjectOutputStream(clientSocket.getOutputStream());
this.start();
} catch (IOException e) {
System.out.println("Connection:" + e.getMessage());
}
}
public void run() {
try {
MathsTutor mt = (MathsTutor) in.readObject();
InetAddress ip = clientSocket.getInetAddress();
System.out.println("The Received Message from Client at address:/" + ip.getHostAddress());
System.out.println("====================================");
MathsTutor mt1 = new MathsTutor();
out.writeObject(mt1);
while(true) {
// Read from input
String command = in.readUTF();
System.out.println(command);
}
//System.out.println();
} catch (EOFException e) {
System.out.println("EOF:" + e.getMessage());
} catch (IOException e) {
System.out.println("readline:" + e.getMessage());
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {/*close failed*/
}
}
}
}
The problem is when I run server and then client on cmd, the client side displays the welcome msg and puts cursor on another line for user input but, I can't type anything, the cursor just blinks... I know this might be simple but it has taken already 3 hours for me and I'm stuck in the same thing.
The cursor marked with red keeps blinking but doesn't let me type anything.
You're writing an object with writeObject() and trying to read it with readUTF(). Illogical.
objects written with writeObject() must be read with readObject().
strings written with writeUTF() must be read with readUTF().
primitives written with writeXXX() must be read with readXXX(), for most values of X.

Serialization:java.io.StreamCorruptedException: invalid stream header: 0AACED00

I'm a student practicing my File IO skills and I am coming up against a problem with reading Objects from a file using ObjectInputStream. The code is consistently throwing an InvalidClassException and I can't find how the code is throwing it online or by trial and error. Here's my code:
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class ReadFromFile {
String filename;
List<Object> os;
public ReadFromFile(String filename) {
this.filename = filename;
os = new ArrayList<>();
}
public Object[] readObject() {
try {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.print("reading\n");
while (true) {
os.add(ois.readObject());
System.out.print("read one\n");
}
} catch (EOFException e) {
return os.toArray();
} catch (FileNotFoundException e) {
System.out.print("File not found\n");
return os.toArray();
} catch (ClassNotFoundException e) {
System.out.print("Class not found\n");
return os.toArray();
} catch (StreamCorruptedException e) {
System.out.print("SC Exception\n");
e.printStackTrace();
return os.toArray();
} catch (InvalidClassException e) {
e.printStackTrace();
System.out.print("IC Exception\n");
return os.toArray();
} catch (OptionalDataException e) {
System.out.print("OD Exception\n");
return os.toArray();
} catch (IOException e) {
System.out.print("IO Exception\n");
return os.toArray();
}
}
}
I wrote all of the separate catch blocks to figure out what Exception was being thrown and it always throws the InvalidClassException.
Here also is my Tree Class:
import java.io.Serializable;
public class Tree implements Serializable {
private static final long serialVersionUID = -310842754445106856L;
String species;
int age;
double radius;
public Tree() {
this.species = null;
this.age = 0;
this.radius = 0;
}
public Tree(String species, int age, double radius) {
this.species = species;
this.age = age;
this.radius = radius;
}
public String toString() {
return species + ", age: " + age + ", radius: " + radius;
}
}
And here is my write to file function:
public boolean write(Object object) {
try {
File f = new File(filename);
FileOutputStream fos = new FileOutputStream(f,true);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(object + "\n");
oos.close();
} catch (FileNotFoundException e) {
System.out.print("File Not Found\n");
return false;
} catch (IOException e) {
System.out.print("IOException\n");
return false;
}
return true;
}
Your knowledge is appreciated...
Stack trace:
SC Exception
java.io.StreamCorruptedException: invalid stream header: 0AACED00
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:806)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)
at ReadFromFile.readObject(ReadFromFile.java:17)
at WriteAndRecord.main(WriteAndRecord.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Process finished with exit code 0
java.io.StreamCorruptedException: invalid stream header: 0AACED00
This is caused by appending to the FileOutputStream. As I mentioned in a comment above, you can't append to a stream written by ObjectOutputStream, at least not without special measures. Keep the file and the ObjectOutputStream open until you've written all the objects you want to write, then close it, then deserialize from it.
NB As I also mentioned,
while ((object = in.readObect()) != null)
is not a valid object-reading loop. readObject() doesn't return null at end of stream: it throws EOFException. null can occur anywhere in the stream, any time you write one. The correct form of the loop is:
try
{
for (;;)
{
Object object = in.readObject();
// ...
}
}
catch (EOFException exc)
{
// end of stream
}
// other catch blocks ...
NB 2 This:
oos.writeObject(object + "\n");
should be just
oos.writeObject(object);
Otherwise you're implicity calling toString() and pointlessly appending a line terminator, so the result of readObject() will be a String, not the original object.
I think this was caused by the lack of a serialVersionUID.
Whenever you serialize an object, the ClassLoader needs something to verify the new loaded object against to verify it and ensure its compatibility. In order to do this, you just need to define a field in your class like this:
private static final long serialVersionUID = 12358903454875L;
Your IDE may have also given you a warning stating the lack of it (Eclipse does this).
This should solve your problem.
You can learn more in this excellent answer by Jon Skeet here: What is a serialVersionUID and why should I use it?.

Deserializing an Object only reads one data

how do read file data from file/Deserializing an object.I have created a file which is binary file which contains list of companies data i am able to add new company and its related data but when i want to read back all the file datas it only gives first company datas and it prints null ..what is the problem below is what i have done
public class CompanyInfo extends Company {
int counter=0;
Scanner in=new Scanner(System.in);
private ArrayList<Company> companyinfo;
public CompanyInfo() {
companyinfo=new ArrayList<Company>();
}
public void registercompany() {
System.out.println("Enter Company Name \n");
companyName=in.nextLine();
System.out.println("\n");
System.out.println("Enter Company Code \n");
companyCode=in.nextLine();
System.out.println("\n");
System.out.println("Enter the Share Number \n");
shareNo=in.nextInt();
System.out.println("\n");
System.out.println("Enter Closing Rate \n");
closingRate=in.nextDouble();
Company cin=new Company(companyName,companyCode,shareNo,closingRate);
companyinfo.add(cin);
try {
ObjectOutputStream outObjFile =new ObjectOutputStream(new FileOutputStream("companies.dat",true));
Company company = new Company(companyName,companyCode,shareNo,closingRate);
outObjFile.writeObject(company);
outObjFile.writeChars("\n");
outObjFile.close();
} catch (Exception e) {
// TODO: handle exception
System.out.println("A file error has occurred. Sorry.");
System.out.println( e.getMessage() );
}
counter++;
}
public void viewcompany(){
try {
ObjectInputStream inObjFile = new ObjectInputStream(
new FileInputStream("companies.dat"));
System.out.println(inObjFile.readObject()); // displays first object
Company company = (Company)inObjFile.readObject(); // restores object
System.out.println(company); // displays restored object
inObjFile.close(); // finished with the file now.
} catch (Exception e) {
System.out.println(e.getMessage());
}
I will do two different ways.
Add all details into hashmap and serialize that object. So while reading back, I can search using "key". Key can be name or ID of company. You can do same with ArrayList as well. Search may be difficult. Immutable collections from Guava are less memory used and more better.
Another solution is create object file with key.dat and put into a directory called company. So easy to read back and do search as well.
finally i found the answer ...Hope it helps to others too..good luck
public class CompanyInfo extends Company {
int counter=0;
private static String filename = "company.dat";
Scanner in=new Scanner(System.in);
private ArrayList<Company> companyinfo;
public CompanyInfo() {
companyinfo=new ArrayList<Company>();
}
public void registercompany() {
System.out.println("Enter Company Name \n");
companyName=in.nextLine();
System.out.println("Enter Company Code \n");
companyCode=in.nextLine();
System.out.println("Enter the Share Number \n");
shareNo=in.nextInt();
System.out.println("Enter Closing Rate");
closingRate=in.nextDouble();
Company cin=new Company(companyName,companyCode,shareNo,closingRate);
companyinfo.add(cin);
File file=new File(filename);
boolean append=true;
ObjectOutputStream out=null;
try {
if (!file.exists()||!append) {
out=new ObjectOutputStream(new FileOutputStream(filename));
}
else
{
out=new AppendableObjectOutputStream(new FileOutputStream (filename, append));
}
Company company = new Company(companyName,companyCode,shareNo,closingRate);
out.writeObject(company);
out.flush();
} catch (Exception e){
e.printStackTrace ();
}finally{
try{
if (out != null) out.close ();
}catch (Exception e){
e.printStackTrace ();
}
}
counter++;
}
public void viewcompany(){
try {
List<Object> results = new ArrayList<Object>();
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
try{
while (true) {
results.add(ois.readObject());}
}
catch (OptionalDataException e) {
if (!e.eof) throw e; }
finally {
System.out.println(results);
//System.out.println(((Company)results.get(0)).companyName);
ois.close(); }
}
catch (Exception e){
System.out.println(e.getMessage());
}
}
private static class AppendableObjectOutputStream extends ObjectOutputStream {
public AppendableObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
#Override
protected void writeStreamHeader() throws IOException {}
}
}

Java - passing input into external C/C++ application

I'm trying to enter some value in external application using Java.
Java application looks like this:
Runtime runtime = Runtime.getRuntime();
// ... str build ...
proc = runtime.exec(str);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
bw.write(value);
bw.flush();
bw.close();
if (proc.waitFor() != 0)
// error msg
// the end
Application hangs at waitFor method.
External application looks like this:
welcome banner
please enter 8 character input:
Welcome banner is printed using printf and input is taken with SetConsoleMode/ReadConsoleInput. ReadConsoleInput reads one char and they are masked with * character.
Help
you can use:
proc.getOutputStream().write("some date".getBytes())
keep in mind that you HAVE to read everything the app send to stdout and stderr, else it might get stuck writing there.
I use a generic class to read it in a different thread.
usage is like:
InputStreamSucker inSucker = new InputStreamSucker(proc.getInputStream());
InputStreamSucker errSucker = new InputStreamSucker(proc.getErrorStream());
proc.waitFor();
int exit = process.exitValue();
inSucker.join();
errSucker.join();
InputStreamSucker code is here:
public class InputStreamSucker extends Thread
{
static Logger logger = Logger.getLogger(InputStreamSucker.class);
private final BufferedInputStream m_in;
private final ByteArrayOutputStream m_out;
private final File m_outFile;
public InputStreamSucker(InputStream in) throws FileNotFoundException
{
this(in, null);
}
public InputStreamSucker(InputStream in, File outFile) throws FileNotFoundException
{
m_in = new BufferedInputStream(in, 4096);
m_outFile = outFile;
m_out = new ByteArrayOutputStream();
start();
}
#Override
public void run()
{
try
{
int c;
while ((c = m_in.read()) != -1)
{
m_out.write(c);
}
}
catch (IOException e)
{
logger.error("Error pumping stream", e);
}
finally
{
if (m_in != null)
{
try
{
m_in.close();
}
catch (IOException e)
{
}
}
try
{
m_out.close();
}
catch (IOException e)
{
logger.error("Error closing out stream", e);
}
if (m_outFile != null)
{
byte data[] = m_out.toByteArray();
if (data.length > 0)
{
FileOutputStream fo = null;
try
{
fo = new FileOutputStream(m_outFile);
fo.write(data);
}
catch (IOException e)
{
logger.error("Error writing " + m_outFile);
}
finally
{
try
{
if (fo != null) fo.close();
}
catch (IOException e)
{
logger.error("Error closing " + m_outFile);
}
}
}
}
}
}
public String getOutput()
{
return new String(m_out.toByteArray());
}
}
Got the answer! The trick is to use WriteConsoleInput() API because program expects keyboard event, not text ... That's why the waitFor() waited forever! :)

Categories