How to read the multiple objects in a text file. I am trying to read the text file. I am always get only the first object of the file. How to get the all objects from text file...
List<Processedfile> processfiles = new ArrayList<Processedfile>();
Processedfile processfile = new Processedfile();
processfile.setFilename(filename);
processfile.setCountrow(uploadedFileCount);
processfile.setDate(dateformat);
processfiles.add(processfile);
writeReportTextFile(processfiles);
Write the processedfile object in the text file...
Write the file
public void writeReportTextFile(List<Processedfile> processfiles) {
String processedfilereport = "D:\\PaymentGatewayFiles\\MSSConsolidate\\processedfilereport.txt";
try {
File file = new File(processedfilereport);
FileOutputStream f = new FileOutputStream(file.getAbsoluteFile(), true);
// System.out.println(file);
ObjectOutputStream s = new ObjectOutputStream(f);
// System.out.println("the write"+reportfile);
s.writeObject(processfiles);
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Read the file..
public List<Processedfile> processreportfileread() {
List<Processedfile> a1 = new ArrayList();
String processedfilereport = "D:\\PaymentGatewayFiles\\MSSConsolidate\\processedfilereport.txt";
try {
File file = new File(processedfilereport);
FileInputStream r = new FileInputStream(file);
ObjectInputStream sp = new ObjectInputStream(r);
a1 = (List) sp.readObject();
System.out.println("the list is" +a1);
Iterator i = a1.iterator();
while(i.hasNext()) {
System.out.println("the iterator report is ===="+i.next());
}
}
catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return a1;
}
The object serialization protocol / APIs can cope with a stream containing single object or a sequence of objects. But it cannot cope with a concatenation of streams1 ... which is what your application appears to be creating by opening the output file in "append" mode)
The solution is to NOT write them like that. This:
FileOutputStream f = new FileOutputStream(file.getAbsoluteFile(), true);
is fundamentally wrong. It results in multiple object streams being concatenated. That can't be read.
The correct approach is to either:
assemble all of the Processedfile objects into a single list, and write the list ... with one writeObject call, or
use a sequence of writeObject calls to write the Processedfile objects to a single ObjectOutputStream, or
write the objects to multiple output files, and send the files as a ZIP archive or similar.
1 - To understand why, you need to read the Object Serialization specification, and in particular you need to understand the serialization protocol / format.
Related
I am writing a small program that inserts customer details in ArrayList and write it in file.
The problem is with ObjectOutputStream I was able to append data in file with turning FileOutputStream("",true). But when I try to read data with ObjectInputStream it only reads data that was inserted at first instance. But data is being added to file.
Here is the code -
public void insertCustomer() throws IOException
{
Customer1=new customerDetails("1", "Moeen4", "654654", "asdf", "coding", "student", "65464", "3210");
Customer3=new customerDetails("3", "Moeen5", "888888", "asdf", "coding", "student2", "65464", "321022");
Customer4=new customerDetails("4", "Moeen6", "654654", "asdf", "coding", "student", "65464", "7890");
_list=new ArrayList<customerDetails>();
_list.add(Customer1);
_list.add(Customer3);
_list.add(Customer4);
customersList cl=new customersList();
cl.WriteObjectToFile(files._customers, _list);
ArrayList<customerDetails>li=new ArrayList<customerDetails>();
li= (ArrayList) cl.ReadObjectFromFile(files._customers);
for(int i=0;i<li.size();i++)
{ System.out.println(li.size());
System.out.println(li.get(i).Id);
System.out.println(li.get(i).name);
System.out.println(li.get(i).annual_Salary);
System.out.println(li.get(i).Company);
System.out.println(li.get(i).dateOfBirth);
System.out.println(li.get(i).phone_Number);
}
}
public void WriteObjectToFile(String filepath,Object serObj) {
try {
FileOutputStream fileOut = new FileOutputStream(filepath,true);
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(serObj);
objectOut.close();
System.out.println("The Object was succesfully written to a file");
} catch (Exception ex) {
ex.printStackTrace();
}
}
public Object ReadObjectFromFile(String filepath) {
try {
FileInputStream fileIn = new FileInputStream(filepath);
ObjectInputStream objectIn = new ObjectInputStream(fileIn);
Object obj = objectIn.readObject();
objectIn.close();
System.out.println("The Object has been read from the file");
return obj;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
The real problem here is this:
FileOutputStream fileOut = new FileOutputStream(filepath, true);
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(serObj);
You cannot append to an existing serialization like this. If you do get an exception when attempting to read any objects appended to a pre-existing (non-empty) file.
There is a trick / hack that allows you to append objects though; see Appending to an ObjectOutputStream. (The trick involves suppressing the writing of the object stream header. It is most easily done by overriding the method that does this.)
The other approach is to keep the ObjectOutputStream open between writeObject calls. However there are use-cases where that won't be possible.
Note that there is a semantic difference between these two approaches. The best way to explain it is that the first one behaves as if you called reset() each time you write an object; see the javadoc.
Another thing to note about your example is that your reader code only reads one object. If you want to read multiple objects, you need to call readObject in a loop. And that will only work if you have used the trick / hack above to avoid writing a spurious header.
As suggested the code is only reading the first object and you would need to use a loop to read all the objects from multiple writes.
However -
If you change the above code i.e. ReadObjectFromFile to use a loop this will lead to an StreamCorruptedException: invalid type code: AC. The ObjectOutputStream constructor writes a serialization stream header to the OutputStream i.e. the file, when it is closed and reopend using new ObjectOutputStream and new FileOutputStream(filepath, true) a new header will be written at the append point so you will get an exception as the header is only expected once at the beginning of the file
This will need to be handled e.g.
Use the same ObjectOutputStream for the duration
Override java.io.ObjectOutputStream.writeStreamHeader() to account for append to a file
Change the approach and use List<List<Object>> which you could read, add, write to as a whole.
Loop example would throw exception unless ObjectOutputStream approach is changed
public Object ReadObjectFromFile(String filepath) {
List<List<Object>> objects = new ArrayList<>();
FileInputStream fileIn = new FileInputStream(filepath);
ObjectInputStream objectIn = new ObjectInputStream(fileIn);
try {
while (true) {
List<Object> obj = (List<Object>) objectIn.readObject();
// This will throw StreamCorruptedException: invalid type code: AC
objects.add(obj);
System.out.println("The Object has been read from the file");
}
} catch (EOFException ex) {
// ENDS WHEN ALL READ
} finally {
fileIn.close();
objectIn.close();
}
return objects;
}
Sudo code List<List<Object>> approach -
public void readAndWrite() {
List<Object> customer = List.of(new CustomerDetails(...),
new CustomerDetails(...),
new CustomerDetails(...));
List<List<Object>> objects = readFromFile("existing-customer-file.txt");
objects.addAll(customer);
writeObjectToFile(objects);
}
I am building a basic bank application, although the usage of the java language is intermediate level.
There I am using file input and output a lots. Along the way some questions has popped up in my mind about the file-i/o in java.
1) What if I create two different text file for writing and reading objects? Does it make any difference?
2) How about the specifying path (or giving file name), what if I use // instead of \\?
3) Do I necessarily need to create a new file object like this: File file=new File("C://Users//Documents//NetBeansProjects//BankFile_assignment.txt"); in my specific case?
Last but not least if you may wonder about my file-i/o class:
public class ReaderWriter {
public void writeToFile(List<BankAccount> accounts) {
try {
File file = new File("C://Users//Documents//NetBeansProjects//BankFile_assignment.txt");
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(accounts);//take the arrayList
oos.flush();
oos.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public List<BankAccount> readFromFile() {
List<BankAccount> readData = null;
try {
File file = new File("C://Users//Documents//NetBeansProjects//BankFile_assignment.txt");
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
readData = (List<BankAccount>) ois.readObject();
ois.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
return readData;
}
}
1) Better way is to use databases (mySQL, SQLite,...) to access easily to all your datas without I/O worries.
2) If your application might work on different Operating Systems, a safe way to avoid any trouble with the specific symbol of system ( \ on Windows, / on Unix, Mac) is to use File.separator for example. More about this subject .
3) It must work on Windows, but fails on Unix. You can use (with adaptation for path) this instead of: File file = new File(System.getProperty("user.home")+ File.separator + BankFile_assignment.txt); See this .
I am trying to write an object into hdfs .
Split currentsplit = new Split();
Path p = new Path("C45/mysavedobject");
ObjectOutputStream oos = new ObjectOutputStream(fs.create(p));
oos.writeObject(currentsplit);
oos.close();
But I am not able to get the exact object value.
Path p = new Path("C45/mysavedobject");
Split curntsplit = null;
ObjectInputStream ois = new ObjectInputStream(fs.open(p));
try {
curntsplit = (Split) ois.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ois.close();
Showing duplicate objects value.
In driver i am getting :
objjjjjjj in driver pck.Split#14da173c
After writing the object into file and reading back within driver itself I am getting an alternate object value.
objjjjjj in mysavedobject pck.Split#62eade0
I want the driver object along my Mapper code.
Why is it so?
Your custom Split object (pck.Split) doesn't have a toString method defined so what you're seeing is the class name followed by an address in memory (as Java has no otherway to display to you the string value of that object).
Simply add a toString method implementation to your custom Split class and rerun - now you should be able to confirm whether the written and read object has the same contents.
Well, I am creating dumped objects using a ByteArrayOutputStream. And then will write them to MongoDB as an attribute in my documents. When I read it back how can I convert it to a byte array or a Binary without using a toString in the middle?
This is the way I do it now, and I dont think it is safe:
BasicBSONObject temp = (BasicBSONObject) models.get("0");
model = null;
if (temp != null) {
// TODO fix this serialization!
try {
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(temp.toString().getBytes()));
} catch (IOException e) {
L.error("unable to read model from string!");
L.error(e.getStackTrace().toString());
}
}
I have one problem, that is I have one string of data and I want to save it into a separate file every time. Please give me a suggestion.
Thanks,
vara kumar.pjd
Use a timestamp in the filename so you can be sure it is unique. Below example uses a timestamp in milliseconds which should be enough in most cases.
If you expect you can have multiple files within 1 millisecond then you could do something with a GUID/UUID. Note that GUID/UUID could result in duplicates too, however this chance is extremely rare.
import java.io.*;
class FileWrite
{
public static void main(String args[])
{
try{
// Create file
FileWriter fstream = new FileWriter(System.currentTimeMillis() + "out.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write("Hello Java");
//Close the output stream
out.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
You don't need to compute the filename by yourself, have a look at File.createTempFile.
From the javadoc:
Creates a new empty file in the specified directory, using the given prefix and suffix strings to generate its name. If this method returns successfully then it is guaranteed that:
The file denoted by the returned abstract pathname did not exist before this method was invoked, and
Neither this method nor any of its variants will return the same abstract pathname again in the current invocation of the virtual machine.
This method provides only part of a temporary-file facility. To arrange for a file created by this method to be deleted automatically, use the deleteOnExit() method.
A one liner. Using base 36 for the ids will make the file names shorter.
IOUtils.write(text, new FileWriter(Long.toString(System.currentTimeMillis(), 36)+".txt")));
http://commons.apache.org/io/
One solution can be, use a random number generator to generate a random number. Use this random number with some text as a filename. Maintain a list of already used names and each time you are saving the file, check through this list if the file name is unique.
One of possible ways to get File object with unique name could be:
public static File getUniqueFile(String base, String ext, int index) {
File f = new File(String.format("%s-%03d.%s", base, index, ext));
return f.exists() ? getUniqueFile(base, ext, index + 1) : f;
}
Update: and here goes basic usage/test case:
String s = "foo string\n";
FileWriter writer = null;
for (int i = 0; i < 10; i++) {
File f = getUniqueFile("out", "txt", 0);
try {
writer = new FileWriter(f);
writer.write(s);
writer.close();
writer = null;
} catch (IOException e) {
e.printStackTrace();
break;
}
}
if (writer != null) { try { writer.close(); } catch (Exception e) {} }