I wrote program for reading and displaying GIS shape files by GeoTools, and I want to save the state of my program.
Main class.java
Project myproject=new Project();
myproject.mapLayers=this.frame.getMapContext().getLayers();
Project.java
import org.geotools.map.MapLayer;
public class Project implements Serializable{
public String name;
public MapLayer[] mapLayers;
public void save(String projectname){
ReadWriteObject.writeObject(projectname+".gpr",this);
}
public Project load(String projectname){
return (Project)ReadWriteObject.readObject(projectname);
}
}
ReadWriteObject
public class ReadWriteObject {
public static boolean writeObject(String filename, Object obj){
try {
FileOutputStream f = new FileOutputStream(new File(filename));
ObjectOutputStream o = new ObjectOutputStream(f);
// Write objects to file
o.writeObject(obj);
o.close();
f.close();
} catch (FileNotFoundException e) {
System.out.println("File not found");
return false;
} catch (IOException e) {
System.out.println("Error initializing stream");
return false;
}
return true;
}
}
Error occurred DefaultMapLayer is not Serializable.
How do I save my programs state in java?
I would simply write out in some format (XML, JSON) the layers, styles that went into your map and then read that back in again to recreate the map. You don't actually need to store the entire state of the program.
Alternatively, you can propose a change to the source code to add Serialize to class. Ideally you should find all of the necessary classes that will need serializing that currently don't implement Serialize and submit a single pull request.
Related
I have class Artical:
first variable is code of artical, second variable is name of article and third is price of article.
public class Artical {
private final String codeOfArtical;
private final String nameOfArtical;
private double priceOfArtical;
public Artical(String codeOfArtical, String nameOfArtical, double priceOfArtical) {
this.codeOfArtical= codeOfArtical;
this.nameOfArtical= nameOfArtical;
this.priceOfArtical= priceOfArtical;
}
public void setPriceOfArtical(double priceOfArtical) {
this.priceOfArtical= priceOfArtical;
}
public String getCodeOfArtical() {
return codeOfArtical;
}
public String getNameOfArtical() {
return nameOfArtical;
}
public double getPriceOfArtical() {
return priceOfArtical;
}
}
I want in main class to write something like:
Artical a1 = new Artical("841740102156", "LG Monitor", 600.00);
new ShowArticalClass(a1).do();
new WriteArticalInFileClass(new File("baza.csv"), a1).do();
so that data in file will be written in format like this:
841740102156; Monitor LG; 600.00;
914918414989; Intel CPU; 250.00;
Those 2 classes ShowArticalClass and WriteArticalInFileClass arent important, those are abstract classes.*
So my question is: How do I set format to look like this, where every line is new Artical.
A very naive implementation can be the following:
Create a class that in turn creates a CSVWriter (assuming you want to write to a CSV). That class will expose a public method allowing you to pass in a path where the desired csv file lives as well as the Artical object you want to write to this file. Using that class you will format your data and write them to the file. An example of this could be:
public class CsvWriter {
private static final Object LOCK = new Object();
private static CsvWriter writer;
private CsvWriter() {}
public static CsvWriter getInstance() {
synchronized (LOCK) {
if (null == writer) {
writer = new CsvWriter();
}
return writer;
}
}
public void writeCsv(String filePath, Artical content) throws IOException {
try (var writer = createWriter(filePath)) {
writer.append(getDataline(content)).append("\n");
}
}
private String getDataline(Artical content) {
return String.join(",", content.getCode(), content.getName(), Double.toString(content.getPrice()));
}
private PrintWriter createWriter(String stringPath) throws IOException {
var path = Paths.get(stringPath);
try {
if (Files.exists(path)) {
System.out.printf("File under path %s exists. Will append to it%n", stringPath);
return new PrintWriter(new FileWriter(path.toFile(), true));
}
return new PrintWriter(path.toFile());
} catch (Exception e) {
System.out.println("An error has occurred while writing to a file");
throw e;
}
}
}
Note that this will take into account where the file provided is already in place (thus appending to it). In any other case the file will be created and written to directly.
Call this write method in a fashion similar to this:
public static void main(String... args) throws IOException {
var artical = new Artical("1", "Test", 10.10);
CsvWriter.getInstance().writeCsv("/tmp/test1.csv", artical);
var artical2 = new Artical("2", "Test", 11.14);
CsvWriter.getInstance().writeCsv("/tmp/test1.csv", artical2);
}
With that as a starting point you can go ahead and modify the code to be able to handle list of Artical objects.
If you really need to support CSV files though I would strongly recommend into looking at the various CSV related libraries that are out there instead of implementing your own code.
How do I write in same text file from different classes in java.
One of the class call method from another class.
I do not want to open BufferedWriter in each class, so thinking if there is a cleaner way to do this ?
So essentially, I want to avoid writing the following code in each class
Path path = Paths.get("c:/output.txt");
try (BufferedWriter writer = Files.newBufferedWriter(path)) {
writer.write("Hello World !!");
}
A good way of doing this is to create a central writing class, that maps from a file name to a reader/writer-object. For example:
public class FileHandler {
private static final Map<String, FileHandler> m_handlers = new HashMap<>();
private final String m_path;
private final BufferedWriter m_writer;
// private final BufferedReader m_reader; this one is optional, and I did not instantiate in this example.
public FileHandler (String path) {
m_path = path;
try {
m_writer = Files.newBufferedWriter(path);
} catch (Exception e) {
m_writer = null;
// some exception handling here...
}
}
public void write(String toWrite) {
if (m_writer != null) {
try {
m_writer.write(toWrite);
} catch (IOException e) {
// some more exception handling...
}
}
}
public static synchronized void write(String path, String toWrite) {
FileHandler handler = m_handlers.get(path);
if (handler == null) {
handler = new FileHandler(path);
m_handlers.put(path, toWrite);
}
handler.write(toWrite);
}
}
Be aware that this behavior does not close the file writers at any point, because you don't know who else is currently (or later on) writing. This is not a complete solution, just a strong hint in a good direction.
This is cool, because now you can "always" call FileHandler.write("c:output.txt", "Hello something!?$");. The FileHandler class could be extended (as hinted) to read files too, and to do other stuff for you, that you might need later (like buffer the content, so you don't have to read a file every time you access it).
What happens during serialization in java, if two object refrences are pointing to the same serializable Object? Does the Serializable Objects get saved twice ?
for example :
class King implements java.io.Serializable {
private String name="Akbar";
}
class Kingdom implements java.io.Serializable {
King goodKing=new King();
King badKing=goodKing;
}
public class TestSerialization {
public static void serializeObject(String outputFileName,
Object serializableObject) throws IOException {
FileOutputStream fileStream=new FileOutputStream(outputFileName);
ObjectOutputStream outStream=new ObjectOutputStream(fileStream);
outStream.writeObject(serializableObject);
outStream.close();
}
public static void main(String[] args) {
Kingdom kingdom=new Kingdom();
try {
TestSerialization.serializeObject("Kingdom1.out", kingdom);
}catch(IOException ex) {
ex.getMessage();
}
}
}
Now, whether only one object state is saved for both goodKing and badKing refrences or the King object get saved twice ?
The documentation for ObjectOutputStream says what happens:
The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields. References to other objects (except in transient or static fields) cause those objects to be written also. Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written.
(My emphasis)
E.g., if you have multiple references to a single object, when the graph is reconstituted, you end up with multiple references to a single reconstituted version of that object, not references to multiple equivalent instances of it.
Of course, if the container being serialized implements a different mechanism, the behavior is dictated by that mechanism, not the default one.
So for instance, if we have Thing and Test:
Thing.java:
import java.io.*;
import java.util.*;
public class Thing implements Serializable {
private Map<String,String> map1;
private Map<String,String> map2;
public Thing() {
this.map1 = new HashMap();
this.map2 = this.map1; // Referring to same object
}
public void put(String key, String value) {
this.map1.put(key, value);
}
public boolean mapsAreSameObject() {
return this.map1 == this.map2;
}
}
Test.java:
import java.io.*;
public class Test implements Serializable {
public static final void main(String[] args) {
try
{
// Create a Thing
Thing t = new Thing();
t.put("foo", "bar");
// Write it out
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("foo"));
os.writeObject(t);
os.close();
os = null;
// Read it in
Thing t2;
ObjectInputStream is = new ObjectInputStream(new FileInputStream("foo"));
t2 = (Thing)is.readObject();
is.close();
is = null;
// Same underlying map for both properties?
System.out.println("t2.mapsAreSameObject? " + t2.mapsAreSameObject());
}
catch (Exception e)
{
System.out.println("Exception: " + e.getMessage());
}
}
}
And run java Test, we get:
t2.mapsAreSameObject? true
...because both of Thing's members, map1 and map2 end up pointing to a single HashMap instance.
I have an array of objects and I want to write them in a text file. So that I can later read the objects back in an array. How should I do it?
Using Serialization.
Deserialization is not working:
public static void readdata(){
ObjectInputStream input = null;
try {
input = new ObjectInputStream(new FileInputStream("myfile.txt")); // getting end of file exception here
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
array = (players[]) input.readObject(); // null pointer exception here
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
readdata();
writedata();
}
The process of converting objects into strings and vice versa is called Serialization and Deserialization. In order to serialize an object it should implement Serializable interface. Most built-in data types and data structures are serializable by default, only certain classes are not serializable (for example Socket is not serializable).
So first of all you should make your class Serializable:
class Student implements java.io.Serializable {
String name;
String studentId;
float gpa;
transient String thisFieldWontBeSerialized;
}
The you can use ObjectOutputStream to serialize it and write to a file:
public class Writer {
static void writeToFile(String fileName, Student[] students) throws IOException {
File f = new File(fileName);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
oos.writeObject(students);
oos.flush();
oos.close();
}
}
ObjectInputStream can be used in a similar way to read the array back from file.
As far as I know, Java doesn't give you an easy way to do this for arbitrary objects. Thus, consider restricting yourself to an array of Serializable.
If the objects you have to handle are of your own classes and you thus want these classes to implement the java.io.Serializable interface, carefully read what 'contract' it comes with, as not all of what you have to guarantee for your class will be enforced programatically at compile-time. (So if your classes implement Serializable without completely following the conditions it poses, you might get runtime errors or just 'wrong' and maybe hard-to-detect runtime behavior.)
(See also these best practices.)
I am trying to serialize this arraylist:
static ArrayList<Product> Chart=new ArrayList<Product>();
with these objects:
double Total;
String name;
double quantity;
String unit;
double ProductPrice
This is the class so far:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Product implements Serializable{
double Total;
String name;
double quantity;
String unit;
double ProductPrice;
public Product(String n)
{
name=n;
}
private void writeObject(ObjectOutputStream s) throws IOException
{
s.defaultWriteObject();
Product pt=new Product(name);
ObjectOutputStream oos=new ObjectOutputStream(s);
oos.writeObject(pt);
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException
{
s.defaultReadObject();
Product pt;
ObjectInputStream ios =new ObjectInputStream(s);
ObjectInputStream ois = null;
pt=(Product)ois.readObject();
}
}
I am trying to serialize and deserialize the arraylist(declared in another class) so that the objects in the arraylist will be saved between runtimes. Any ideas?
Why are you creating new Product objects in these methods? They are not static, so I would assume they should operate on this? You also are trying to call readObject() on an Object you just set to null.
If you can give some more details about the errors you're seeing and how you're using this, we can probably help more.
Edit: Added some sample code
Write it out:
Product p = new Product("My Product");
try
{
FileOutputStream fileOut =
new FileOutputStream("product.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(p);
out.close();
fileOut.close();
} catch(IOException ioe)
{
ioe.printStackTrace();
}
Read it in:
Product p = null;
try
{
FileInputStream fileIn = new FileInputStream("product.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
p = (Product) in.readObject();
in.close();
fileIn.close();
} catch(IOException ioe)
{
ioe.printStackTrace();
return;
} catch(ClassNotFoundException c)
{
System.out.println(.Product class not found.);
c.printStackTrace();
return;
}
It doesn't look like there is any need for Product to provide readObject and writeObject methods. You should just be able to serialise and deserialise the List as is.
I'd suggest wrapping the list in a class that makes sense in the context. (I don't know what the context is, or what the order is (would a Set be better).) Also mutable statics are generally a bad idea, in particular if you are going to try to serialise and deserialise the referenced object.
The ArrayList class already implements Serializable, and you made your class (Product) serializable; everything seems write to me. "so that the objects in the arraylist will be saved between runtimes." You make it sound like you think it should automatically save them between each time you run it; this might be your mistake. You must write it to a file, and read it the next execution (Use ObjectOutput(/Input)Streams)