Currently I'm serializing an ArrayList to a file like this:
FileOutputStream fosAlarms = null;
ObjectOutputStream oosAlarms = null;
try {
fosAlarms = openFileOutput("alarms.ser", Context.MODE_PRIVATE);
oosAlarms = new ObjectOutputStream(fosAlarms);
oosAlarms.writeObject(alarms);
System.out.println("Serialisation done");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (oosAlarms != null && fosAlarms != null) {
try {
oosAlarms.close();
fosAlarms.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And this works as intended. But I want this method to overwrite current file (if there is any). If I remove an object from the array and serialize it again, the removed object persists. How do I do this?
Use this constructor of FileOutputStream and set append to false.
FileOutputStream(String, boolean)
So... I guess you need to change a bit your method openFileOutput.
Related
I have the following problems:
I would like to call a function from another class so I added this line of code
Function1 func = new Function1(); and I get an error saying
Function1 (Context) in Function1 cannot be applied to ()
Furthermore, relating to this function and its error, I intend calling the aforementioned function which takes a JSON object and a Filename as parameters and it returns a file, however, when I enter it, I get the following error
Wrong 2nd argument type, found Java.lang.String required Java.io.File
The code in question is this:
JSONObject export = jsonArray1.getJSONObject(index);
File file = func.exportToFile(export, "Export.json");
The fuction in question starts like this:
public void exportToFile(JSONObject objectToExport, File fN)
{
String output = objectToExport.toString();
file_ = fN;
if (!file_.exists()) {
try {
file_.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try{
FileOutputStream fOut = new FileOutputStream(file_);
fOut.write(output.getBytes());
fOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
N.B.: I have tried to call the function like this:
File file = func.exportToFile(export, func.file);
but I only get the error saying incompatible types
Required Java.io.file
Found Void
What have I done wrong?
this func.exportToFile(export, func.file); will not return anything since exportToFile it's a void method .
change your method to make it return file this way :
public File exportToFile(JSONObject objectToExport, File fN) {
String output = objectToExport.toString();
file_ = fN;
if (!file_.exists()) {
try {
file_.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try{
FileOutputStream fOut = new FileOutputStream(file_);
fOut.write(output.getBytes());
fOut.close();
return file_;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
my code has to read in two different Object Types (Bestellung, AKunde) through a ObjectOutputStream and save it in a csv file, which works.
But when i try to read them from the file it doesn't work.
Here is the code:
OutputStream:
LinkedList<Bestellung> bestellListe = verwaltungBestell.getBestellListe();
try {
fileOutputStream = new FileOutputStream(file);
outputStream = new ObjectOutputStream(fileOutputStream);
for (AKunde kunde : kundenliste) {
outputStream.writeObject(kunde);
}
for (Bestellung bestellung : bestellListe) {
outputStream.writeObject(bestellung);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
InputStream:
ArrayList<AKunde> kundenImport = new ArrayList<AKunde>();
ArrayList<Bestellung> bestellungenImport = new ArrayList<Bestellung>();
boolean cont = true;
try {
ObjectInputStream objectStream = new ObjectInputStream(new FileInputStream(directorie));
while (cont) {
AKunde kunde = null;
try {
kunde = (AKunde) objectStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (kunde != null) {
kundenImport.add(kunde);
} else {
cont = false;
}
}
while (cont) {
Bestellung bestellung = null;
try {
bestellung = (Bestellung) objectStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (bestellung != null) {
bestellungenImport.add(bestellung);
} else {
cont = false;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
}
But it won't read the "Bestellungen" and won't save them into "bestellungenImport".
Anyone has a solution???
Your code never reaches the Bestellung reader part.
You have a false assumption that kunde =(AKunde)objectStream.readObject(); returns null.
Instead, it throws exception.
Oneway you can do is cast it like #luk2302.
Another way is to add a object count when writing your object stream:
outputStream.writeInt(kundenliste.size());
for (AKunde kunde : kundenliste) {
outputStream.writeObject(kunde);
}
outputStream.writeInt(bestellListe.size());
for (Bestellung bestellung : bestellListe) {
outputStream.writeObject(bestellung);
}
Then replace your while(cont) loop with a for each loop:
int kundeCount = objectStream.readInt();
for (int i = 0; i < kundeCount; i++) {
// Read and import kunde
}
You need to change your logic for reading objects. There are two main issues:
you never reset cont so the second while loop will never do anything
even if you did that you would always skip the first Bestellung since it was already read when the second loop is reached
I would propose something along the lines of:
Object object = objectStream.readObject();
if (object instanceof AKunde) {
kundenImport.add((AKunde) object);
} else if (object instanceof Bestellung) {
bestellungenImport.add((Bestellung) object);
} else {
// something else was read
}
You simply need to loop over this code and add proper error handling where needed.
I would suggest, you change the way you write your objects to ObjectOutputStream in the first place:
Directly write the kundenListe and bestellListe objects, so you dont't have to worry about types or number of elements when reading the objects again. Your stream of object then always contains two objects, the two lists.
// use try-with-resources if you're on Java 7 or newer
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file))) {
// write the complete list of objects
outputStream.writeObject(kundenliste);
outputStream.writeObject(bestellListe);
} catch (IOException e) {
e.printStackTrace(); //TODO proper exception handling
}
Then you could read it just like that:
ArrayList<AKunde> kundenImport = new ArrayList<>();
ArrayList<Bestellung> bestellungenImport = new ArrayList<>();
//again try-with-resources
try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file))) {
kundenImport.addAll((List) inputStream.readObject());
bestellungenImport.addAll((List) inputStream.readObject());
} catch (IOException | ClassNotFoundException e) { //multi-catch, if Java 7 or newer
e.printStackTrace(); //TODO proper exception handling
}
Further reads:
The try-with-resources Statement
Catching Multiple Exception Types (...)
cur file does not seem to be deleted and temp file does not get renamed.
private class editClassListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
File temp = new File("courseTemp.bin");
File cur = new File("course.bin");
ArrayList<Course> courses = new ArrayList<Course>();
int count = 0;
try {
FileInputStream fin = new FileInputStream(cur);
while(true)
{
try
{
ObjectInputStream oin = new ObjectInputStream(fin);
Course c = (Course) oin.readObject();
courses.add(c);
}catch (EOFException eofException){
break;
} catch (IOException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
while(count < courses.size())
{
if(enterCourseID.getText().equals(courses.get(count).getCourseID()))
{
courses.get(count).setDescription(enterCourseDescription.getText());
courses.get(count).setSemester((String) semesterBox.getSelectedItem());
courses.get(count).setYear(yearBox.getSelectedIndex());
}
}
temp.renameTo(cur);
cur.delete();
temp.delete();
fin.close();
FileOutputStream fos = new FileOutputStream(temp);
courses.trimToSize();
count = 0;
while(count < courses.size())
{
ObjectOutputStream oop = new ObjectOutputStream(fos);
oop.writeObject(courses.get(count));
count++;
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
Both File.delete() and File.renameTo() do not throw an Exception but instead return false if the underlying OS-operation cannot be executed. Reasons for that are dependant on your system, but include among others:
The file you are trying to rename/delete is in use (i. e. open streams)
The file is protected by the OS (insufficient rights)
In case of renaming: A file with the new name already exists
In your case, at least the first point is true. You should be fine by simply closing your FileInputStream fin before trying to delete cur. As for the renaming, you might need to delete cur first before renaming temp.
As an aside, the Utility Class java.nio.file.Files offers methods (move()&delete()) for renaming and deleting, which throw an IOException, if the operation fails, with the cause of failure in the error message.
I am wondering why I get this warning with the new eclipse Juno despite I think I correctly closed everything. Could you please tell me why I get this warning in the following piece of code?
public static boolean copyFile(String fileSource, String fileDestination)
{
try
{
// Create channel on the source (the line below generates a warning unassigned closeable value)
FileChannel srcChannel = new FileInputStream(fileSource).getChannel();
// Create channel on the destination (the line below generates a warning unassigned closeable value)
FileChannel dstChannel = new FileOutputStream(fileDestination).getChannel();
// Copy file contents from source to destination
dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
// Close the channels
srcChannel.close();
dstChannel.close();
return true;
}
catch (IOException e)
{
return false;
}
}
IF you're running on Java 7, you can use the new try-with-resources blocks like so, and your streams will be automatically closed:
public static boolean copyFile(String fileSource, String fileDestination)
{
try(
FileInputStream srcStream = new FileInputStream(fileSource);
FileOutputStream dstStream = new FileOutputStream(fileDestination) )
{
dstStream.getChannel().transferFrom(srcStream.getChannel(), 0, srcStream.getChannel().size());
return true;
}
catch (IOException e)
{
return false;
}
}
You won't need to explicitly close the underlying channels. However if you're not using Java 7, you should write the code in a cumbersome old way, with finally blocks:
public static boolean copyFile(String fileSource, String fileDestination)
{
FileInputStream srcStream=null;
FileOutputStream dstStream=null;
try {
srcStream = new FileInputStream(fileSource);
dstStream = new FileOutputStream(fileDestination)
dstStream.getChannel().transferFrom(srcStream.getChannel(), 0, srcStream.getChannel().size());
return true;
}
catch (IOException e)
{
return false;
} finally {
try { srcStream.close(); } catch (Exception e) {}
try { dstStream.close(); } catch (Exception e) {}
}
}
See how much better the Java 7 version is :)
You should always close in finally because if an exception rise, you won't close the resources.
FileChannel srcChannel = null
try {
srcChannel = xxx;
} finally {
if (srcChannel != null) {
srcChannel.close();
}
}
Note: even if you put a return in the catch block, the finally block will be done.
eclipse is warning you about the FileInputStream and FileOutputStream that you can no longer reference.
I had a class loader working although I am now getting an error after adapting it to my new application. I believe it is because I am converting an integer to a long.
private byte[] loadClassData(String name) {
try {
JarInputStream jis = new JarInputStream(new ByteArrayInputStream(dec));
JarEntry entry = null;
String entryName = null;
while((entry = jis.getNextJarEntry()) != null)
{
entryName = entry.getName();
if(entryName.equalsIgnoreCase(name))
{
try{
classBytes = new byte[(int)entry.getSize()];
jis.read(classBytes, 0, classBytes.length);
return classBytes;
}catch(Exception ex){
ex.printStackTrace();
return null;
}
}
}
return classBytes;
} catch (IOException e) {
e.printStackTrace();
System.out.println(e.getMessage());
} catch (Exception ex) {
ex.printStackTrace();
System.out.println(ex.getMessage());
}
return null;
}
Anyways, that is the basics of it. I am getting an error on the " new byte[(int)entry.getSize()];" part.
"java.lang.NegativeArraySizeException"
Thanks.
Yes, because ZipEntry.getSize() can return -1. Even if it didn't return -1, you shouldn't assume that a single call to read will read all the data. You should read in a loop until the input stream returns -1.
I suggest you use ByteStreams.toByteArray(InputStream) from Guava for this.