I have an issue while reading the data from a file using objectInputStream. Please find the code below
File file = new File("model.pst")
if (file.exists()) {
fis = new FileInputStream(file);
in = new ObjectInputStream(fis);
input = (List<GlobalModel>) in.readObject();
in.close();
}
I got to know from the ObjectOutputStream http://docs.oracle.com/javase/6/docs/api/java/io/ObjectOutputStream.html docs, that while writing the object to the file, he 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.I have an issue where the class name has been changed after writing the object to the file and when I use the above code to read the values, its throwing a classNotFound exception. I would like to know if there is a way, I can handle this exception, i.e once it comes to the exception block, can I replace the classname in the object that is being read to the new class name and make it work ?
Please Assist. Thanks in Advance
I've never done this myself but it should be possible to replace a class by another by making a subclass of object input stream and overriding the resolveClass method, http://docs.oracle.com/javase/6/docs/api/java/io/ObjectInputStream.html#resolveClass(java.io.ObjectStreamClass)
Related
I have tried to serialize an object of type
HashMap<UUID, ArrayList<String>>
Knowingly, Hashmap is Serializable, UUID, ArrayList, and String are too.
I have debugged the value of the map, and the path, they're correct, no error is throws and the code seems to successfully run, however nothing is being written into the file...
Here's the code:
try
{
FileOutputStream fos = new FileOutputStream(file.getPath());
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(serializable);
oos.close();
fos.close();
System.out.println("Success serialization - " + serializable + " at path " + file.getPath());
}catch(Exception e)
{
e.printStackTrace();
}
The results of the syso were valid, not a null nor an empty table, and a correct path, a file exists in that dictionary and everything...
does anyone know why it wouldn't work?
I tried googling but all I saw were cases where an error was thrown or an incorrect path was used etc...
EDIT
the "serializable" is the table. I made a serialize method taking a file and a Serializable type, and a HashMap is so it passes
Alright, I figured it out.
When I originally made the class that handled it, it also used another something that is made for something else(mostly human-readable text), which interfered with it.
I then tested by creating another class purely for serialization, and it worked!
I am sorry I bothered ya'll, and thanks for #markspace for the help!
Tho that it shouldn't have interfered.. it seems to have done it so I am glad I figured it out
I am new to programming, I need help in understanding the difference between 2 ways of creating a fileinputstream object for reading files. I have seen examples on internet, some have used first one and others second one. I am confused which is better and why?
FileInputStream file = new FileInputStream(new File(path));
FileInputStream file = new FileInputStream(path);
Both are fine. The second one calls the first implicitly.
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
If you have a reference to the file which should be read, use the former. Else, you should probably use the latter (if you only have the path).
Don't use either in 2015. Use Files.newInputStream() instead. In a try-with-resources statement, at that:
final Path path = Paths.get("path/to/file");
try (
final InputStream in = Files.newInputStream(path);
) {
// do stuff with "in"
}
More generally, don't use anything File in new code in 2015 if you can avoid it. JSR 203, aka NIO2, aka java.nio.file, is incomparably better than java.io.File. And it has been there since 2011.
The FileInputStream Class has three constructors. Described in the official documentation:
FileInputStream(File file)
Creates a FileInputStream by opening a connection to an actual file, the file named by the File object file in the file system.
FileInputStream(String name)
Creates a FileInputStream by opening a connection to an actual file, the file named by the path name name in the file system.
FileInputStream(FileDescriptor fdObj)
Creates a FileInputStream by using the file descriptor fdObj, which represents an existing connection to an actual file in the file system.
As you see here there is no real difference.
Actually they both have the same way to open a file. The first constructor calls
SecurityManager.checkRead(File.getPath())
And the second one uses the same checkRead() as
SecurityManager.checkRead(name)
if you want use
FileInputStream file = new FileInputStream(new File(path));
for create FileInputStream need more time, if I don't mistake, because this constructor doing some checks with security manager
There is not much difference between the two , as
FileInputStream file = new FileInputStream(path)
implicitly calling other.
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
But to make better use of two available constructors, we can use constructor taking File argument when there is already a File object so we will be avoiding creation of another file object which will be created implicitly If we are using another constructor
Secondly, It is better to create FileinputStream object only after checking the existence of file which can be checked by using file.exists() in that case we can avoid FileNotFoundException.
It's possible to save class from URLClassLoader to normal file.class? and then decompile it?
I trying save it just as object using
Class<?> clazz = classLoader.loadClass("foo.Bar");
FileOutputStream sf = new FileOutputStream(f);
ObjectOutputStream s = new ObjectOutputStream(sf);
s.writeObject(clazz);
s.close();
Bu that don't work.
So... how to decompile it? I need get something like result of jd-gui, but using class from URLClassLoader.
You need to map the class name (e.g. "foo.Bar") to a resource path name (e.g. "/foo/Bar.class") and then use classLoader.getResourceAsStream to open a stream to read the bytecode file.
In theory, this can then be fed to a decompiler ... assuming that you have a decompiler that can read from an InputStream.
What you are doing at the moment fails because a Class object cannot be serialized.
Do a simple HTTP download, rather than URLClassLoader, to get the class into a file. Then decompile that.
(Writing an object to an ObjectOutputStream only saves the data in an instance of the object, and even that works only if the object has implemented Serializable. Not what you're looking for here.)
In previous code in my program, I had saved an ArrayList (consisting of objects of a custom class called location as you can see in my code) in a file using ObjectOutputStream and FileOutPutStream. However, when trying to retrieve the object from the file, using ObjectInputStream, I am getting an error saying that I have an unhandled exception (ClassNotFoundException).
Here's the code I used to get the ArrayList out of the file:
String file = "file";
ObjectInputStream input = new ObjectInputStream(new FileInputStream("file"));
ArrayList<location> arrayList = new ArrayList<location>();
arrayList = (ArrayList) input.readObject();
The error is on the line where I call the .readObject() method. Any Help will be appreciated as I am new to Java. Thank You!
That means the class you sent could not be found in your app. You have to add it to the class path of the app, or only send classes the app has. In your case, the missing class will be in the ArrayList as ArrayList will always be there.
Nothing mysterious is going on, the error means just what it says.
It would be more useful if the exception told you which class was missing. I think Java 7 does this now.
honestly I'm not very experienced with exception handling, because often for my laziness I tend to not handle exceptions. So here's a very basic question.
I would like to know what's the cleanest way to accomplish this situation, with an exception handling approach:
I have a class (ConfigManager) that reads a file within its constructor, and need that file to exists to be constructed correctly, given as the constructor parameter.
If the file doesn't exist, I would like to catch the FileNotFoundException, create the file with some defaults values, and continue the creation of the ConfigManager object with the default config file now available.
Here's some code:
class ConfigManager{
ConfigManager(String file){
try{
builder = builderFactory.newDocumentBuilder();
document = builder.parse (new FileInputStream(file));
....
}catch (FileNotFoundException e) {
File configFile = new File (file);
try {
configFile.createNewFile();
BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
writer.write(this.defaultConfig);
writer.close();
return new ConfigManager(string); //Here's the problem. I can't do that but I need to try build ConfigManager again. How do that?
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
How to construct a new ConfigManager object, after the default config file has been created?
Is that the rigth way to handle such type of exception?
thanks in advance
What you can do is ensure the file exists before attempting to parse it.
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
writer.write(defaultConfig);
writer.close();
fis = new FileInputStream(file);
}
try{
builder = builderFactory.newDocumentBuilder();
document = builder.parse (fis);
don't do the reading file in the constructor, create a method (possibly private) that does the reading of the file and setting of the values on the ConfigManager.
Then in the constructor, where you try to call the constructor again, just call the method.
i.e. dont call the constructor again.
update -- I would organize the code like this:
ConfigManager(String fileName) {
File file = new File(fileName);
if (!file.exists()){
// create this method -- Im assuming its ok to put the default
// config on the path where the file did not exist.
createDefaultConfigFile(fileName);
}
parseConfigFile(fileName, ...); // create this method too
}
this is obviously not working code, and I dont know specifically what you are doing so its as far as I can go. But its more readable than what you have now, and a bit more organized. Also, do you really want to create a new default config file if the specified one does not exist? Why not pop up a warning saying the config did not exist so you are using defaults, but not write the default file? You might have a reason to write the default, and if thats true then ok, but if you don't have to, don't add more work...
The solution is to partition your constructor into two parts. The first part tries to create the FileInputStream from the existing file. If it throws the FileNotFoundException, then you create and populate the file as above, and then open the FileInputStream again. The second part takes the file FileInputStream opened by the first part (regardless of how it was opened) and proceeds with initialization.
Another option is to defer this loading to an init() method, so that consumers of your class must both create and initialize their objects.
You need to be able to call the constructor again, but without creating a new object - just calling it on the same object. Since Java doesn't allow you to do that, you have to create an auxillary method, move the code from the constructor into that, and then call the new method from the constructor.
This is a basic technique for any situation where you need to implement recursion, but you can't directly recurse.
The cleanest way of accomplishing this is not to perform any operations that can result in exceptions in the constructor. If you absolutely need to perform them before your object can be used, do them in a separate method init().
Try delegating the parsing of the configuration file to another method. That way, you can check if the file exists first and then either create a default one, or pass the existing one to this new method.
Well, actually you have a new instance of ConfigManager after the constructor was executed without an error. So all you have to to is to just remove the line in question.
Or consider using a static initializer. This will check for the file only once, when your application is deployed/started.
often for my laziness I tend to not
handle exceptions
I suggest you fix the laziness first. In reality you are just creating more work for yourself further down the line.