Write an object into hadoop hdfs issue - java

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.

Related

ObjectInputStream not reading full file after appending data

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);
}

How to read the multiple objects text file in java?

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.

Gson, unable to load or save. Giving null object references

Edit for clarification:
Why this does not appear to be a normal null reference is the fact that I have already used this code in another form and have had no issue there. I could manually delete the file from my device and the file will just be replaced later. This should be handled by my try/catch statement where if the file does not exist it will initialize a new object for me.
Furthermore when I get the error in android studio upon running it, the error points directly at the
FileInputStream fis = openFileInput(FILENAME);
Another thing to note is that when I add an item to the object that I am trying to pass into gson I have no issues. The object is created and I have no issue whatsoever adding items to it.
Furthermore as context, I have these two functions in an object class that manages my data for me. I create a single one of these objects as a DataManager and use these functions to save/load (among others) an object that contains all of my data within itself.
When I was putting the class together I had to add that the object class
extends Activity
Because I was getting the fileoutput and fileinput as red functions beforehand. However this seems very sketchy to me (and perhaps explains exactly why I am seeing this error...?)
Original before edit:
In my Android Studio application I've been trying my best to utilize gson and at present I am attempting to save a single object containing multiple attributes using gson.
However I just successfully managed to use this same gson code to put an ArrayList into a file. I could delete that file myself and everything would work just fine. However I am now trying to place an entire object in.
The error is: "java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileOutputStream android.content.Context.openFileOutput(java.lang.String, int)' on a null object reference"
The code looks like the following:
public void loadFromFile() {
try {
FileInputStream fis = openFileInput(FILENAME);
BufferedReader in = new BufferedReader(new InputStreamReader(fis));
Gson gson = new Gson();
// https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/Gson.html, 2015-09-23
Type objectType = new TypeToken<StatisticsRecordObject>() {}.getType();
recordObject = gson.fromJson(in, objectType);
} catch (FileNotFoundException e) {
recordObject = new StatisticsRecordObject();
}
}
public void saveInFile() {
try {
FileOutputStream fos = openFileOutput(FILENAME, 0);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
Gson gson = new Gson();
gson.toJson(recordObject, out);
out.flush(); //same as fflush as before. Buffer must go. FLUSH AFTER WRITING.
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
recordObject = new StatisticsRecordObject();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
I think the NullpointerException says that context object that you call "openFileForOutput" is null
http://developer.android.com/reference/android/content/Context.html#openFileOutput(java.lang.String, int)
You should probably pass in a context to the method and make sure that the context is proper initialised.

Appending New Object to the existing file

Hi I have an issue when trying to append new objects to the existing file..
Once the android app has been lunched again I want to get the existing file and add a new objects then read the objects from the existing file ... Actually, when I'm trying to read the object, the code will read only the first objects .. You can find below the code .. Could you please help ? Thanks
using the following method to write an objects :
public void saveObject(Person p, File f){
try
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f, true));
oos.writeObject(p);
oos.reset();
oos.flush();
oos.close();
}
catch(Exception ex)
{
Log.v("Serialization Save Error : ",ex.getMessage());
ex.printStackTrace();
}
}
Using the following method to read an objects :
public Object loadSerializedObject(File f)
{
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
try{
Object loadedObj = null;
while ((loadedObj = ois.readObject()) != null) {
Log.w(this.getClass().getName(), "ReadingObjects") ;
}
return objects;
}finally{
ois.close();
}
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
Unfortunately you can't create a new ObjectOutputStream every time you want to append to the stream and then read everything back with a single stream. The constructor adds headers to the underlying stream before you start writing objects. You are probably seeing the java.io.StreamCorruptedException: invalid type code: AC exception, that's because the first header is 0xAC.
I don't know how many objects you are dealing with, but one option might be to read all your objects and then rewriting them all using a single ObjectOutputStream. That can get pricy if there are lots of objects. Alternatively, you might want to consider managing the serialization yourself manually through Externalizable. It can get painful though.

How to save the data into File in java?

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) {} }

Categories

Resources