I developed an app where I am backing up and restoring app data. The backup data is stored in .zip format in phone directory. While restoring I am unzipping the file till here everything works fine. But, if the backup contain images as data, while restoring they are not opening in app and giving an error. The code written for unzipping file is written as
public void DBimport(String inFileName) {
opener= new DataBaseOpener(mApp);
final String outFileName = mContext.getDatabasePath(opener.getDatabaseName()).toString();
try {
File dbFile = new File(inFileName);
FileInputStream fis = new FileInputStream(dbFile);
ZipInputStream zipInputStream= new ZipInputStream(fis);
ZipEntry zipEntry= zipInputStream.getNextEntry();
while(zipEntry!=null) {
String fileName=zipEntry.getName();
File newFile= new File(outFileName/* + File.separator + fileName*/);
new File(newFile.getParent()).mkdirs();
// Open the empty db as the output stream
OutputStream output = new FileOutputStream(newFile);
// Transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = zipInputStream.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
// Close the streams
output.flush();
output.close();
zipEntry=zipInputStream.getNextEntry();
}
zipInputStream.closeEntry();
fis.close();
Toast.makeText(mContext, "Restore Completed", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(mContext, "Unable to Restores. Retry", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
}
May I know where I am going wrong ? and how to resolve this issue. any suggestions will be helpful.
Related
I am trying to transfer a video file from an RPi hotspot to my a directory on my phone over WiFi. I have been able to successfully create a folder in my storage, connect with the RPi server, and receive data. However, the file that appears after being written isn't correct. In fact, when I try to open it, it just opens a separate, unrelated app on my phone. Very weird!
Here is the code in question:
try {
BufferedInputStream myBis = new BufferedInputStream(mySocket.getInputStream());
DataInputStream myDis = new DataInputStream(myBis);
byte[] videoBuffer = new byte[4096*2];
int i = 0;
while (mySocket.getInputStream().read(videoBuffer) != -1) {
Log.d(debugStr, "while loop");
videoBuffer[videoBuffer.length-1-i] = myDis.readByte();
Log.d(debugStr, Arrays.toString(videoBuffer));
i++;
}
Log.d(debugStr, "done with while loop");
// create a File object for the parent directory
File testDirectory = new File(Environment.getExternalStorageDirectory()+File.separator, "recordFolder");
Log.d(debugStr, "path made?");
if(!testDirectory.exists()){
testDirectory.mkdirs();
}
Log.d(debugStr, "directory made");
// create a File object for the output file
File outputFile = new File(testDirectory.getPath(), "recording1");
Log.d(debugStr, "outputfile made");
// now attach the OutputStream to the file object, i
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
Log.d(debugStr, "write to file object made");
fileOutputStream.write(videoBuffer);
Log.d(debugStr, "video written");
fileOutputStream.close();
Log.d(debugStr, "done");
} catch (IOException e1) {
e1.printStackTrace();
}
The video is initially in .h264 format and is being sent as a byte array. The file is 10MB in size. In my while loop, I print out the value of the array as a string, and it prints a lot of data. Enough data for me to suspect that all the data is being sent. When I navigate to the folder it should be in, there is a file with the name I gave it, "recording1", but it is only 8KB in size.
Any ideas on what is going on? Any help is greatly appreciated!
Android FileOutputStream seems to fail
No it doesn't. Your code seems to fail. That's because your code makes no sense. You're throwing away large chunks of data, more or less accumulating only 1 out of every 8192 bytes; you're using both buffered and unbuffered reads; you're limiting the input to 8192 bytes; and you're never closing the input. And if the input is larger than 8192*8193 you can get an ArrayIndexOutOfBoundsException.
Throw it all away and use this:
try {
File testDirectory = new File(Environment.getExternalStorageDirectory()+File.separator, "recordFolder");
if(!testDirectory.exists()){
testDirectory.mkdirs();
}
File outputFile = new File(testDirectory, "recording1");
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile));
BufferedInputStream in = new BufferedInputStream(mySocket.getInputStream())) {
byte[] buffer = new byte[8192]; // or more, whatever you like > 0
int count;
// Canonical Java copy loop
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
This is a function I have written that tries to:
Create a folder with the users name
Save a .jpg inside of that
folder
The folder creation works fine, however when I try to save the pictures, they all save with the correct name, however they do not save in their intended folders. In other words, instead of having a folder containing a bunch of folders each containing one picture, I have one folder containing a bunch of empty folders, and a bunch of pictures all outside their folders (I can clarify if needed).
This is my code:
public void addToDir(List<Contact> list){
for(int i = 0; i < list.size(); i++){
String nameOfFolder = list.get(i).getName();
Bitmap currentBitmap = list.get(i).getBusiness_card();
String conName = Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator +
"Connected Accounts" + File.separator + nameOfFolder;
File conDir = new File(conName);
if (!conDir.mkdirs()) {
if (conDir.exists()) {
} else {
return;
}
}
try {
FileOutputStream fos = new FileOutputStream(conName + ".jpg", true);
currentBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (Exception e) {
Log.e("MyLog", e.toString());
}
}
}
I suspect the problem is with the FileOutputStream path, but I am not sure how to set it so that it is set to the folder I just created.
Much appreciated
This is how to define mFileTemp
String state = Environment.getExternalStorageState();
File mFileTemp;
if (Environment.MEDIA_MOUNTED.equals(state)) {
//this is like that
//directory : any folder name/you can add inner folders like that/your photo name122412414124.jpg
mFileTemp = new File(Environment.getExternalStorageDirectory()+File.separator+"any folder name"+File.separator+"you can add inner folders like that"
, "your photo name"+System.currentTimeMillis()+".jpg");
mFileTemp.getParentFile().mkdirs();
}
else {
mFileTemp = new File(getFilesDir()+"any folder name"+
File.separator+"myphotos")+File.separator+"profilephotos", "your photo name"+System.currentTimeMillis()+".jpg");
mFileTemp.getParentFile().mkdirs();
This is how i save any image
try {
InputStream inputStream = getContentResolver().openInputStream(data.getData());
FileOutputStream fileOutputStream = new FileOutputStream(mFileTemp);
copyStream(inputStream, fileOutputStream);
fileOutputStream.close();
inputStream.close();
} catch (Exception e) {
Log.e("error save", "Error while creating temp image", e);
}
And copyStream method
public static void copyStream(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
}
I have this method that zips files from a List and another method that uses this for send it with mail through intent.
My problem is that when I send it two or three times the app crashes and shows me this.
E/StrictMode: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
java.lang.Throwable: Explicit termination method 'close' not called
at dalvik.system.CloseGuard.open(CloseGuard.java:184)
at java.io.FileOutputStream.<init>(FileOutputStream.java:89)
at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
at com.waffles.vatsandbats.VisaDatai.zip(VisaDatai.java:1172)
at com.waffles.vatsandbats.VisaDatai.sendZippedMail(VisaDatai.java:207)
at com.waffles.vatsandbats.VisaDatai.getFiles(VisaDatai.java:298)
at com.waffles.vatsandbats.VisaDatai$7$1.run(VisaDatai.java:1823)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:211)
at android.app.ActivityThread.main(ActivityThread.java:5373)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)
The main problem (I think) is in this message
at com.waffles.vatsandbats.VisaDatai.zip(VisaDatai.java:1172)
That refers to this
in = new FileInputStream(files.get(i)
.getCanonicalFile());
Here's the method that creates the zip and that has the error code
public static File zip(List<File> files, String filename) {
File zipfile = new File(filename);
// Create a buffer for reading the files
FileInputStream in=null;
byte[] buf = new byte[1024];
try {
// create the ZIP file
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
zipfile));
// compress the files
for (int i = 0; i < files.size(); i++) {
in = new FileInputStream(files.get(i)
.getCanonicalFile());
// add ZIP entry to output stream
out.putNextEntry(new ZipEntry(files.get(i).getName()));
// transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
// complete the entry
out.closeEntry();
in.close();
}
// complete the ZIP file
out.close();
return zipfile;
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
The list of files that I zip is several PrintedPdfDocuments with images and texts (this class has it owns disadvantages but Im lazy changing that right now)
I just can't find the problem. Maybe I need to change the method that zips. Any suggestions?
You should close your streams in a finally block to make sure they are closed properly even when an exception occurs.
Also using getCanonicalFile() creates a new file when you are creating your FileInputStream. You probably want:
in = new FileInputStream(files.get(i));
I solved it. I closed the FileInputStream inside the for loop. So every time it looped and opened the stream I also closed it.
I added a own try catch for the close block at finally just for being sure but when I took away the close section in the for loop it crashed.
Here's the working code
public File zip(List<File> files, String filename) {
File zipfile = new File(filename);
FileInputStream in=null;
ZipOutputStream out=null;
// Create a buffer for reading the files
byte[] buf = new byte[1024];
try {
// create the ZIP file
out = new ZipOutputStream(new FileOutputStream(
zipfile));
// compress the files
for (int i = 0; i < files.size(); i++) {
in = new FileInputStream(files.get(i));
// add ZIP entry to output stream
out.putNextEntry(new ZipEntry(files.get(i).getName()));
// transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
} catch (IOException ex) {
ex.printStackTrace();
}finally {
try {
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
out.closeEntry();
out.close();
}catch (Exception ex) {
ex.printStackTrace();
}
}
return zipfile;
}
I want to copy a file from network location into my local directory. I have written following code for this, but the problem is, it needs to have a file created first, and then the out stream writes the bytes stream into this file.
What i want is, the precondition to first create file locally should not be there. It should simply copy the network file into the mentioned directory directly, thats it! I'm kind of doing this for the first time.
try {
File srcFile = new File("//network//file//path//here");
File dstFileName = new File("//local//drive//file//path//here");
InputStream in = new FileInputStream(srcFile);
OutputStream out = new FileOutputStream(dstFileName);
byte[] buff = new byte[1024];
int length;
while ((length = in.read(buff)) > 0) {
out.write(buff, 0, length);
}
in.close();
out.close();
} catch (Exception ex) {
ex.printStackTrace();
}
You need to create the file, before you can write to it.
if(!dstFileName.exists()){
dstFileName.createNewFile();
}
If the the path does not exist, you can try to create it first with
dstFileName.getParentFile().mkdirs();
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is it possible to copy database file to SD card?
I have a database on my Android phone, and I need to get the information onto an SD card.
Is it possible to save the database file onto the SD card in a readable state? I haven't been able to find any information on how to do this. I know the name of the database, and fields etc...
I've found some examples that show how to save to SD cards, but not exactly what I need.
Some source code that copies the database file to an SD card would be perfect.
Hopefully this question is clear enough.
Yes. Here is the function that i use:
public void copyDBToSDCard() {
try {
InputStream myInput = new FileInputStream("/data/data/com.myproject/databases/"+DATABASE_NAME);
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/"+DATABASE_NAME);
if (!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
Log.i("FO","File creation failed for " + file);
}
}
OutputStream myOutput = new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/"+DATABASE_NAME);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
Log.i("FO","copied");
} catch (Exception e) {
Log.i("FO","exception="+e);
}
}
For a project that I worked on, I put a menu option in the home screen that I could call this function from at any time. Then, I'd move the database to my desktop and open it up with the SQLite Manager plugin for FireFox.
Sure. If this is a database that exists in your app, you can get a reference to the db file via Context.getDatabasePath(), passing it the database name. From there, it's just a routine file copy operation:
//Get a reference to the database
File dbFile = mContext.getDatabasePath("mydb");
//Get a reference to the directory location for the backup
File exportDir = new File(Environment.getExternalStorageDirectory(), "myAppBackups");
if (!exportDir.exists()) {
exportDir.mkdirs();
}
File backup = new File(exportDir, dbFile.getName());
//Check the required operation String command = params[0];
//Attempt file copy
try {
backup.createNewFile();
fileCopy(dbFile, backup);
} catch (IOException e) {
/*Handle File Error*/
}
Where the method fileCopy() is defined as:
private void fileCopy(File source, File dest) throws IOException {
FileChannel inChannel = new FileInputStream(source).getChannel();
FileChannel outChannel = new FileOutputStream(dest).getChannel();
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} finally {
if (inChannel != null) inChannel.close();
if (outChannel != null) outChannel.close();
}
}
HTH!