I'm trying to append objects to a serialized file but when I read it, it only contains the most recent object instead of all of the objects:
import java.io.*;
public class Main implements Serializable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
TestClass test = new TestClass();
test.username = "this one is second";
test.age = 23;
test.phone = "+1 (010) 000 0000";
test.address = "2 Main St.";
TestClass test2 = new TestClass();
test2.username = "this one is second 22222";
test2.age = 23;
test2.phone = "+1 (010) 000 0000";
test2.address = "2 Main St.";
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("C:\\Java Projects\\ObjectOutputStreamTests\\files\\test.ser"));
out.writeObject(test);
out.writeObject(test2);
out.close();
ObjectOutputStream out2 = new ObjectOutputStream(new FileOutputStream("C:\\Java Projects\\ObjectOutputStreamTests\\files\\test.ser", true)) {
#Override
protected void writeStreamHeader() throws IOException {
reset();
}
};
out2.writeObject(test);
out2.writeObject(test2);
out2.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("C:\\Java Projects\\ObjectOutputStreamTests\\files\\test.ser"));
try {
while ((in.readObject()) != null) {
TestClass testRead = (TestClass) in.readObject();
System.out.println(testRead.username);
System.out.println(testRead.age);
System.out.println(testRead.address);
System.out.println(testRead.phone);
}
} catch (EOFException e) {
System.out.println("end");
}
}
}
TestClass:
import java.io.Serializable;
public class TestClass implements Serializable {
public String username;
public int age;
public String phone;
public String address;
}
When I run this code, I get the second object (test2) printed twice, instead of the first and second object consecutively. This issue persists with more or less objects. How do I fix this?
You are reading the same Object twice for each iteration
while ((in.readObject()) != null) { // once
TestClass testRead = (TestClass) in.readObject(); // twice
You can change your code to
Object obj;
while ((obj = in.readObject()) != null) {
TestClass testRead = (TestClass) obj;
System.out.println(testRead.username);
System.out.println(testRead.age);
System.out.println(testRead.address);
System.out.println(testRead.phone);
}
Note
To get it to work I changed to
FileOutputStream f = new FileOutputStream("C:\\temp\\test.ser", true);
ObjectOutputStream out2 = new ObjectOutputStream(f)
{
#Override
protected void writeStreamHeader() throws IOException {
System.out.println("I am called");
reset();
}
}
;
out2.writeObject(test);
out2.writeObject(test2);
out2.close();
Related
I have 3 Classes: Regulate, Luminosity, Test
From the class Regulate, I which to setting an attribute in the class Luminosity by invoking the method setAttribute
Then in class Test, I calling the method getAttribute.
The problem is, When I calling the method getAttribute, I find a different value that I set it.
This is the Class Luminosity
public class Luminosity{
public static int attribute;
public static int getAttribute(){
return attribute;
}
public static void setAttribute(int v) {
attribute=v;
try {
File fichier = new File("../../WorkspaceSCA/Lamp/value.txt");
PrintWriter pw = new PrintWriter(new FileWriter(fichier)) ;
String ch=Integer.toString(attribute);
pw.append(ch);
pw.println();
pw.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
the Regulate Code:
public class Regulate {
public static void main(String[] args) throws InterruptedException {
Luminosity.setSensedValue(50));
System.out.println("Value of Luminosity= "+ Luminosity.getSensedValue());
}
}
this shows me: Value of Luminosity= 50
Now, I want to recover this value from a different class(Test), like this:
public class Test {
public static void main(String[] args) throws InterruptedException {
System.out.println("Value = "+ Luminosity.getSensedValue());
this shows me: Value= 0
I want to recover the same value.
Thank's in advance
You are start two different classes in two different threads.
Of course Luminosity doesn't have previous value, it was setting in different JVM.
If you want to setup an attribute and transfer it between two threads you can place it in a text file.
public class Luminosity {
private static final String FILE_NAME = "attribute.txt";
private int attribute;
public void writeAttribute(int val) throws IOException {
try (FileWriter fileWriter = new FileWriter(FILE_NAME)) {
fileWriter.append("" + val);
fileWriter.flush();
}
attribute = val;
}
public int readAttribute() throws IOException {
StringBuilder sb = new StringBuilder();
try (FileReader fileReader = new FileReader(FILE_NAME)) {
int r;
while (true) {
char[] buffer = new char[100];
r = fileReader.read(buffer);
if (r == -1) break;
sb.append(new String(Arrays.copyOf(buffer, r)));
}
} catch (FileNotFoundException e) {
return 0;
}
if (sb.length() == 0) return 0;
return Integer.parseInt(sb.toString());
}
public static void main(String[] args) throws IOException {
Luminosity luminosity = new Luminosity();
System.out.println("attribute after start: " + luminosity.readAttribute());
luminosity.writeAttribute(50);
System.out.println("new attribute: " + luminosity.readAttribute());
}
}
I am trying to create a file that stores high scores for a game that I am making. I am using a serializer to write my arrays into a file. The file is created upon running my code but the file is empty (0 bytes). I'm not getting any errors. Can anyone tell me why the file does not contain my data?
public class BestTimes implements Serializable
{
BestTimes[] beginner = new BestTimes[2];
public static void main(String args[]) throws IOException {
BestTimes bestTimes = new BestTimes();
bestTimes.outputToFile();
}
public BestTimes() {
beginner[0] = new BestTimes(1, "John", 10.5);
beginner[1] = new BestTimes(2, "James", 20.3);
}
public int ranking;
public String playerName;
public double time;
public BestTimes(int r, String p, double t)
{
ranking = r;
playerName = p;
time = t;
}
public void outputToFile() throws IOException {
try(FileOutputStream f = new FileOutputStream("bestTimes.txt")) {
ObjectOutputStream s = new ObjectOutputStream(f);
s.writeObject(beginner);
s.flush();
s.close();
} finally {
FileOutputStream f = new FileOutputStream("bestTimes.txt");
f.close();
}
}
}
Of course it's empty. You created a new one in the finally block.
Just remove that code.
I have this code (sorry if I use some terms in Spanish) in Java. All is OK, until I need to write an object in a file with ObjectOutputStream, when printStackTrace says java.io.NotSerializableException.
The code is this.
package agenda;
import java.io.*;
public class Agenda implements java.io.Serializable {
public static void addContact() {
String nom, ap1, ap2, tf, em;
Contact newContact = new Contact("Nombre", "Apellido", "Apellido 2", "Telefono", "Email");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("agenda.pzs", true)) {
oos.writeObject(newContact); // NetBeans says the error is here
} catch (IOException ex) {
ex.printStackTrace(); // This is provisional only
System.out.println("OcurriĆ³ un error inesperado.");
}
}
Sorry for my bad English.
public class Agenda implements java.io.Serializable {
public static void addContact() {
String nom, ap1, ap2, tf, em;
Contact newContact = new Contact("Nombre", "Apellido", "Apellido 2", "Telefono", "Email");
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("agenda.txt",true));
oos.writeObject(newContact);
oos.close();
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("OcurriĆ³ un error inesperado.");
}
}
}
There is mistake with your bracket
and implement Serializable interface in Contact class
All objects inside Serializable class must be Serializable. this requirement is traversable - all objects below must be Serializable too..
BUT...
Assuming that Contact is a third party class or you are not allowed to modify it for any other reason, here is possible solution:
DISCLAIMER: this is tricky, if you don't know "Contact" class well it may cause many unexpected issues. You must make sure that you are able to read/write state of "Contact" class using Serializable blocks. Any change in Contact implementation must be tracked. You need a set of JUnit tests to verify if wrapper is correct.
Now get to the point:
Create ContactWrapper class that will disassemble "Contact" class to serializable class on write() and assemble this class from blocks during read(). More or less something like this:
import static org.junit.Assert.*;
import java.io.*;
import org.junit.Test;
public class Agenda {
#Test
public void addContact() throws ClassNotFoundException, FileNotFoundException, IOException {
String nom, ap1, ap2, tf, em;
Contact newContact = new Contact("Nombre", "Apellido", "Apellido 2", "Telefono", "Email");
ContactWrapper wrapper = new ContactWrapper();
wrapper.setContact(newContact);
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("agenda.pzs"));
oos.writeObject(wrapper);
} finally{
if(oos != null){
oos.close();
}
}
ObjectInputStream ois = null;
ContactWrapper wrapper_new = null;
try{
ois = new ObjectInputStream(new FileInputStream("agenda.pzs"));
wrapper_new = (ContactWrapper) ois.readObject();
} finally {
if(ois != null)
ois.close();
}
assertTrue(wrapper.equals(wrapper_new));
Contact deserializedContact = wrapper.getContact();
//Assuming that contact has corectly implemented equals()...
assertTrue(newContact.equals(deserializedContact));
}
}
================================================
import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class ContactWrapper implements Serializable{
//assume not nulls here...-->equals
private String nom, ap1, ap2, tf, em;
public ContactWrapper(){
}
public void setContact(Contact contact){
//Get State of "Contact" and write it to Serializable objects
nom = contact.getNom();
ap1 = contact.getAp1();
//etc....
}
public Contact getContact(){
//create Contact from serialized objects
return new Contact(nom, ap1, ap2, tf, em);
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException{
System.out.println("write");
out.writeObject(nom);
out.writeObject(ap1);
out.writeObject(ap2);
out.writeObject(tf);
out.writeObject(em);
}
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException{
System.out.println("read");
nom = (String) in.readObject();
ap1 = (String) in.readObject();
ap2 = (String) in.readObject();
tf = (String) in.readObject();
em = (String) in.readObject();
}
private void readObjectNoData()
throws ObjectStreamException{
System.out.println("readNoData");
//set everything to null?
}
#Override
public boolean equals(Object other) {
if(this == other) return true;
if(other instanceof ContactWrapper){
ContactWrapper that = (ContactWrapper)other;
if(this.nom.equals(that.nom) &&
this.ap1.equals(that.ap1)
//...etc etc
){
return true;
}
}
return false;
}
}
Edit:
Source: http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
I want to return an array that is accessible by other objects after having read a text file. My instruction parsing class is:
import java.io.*;
public class Instruction {
public String[] instructionList;
public String[] readFile() throws IOException {
FileInputStream in = new FileInputStream("directions.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int n = 5;
instructionList = new String[n];
for (int j = 0; j < instructionList.length; j++) {
instructionList[j] = br.readLine();
}
in.close();
return instructionList;
}
}
The above takes in a text file with 5 lines of text in it. In my main() I want to run that function and have the string array be accessible to other objects.
import java.util.Arrays;
public class RoverCommand {
public static void main(String[] args) throws Exception {
Instruction directions = new Instruction();
directions.readFile();
String[] directionsArray;
directionsArray = directions.returnsInstructionList();
System.out.println(Arrays.toString(directionsArray));
}
}
What's the best way to do that? I would need the elements of the array to be integers if they are numbers and strings if they are letters. P.S. I'm brand new to Java. is there a better way to do what I'm doing?
You don't have to use generics. I try to catch exceptions in the accessors and return null if anything blows up. So you can test if the value returned is null before proceeding.
// Client.java
import java.io.IOException;
public class Client {
public static void main(String args[]) {
try {
InstructionList il = new InstructionList();
il.readFile("C:\\testing\\ints.txt", 5);
int[] integers = il.getInstructionsAsIntegers();
if (integers != null) {
for (int i : integers) {
System.out.println(i);
}
}
} catch (IOException e) {
// handle
}
}
}
// InstructionList.java
import java.io.*;
public class InstructionList {
private String[] instructions;
public void readFile(String path, int lineLimit) throws IOException {
FileInputStream in = new FileInputStream(path);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
instructions = new String[lineLimit];
for (int i = 0; i < lineLimit; i++) {
instructions[i] = br.readLine();
}
in.close();
}
public String[] getInstructionsAsStrings() {
return instructions; // will return null if uninitialized
}
public int[] getInstructionsAsIntegers() {
if (this.instructions == null) {
return null;
}
int[] instructions = new int[this.instructions.length];
try {
for (int i = 0; i < instructions.length; i++) {
instructions[i] = new Integer(this.instructions[i]);
}
} catch (NumberFormatException e) {
return null; // data integrity fail, return null
}
return instructions;
}
}
check instructionList is null or not. if it is null, call readFile method.
public String[] returnsInstructionList() {
if (instructionList== null){
try { readFile(); } catch(Exception e){}
}
return instructionList;
}
because of readFile can throw exception, it would be good to use one extra variable. like:
private boolean fileReaded = false;
public String[] returnsInstructionList() {
if (!fileReaded){
fileReaded = true;
try { readFile(); } catch(Exception e){}
}
return instructionList;
}
and if readFile can be run concurrently, easiest way to make function synchronized, like
private boolean fileReaded = false;
public synchronized void readFile() throws IOException {
.
.
.
}
public synchronized String[] returnsInstructionList() {
if (!fileReaded){
fileReaded = true;
try { readFile(); } catch(Exception e){}
}
return instructionList;
}
There is no guarantee that readFile is called before returnsInstructionList is invoked. Leaving you returnsInstructionList returning null.
I would :
public String[] getContentsFromFile(String fileName) throws IOException {
FileInputStream in = new FileInputStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int n = 5;
instructionList = new String[n];
for (int j = 0; j < instructionList.length; j++) {
instructionList[j] = br.readLine();
}
in.close();
return instructionList;
}
Part two to the question you can use generics. To achieve what you want but you have to incorporate a way to say what it is.
Eg
public class Foo {
public ReturnForFoo returnAStringOrIntger(boolean val) {
if(val){
return new ReturnForFoo("String", ValueType.STRING) ;
}
return new ReturnForFoo(10, ValueType.INTEGER); //int
}
}
public class ReturnForFoo {
Object value;
ValueType type;
public ReturnForFoo(Object value, ValueType type) {
this.value=value;
this.type=type
}
// Asume you have getters for both value and value type
public static ENUM ValueType {
STRING,
INTEGER,
UNKNOWN
}
}
This code is in your main.
Foo foo = new Foo();
String value;
int val;
ReturnForFoo returnForFoo = foo.returnAStringOrIntger(true);
// NOTE you can use switch instead of if's and else if's. It will be better
if(returnForFoo.getValueType().equals(ValueType.INTEGER)){
val = (int) returnForFoo.getValue();
} else if(returnForFoo.getValueType().equals(ValueType.STRING)){
value = (String) returnForFoo.getValue();
} else {
// UNKOWN Case
}
I'm try to create one simple reservation system, we'll read a file, then we'll add Train, Bus, etc., then we'll writer everything to output.
import java.io.*;
import java.util.*;
public class Company
{
private static ArrayList<Bus> bus = new ArrayList<Bus>();
static int buscount = 0, traincount = 0;
public static void main (String[] args) throws IOException
{
FileParser();
}
public Company()
{
}
public static void FileParser()
{
try {
File file = new File(); //i fill this later
File file2 = new File(); // i fill this later
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(file2);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
String line;
while ((line = br.readLine()) != null)
{
String[] splitted = line.split(",");
if(splitted[0].equals("ADDBUS"))
{
bus.add(buscount) = Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]);
}
}
}
catch (FileNotFoundException fnfe) {
}
catch (IOException ioe) {
}
}
}
I try to read the file line by line. For example one of the line is "ADDBUS,78KL311,10,140,54" I split the line for "," then i try to add every pieces of array to Bus' class' constructor but i couldn't figured it out.
My Bus Class is like `
public class Bus extends Vehicle{
private String command;
private String busName;
private String busPlate;
private String busAge;
private String busSpeed;
private String busSeat;
public Bus(String command, String busname, String busplate, String busage, String busspeed, String busseat)
{
this.command = command;
this.busName = busname;
this.busPlate = busplate;
this.busAge = busage;
this.busSpeed = busspeed;
this.busSeat = busseat;
}
public String getBusName() {
return busName;
}
public void setBusName(String busName) {
this.busName = busName;
}
public String getBusPlate() {
return busPlate;
}
public void setBusPlate(String busPlate) {
this.busPlate = busPlate;
}
public String getBusAge() {
return busAge;
}
public void setBusAge(String busAge) {
this.busAge = busAge;
}
public String getBusSpeed() {
return busSpeed;
}
public void setBusSpeed(String busSpeed) {
this.busSpeed = busSpeed;
}
public String getBusSeat() {
return busSeat;
}
public void setBusSeat(String busSeat) {
this.busSeat = busSeat;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
}
can someone show me a way to solve this problem?
Thank you,
You are missing the keyword new to create a new instance of the class:
bus.add(new Bus(...));
You can add items to ArrayList like this
bus.add( new Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
you were missing new keyword before Bus constructor call. Then you can increment the counter (or do whatever)
bus.add( new Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
buscount++;
try to add new Bus(...)
bus.add( new
Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
As I understand if you want to call constructor you need to call new Bus(parms).
when you say new it will call constructor of your class
when you say this() again it going to call enclosing class' constructor
if you say super() it will call super class' constructor.
if you want it into a map order by counter you can use this:
Map(Integer, Bus) busPosition = new HashMap<>();
busPosition.put(buscount, new
Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));