I am serializing a hash map in my Java code and write it to a file. While deserializing, the file contains more than one values, but it returns only top most key and value pair. Can anyone tell me why? Here is my Java code for deserialization:
public static void main(String[] args) throws IOException, ClassNotFoundException {
HashMap<String, String> data = new HashMap<Integer, String>();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("F:\\f.txt"));
data = (HashMap<String, String>) in.readObject();
for (Map.Entry entry : data.entrySet()) {
System.out.println("key" + entry.getKey());
System.out.println("value" + entry.getValue());
}
}
Here is my serialization code
public class SerializeObject implements Serializable {
public static void main(String[] args) throws IOException, ClassNotFoundException
{
HashMap<String,String> map = new HashMap<String,String>();
map.put("Monday","first");
map.put("Tuesday","Second");
map.put("Wednesday","Third");
FileOutputStream fout=new FileOutputStream("F:\\f.txt",true);
ObjectOutputStream out=new ObjectOutputStream(fout);
out.writeObject(map);
out.flush();
}
}
After deserializing it returns only Monday and first
You should close your streams. out.flush() might not be enough to ensure that all remaining data is written to disk. An easy way to ensure that is to use try-with-resource statements:
public static void main(String[] args) throws IOException, ClassNotFoundException
{
HashMap<String,String> map = new HashMap<String,String>();
map.put("Monday","first");
map.put("Tuesday","Second");
map.put("Wednesday","Third");
try (
FileOutputStream fout=new FileOutputStream("F:\\f.txt",true);
ObjectOutputStream out=new ObjectOutputStream(fout); )
{
out.writeObject(map);
}
}
Related
I'm trying to load a json file, convert it into a ConcurrentHashMap and then write into a csv file with the following code:
My json file is of the form
{"lemmas":{"doc4":"which might make it go wrong","doc3":"and no dirty datum","doc2":"each of vary length","doc1":"you should find that it have five line","doc0":"this be a simple text file"}}
package pipeline;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import helpers.JSONIOHelper;
public class DescriptiveStatistics {
private static void StartCreatingStatistics(String filePath) {
System.out.println("Loading file...");
JSONIOHelper JSONIO = new JSONIOHelper(); // create an object of the JSONIOHelper class
JSONIO.LoadJSON(filePath); // call the LoadJSON method
ConcurrentHashMap<String, String> lemmas = JSONIO.GetLemmasFromJSONStructure();
lemmas.forEach((k, v) -> System.out.printf(" %s%n", v));
CountWordsInCorpus(lemmas); // call this method from the end of the StartCreatingStatistics()
}
private static ConcurrentHashMap<String, Integer> CountWordsInCorpus(ConcurrentHashMap<String, String> lemmas) {
// compile the words in the corpus into a list
ArrayList<String> corpus = new ArrayList<String>();
// store the words together with their frequencies
ConcurrentHashMap<String, Integer> counts = new ConcurrentHashMap<String, Integer>();
for (Entry<String, String> entry : lemmas.entrySet()) {
for (String word : entry.getValue().split(" ")) {
corpus.add(word);
}
}
// getting words and their frequencies
for (String word : corpus) {
if (counts.containsKey(word)) {
counts.put(word, counts.get(word) + 1);
} else {
counts.put(word, 1);
}
}
return counts;
}
// writing into a csv file
private void OutputCountsAsCSV(ConcurrentHashMap<String, Integer> counts, String filename) {
String CSVOutput = new String("");
for (Entry<String, Integer> entry : counts.entrySet()) {
String rowText = String.format("%s,%d\n", entry.getKey(), entry.getValue());
System.out.println(rowText);
CSVOutput += rowText;
System.out.println(CSVOutput);
{
try (FileWriter writer = new FileWriter(filename)) {
writer.write(CSVOutput);
System.out.println("CSV File saved successfully...");
}
catch (Exception e)
{
System.out.println("Saving CSV to file failed...");
}
}
}
}
I now want to call the OutputCountsAsCSV() method to pass the csv file name to it, say 'my_file.csv'.
I am not sure how to do it in the main(String[] args) method.
It is easy to call StartCreatingStatistics(), for example, because there is only one argument, but OutputCountsAsCSV() has two arguments and I do not know how to pass ‘counts’ from ConcurrentHashMap<String, Integer> CountWordsInCorpus() to it as the first argument?
public static void main(String[] args) {
String filePath = "JSON_simple.json";
DescriptiveStatistics newobj = new
DescriptiveStatistics();
newobj.StartCreatingStatistics(filePath);
...
// ConcurrentHashMap<String, Integer> newhashmap =
//newobj.CountWordsInCorpus()
String filename = "my_file.csv";
OutputCountsAsCSV ( newhashmap, filename);
}
So if I try 'ConcurrentHashMap<String, Integer> newhashmap = newobj.CountWordsInCorpus()'; it of course, gives an error 'the method CountWordsInCorpus(ConcurrentHashMap<String, String>)' in the type BDescriptiveStatistics is not applicable for the arguments()'.
how can I do it please?
ConcurrentHashMap<String, Integer> newhashmap = newobj.CountWordsInCorpus()
This line is fine; but it back. Except, the CountWordsInCorpus method has an argument: lemmas. You need to find these lemmas someplace and pass them to this method. Your StartCreatingStatistics method does this, but it calls CountWordsInCorpus, and tosses the result in the garbage.
Perhaps StartCreatingStatistics should return it instead. Now your main can call StartCreatingStatistics, save what it returns, and pass that to OutputCountsAsCSV.
Java object serialization: I serialized this type of Hashtable for example of (Integer,Employee) and when I deserialize this, I would like to put the output in a HashMap. Is this possible? Because I get the java.lang.ClassCastException
public class Employee implements Serializable {
private static final long serialVersionUID = -7260877684654746408L;
private String name;
private int age;
Employee(String n, int a) {
name=n;
age=a;
}
public String toString() {
return "Name: "+name+". "+"Age: "+age+".";
}
}
public class Test {
public static void main(String[] args) {
Hashtable<Integer, Employee> ht = new Hashtable<Integer, Employee>() {
{
put(1, new Employee("John", 37));
put(2, new Employee("Julia", 36));
}
};
//HashMap<Integer,Employee> hm = new HashMap<Integer,Employee>();
try {
FileOutputStream outSer = new FileOutputStream("outSer.ser");
ObjectOutputStream os = new ObjectOutputStream(outSer);
os.writeObject(ht);
os.close();
FileInputStream input = new FileInputStream("outSer.ser");
ObjectInputStream ois = new ObjectInputStream(input);
HashMap<Integer,Employee> hm= (HashMap<Integer, Employee>)ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Is this possible?
Yes. But not the way you coded it. You would have to create your own HashMap and load it from the HashTable:
HashMap<Integer,Employee> hm= new HashMap<>((HashTable<Integer, Employee>)ois.readObject());
Please clear my understanding why I am getting of value of company after deserialization. I know "Statics are implicitly transient, so we don't need to declare them as such."
class Employee implements Serializable {
String name;
static String company = "My Company";
public Employee(String name) {
this.name = name;
}
}
public class Test8 {
public static void main(String[] args) throws Exception {
Employee e = new Employee("John");
serializeObject(e);// assume serialize works fine
Employee e1 = deserializeObject(); // assume deserialize works fine
System.out.println(e1.name + " " + e1.company);
}
public static void serializeObject(Employee e) throws IOException {
FileOutputStream fos = new FileOutputStream("Test8.cert");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(e);
oos.flush();
oos.close();
}
public static Employee deserializeObject() throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("Test8.cert");
ObjectInputStream oos = new ObjectInputStream(fis);
return (Employee) oos.readObject();
}
}
Value of static field company was set first time you used Employee class. In your case it would be in line:
Employee e = new Employee("John");
This value didn't change since it wasn't serialized and deserialized so it stayed the same, which means
System.out.println(e1.name + " " + e1.company);
prints John My Company.
But even if you remove lines
Employee e = new Employee("John");
serializeObject(e);
from your code, and invoke only
public static void main(String[] args) throws Exception {
Employee e1 = deserializeObject(); // assume deserialize works fine
System.out.println(e1.name + " " + e1.company);
}
Employee class will still be loaded inside deserializeObject (by oos.readObject() method) so its static fields will also be properly initialized to its default values.
I have created a method writeFile which writes directly to a File if the flag is true. If the flag is false it reads the File, retrieves the Object, appends something and again saves it to the File. I am getting EOFException when the flag is true.
Here is the whole class I am experimenting with:
public class HandleObjects{
public final static String PATH = "/home/user/Desktop/exp.conf" ;
public static boolean i = true ;
public static void main(String[] args) throws JSONException, IOException, ClassNotFoundException {
JSONObject obj = new JSONObject();
obj.put("id", "something");
JSONObject obj1 = new JSONObject();
obj1.put("key", "xxxxxxxxxxxxxxx");
obj1.put("token", "xxxxxxxxxxxxx");
writeFile(obj,false);
readFile();
writeFile(obj1,true); // Exception occurs here
readFile();
}
public static void writeFile(JSONObject o, boolean flag ) throws FileNotFoundException, IOException, JSONException, ClassNotFoundException{
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(PATH)) ;
JSONObject ob = null ;
if (flag){
ob = readfile();
ob.append("extra", o);
os.writeObject(ob.toString());
}
else{
os.writeObject(o.toString());
}
os.flush() ;
os.close();
}
public static JSONObject readFile() throws FileNotFoundException, IOException, JSONException, ClassNotFoundException{
ObjectInputStream is = new ObjectInputStream(new FileInputStream(PATH)) ;
String str= (String) is.readObject() ;
JSONObject o = new JSONObject(str);
is.close() ;
return o ;
}}`
You've already created a new empty file before you call readfile() when you're in 'append' mode, so of course you get EOF when trying to read an object. There aren't any. You need to call readfile() before creating the FileOutputStream.
This is code to write hashtable to .txt file !
public static void save(String filename, Map<String, String> hashtable) throws IOException {
Properties prop = new Properties();
prop.putAll(hashtable);
FileOutputStream fos = new FileOutputStream(filename);
try {
prop.store(fos, prop);
} finally {
fos.close();
}
}
How we getback the hashtable from that file ?
Thanks
In the very same ugly manner:
#SuppressWarnings("unchecked")
public static Map<String, String> load(String filename) throws IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(filename);
try {
prop.load(fis);
} finally {
fis.close();
}
return (Map) prop;
}
Use Properties.load()
code example:
public static Properties load(String filename) {
FileReader reader = new FileReader(filename);
Properties props = new Properties(); // The variable name must be used as props all along or must be properties
try{
props.load(reader);
} finally {
reader.close();
}
return props;
}
Edit:
If you want a map back, use something like this. (The toString is to avoid a cast - you can cast to String if you would prefer)
public static Map<String, String> load(String filename) {
FileReader reader = new FileReader(filename);
Properties props = new Properties();
try {
props.load(reader);
} finally {
reader.close();
}
Map<String, String> myMap = new HashMap<String, String>();
for (Object key : props.keySet()) {
myMap.put(key.toString(), props.get(key).toString());
}
return myMap;
}