Save selected file in android sdcard - java

How can I save a file that was selected by user into an specific folder in android sdcard?
I followed this article here that helped me a lot, but i don't know how to save it after that.
I am able to save selected images and pitcures that are taken. This is the code I use for it.
private String saveBitmapToInternalSorage(Bitmap bitmapImage){
// get dir
File dir = new File(Environment.getExternalStorageDirectory(), "myApp/app-files");
if (!dir.mkdirs()){
Log.w("Could not create log directory: " + dir.getAbsolutePath(), "");
}
String fileName = "";
if (ChecklistHandler.getWorkingItem().getChildren() == null ||
ChecklistHandler.getWorkingItem().getChildren().isEmpty()){
fileName = ChecklistHandler.getWorkingItem().getId()
+ "_" + ChecklistHandler.getActivation() + ".jpg";
} else {
fileName = ChecklistHandler.getWorkingItem().getChildren().get(0).
getId() + "_" + ChecklistHandler.getActivation() + ".jpg";
}
File mypath=new File(dir, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return dir.getAbsolutePath();
}
and then I save the reference in the given folder in my db.
I want to do the same with file. Save it in that same folder and then get the reference and save it.

Related

Error reading a txt file

I am getting this error in my code when trying to read a file saved on the external storage of my phone :
java.io.FileNotFoundException: shopping.txt: open failed: ENOENT (No such file or directory)
I can manage to write data to this file with success, what I did a lot of times.
However, I cannot access for reading this same file, giving the entire path or through another method.
The code writing and saving successfully :
File path = new File(this.getFilesDir().getPath());
String value = "vegetables";
// File output = new File(path + File.separator + fileName);
File output = new File(getApplicationContext().getExternalFilesDir(null),"shopping.txt");
try {
FileOutputStream fileout = new FileOutputStream(output.getAbsolutePath());
OutputStreamWriter outputWriter=new OutputStreamWriter(fileout);
outputWriter.write(value);
outputWriter.close();
//display file saved message
// Toast.makeText(getBaseContext(), "File saved successfully!",
// Toast.LENGTH_LONG).show();
Toast.makeText(MainActivity.this,String.valueOf(output),Toast.LENGTH_LONG).show();
Log.d("MainActivity", "Chemin fichier = [" + output + "]");
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
The writing piece of code crashing my app :
try
{
File gFile;
FileInputStream fis = new FileInputStream (new File("shopping.txt"));
//FileInputStream fis = openFileInput("/storage/emulated/0/Android/data/com.example.namour.shoppinglist/files/shopping.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
String line = null, input="";
while ((line = reader.readLine()) != null)
input += line;
Toast.makeText(MainActivity.this,line,Toast.LENGTH_LONG).show();
reader.close();
fis.close();
Toast.makeText(MainActivity.this,"Read successful",Toast.LENGTH_LONG).show();
//return input;
}
catch (IOException e)
{
Log.e("Exception", "File read failed: " + e.toString());
//toast("Error loading file: " + ex.getLocalizedMessage());
}
What am I doing wrong ?
For sure, not a problem of permissions, since I can write with success.
Many thanks for your help.
You missed to specifiy the correct path. You are looking for a file named shopping.txt in your current working directory (at runtime).
Create a new File object with the correct path and it will work:
File input = new File(getApplicationContext().getExternalFilesDir(null),"shopping.txt");. You could reuse your object from writing.
While opening the file, you are simply using new File("shopping.txt").
You need to specify the parent folder, like this:
new File(getExternalFilesDir(),"shopping.txt");
I recommend you make sure of org.apache.commons.io for IO, their FileUtils and FileNameUtils libs are great. ie: FileUtils.writeStringToFile(new File(path), data); Add this to gradle if you wish to use it: implementation 'org.apache.commons:commons-collections4:4.1'
In regards to your problem. When you write your file you are using:
getApplicationContext().getExternalFilesDir(null),"shopping.txt"
But when reading your file you are using:
FileInputStream fis = new FileInputStream (new File("shopping.txt"));
Notice that you didn't specify a path to shopping.txt simply the file name.
Why not do something like this instead:
//Get path to directory of your choice
public String GetStorageDirectoryPath()
{
String envPath = Environment.getExternalStorageDirectory().toString();
String path = FilenameUtils.concat(envPath, "WhateverDirYouWish");
return path;
}
//Concat filename with path
public String GetFilenameFullPath(String fileName){
return FilenameUtils.concat(GetStorageDirectoryPath(), fileName);
}
//Write
String fullFilePath = GetFilenameFullPath("shopping.txt");
FileUtils.writeStringToFile(new File(fullFilePath ), data);
//Read
File file = new File(fullFilePath);
StringBuilder text = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null){
text.append(line);
if(newLine)
text.append(System.getProperty("line.separator"));
}
br.close();

Java save Resources Folder to disk folder

I do have a Folder in my Ressources i want to extract to disk when the App is started the first time. I do have this peace of code here where I tried to copy them to disk, but all I get are empty files. The folder contains .gnh files. Where am I loosing my Bytes of the File?
public void getTemplates() throws URISyntaxException {
final URL url = TemplateUtils.class.getResource("/templates/");
if (url != null) {
final File dir = new File(url.toURI());
for (final File file : dir.listFiles()) {
try {
final OutputStream outStream = new FileOutputStream(
PathManager.INSTANCE.getRootPath() + file.getName());
final long writtenBytes = Files.copy(file.toPath(), outStream);
LOG.info(writtenBytes);
outStream.flush();
outStream.close();
} catch (final IOException e) {
LOG.error(e.getMessage(), e);
}
}
}
}
the LOG.info(writtenBytes) says 0
EDIT:
When I copy simple text Files everything is working fine. But with those .gnh Files nothing is working anymore. Is there another way to extract those Files to disk?
I got the solution: You need to create the File for the OutputStream first and then you can flush it.
final File path = new File(
PathManager.INSTANCE.getRootPath() + "templates");
path.mkdirs();
final File newFile = new File(path.toString()
+ File.separator + file.getName());
newFile.createNewFile();
final OutputStream outStream = new FileOutputStream(newFile);
Files.copy(file.toPath(), outStream);
outStream.flush();
outStream.close();

read and write from Internal storage

I am having this exception when trying to read from the file
java.io.FileNotFoundException: /data/data/.../files
I used this method because it can handle Unicode text while reading from the file
public void save(String string )
{
String filename = "main";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public String read()
{
try
{
Reader readerUnicode =
new InputStreamReader(new FileInputStream(getFilesDir()), Charset.forName("UTF-16"));
int e = 0;
String f="";
while ((e = readerUnicode.read()) != -1) {
// cast to char. The casting removes the left most bit.
f = f+Character.toString((char) e);
System.out.print(f);
}
return f;
}
catch(Exception e)
{
return e+"";
}
}
how can I retrieve the internal save path
thanks
You are using getFilesDir() But not setting the actual file name. Just the directory path.
Try adding the file name in. Plus, you should probably add an extension like .txt to both the save and load path.
new InputStreamReader(new FileInputStream(getFilesDir() + "/" + filename ), Charset.forName("UTF-16"));
and change filename to something more sensible.
String filename = "main.txt";
You could/should also check the file exists before accessing it. (Although you do try catch anyway)
File file = new File(getFilesDir() + "/" + filename);
if(!file.exists())
return "";

Corrupted docx generated using zipping

Let me just start out by saying I created an account on here because I've been beating my head against a wall in order to try and figure this out, so here it goes.
Also, I have already seen this question here. Neither one of those answers have helped and I have tried both of them.
I need to create a word document with a simple table and data inside. I decided to create a sample document in which to get the xml that I need to create the document. I moved all the folders from the unzipped docx file into my assets folder. Once I realized I couldn't write to the assets folder, I wrote a method to copy all the files and folders over to an external storage location of the device and then write the document I created to the same location. From there Im trying to zip the files back up to a .docx file. This is where things arent working.
The actual docx file is created and I can move it to my computer through the DDMS but when I go to view it Word says its corrupt. Heres whats weird though, if I unzip it and then rezip it on my computer without making any changes what so ever it works perfectly. I have used a program (for mac) called DiffMerge to compare the sample unzipped docx file to the unzipped docx that I have created and it says they are exactly the same. So, I think it has something to do with the zipping process in Android.
I have also tried unzipping the sample docx file on my computer, moving all the files and folders over to my assets folder including the document.xml file and just try to zip it up without adding my own document.xml file and using the sample one and that doesnt work either. Another thing I tried was to place the actual docx file in my assets folder, unzipping it onto my external storage and then rezipping it without doing anything. This also fails.
I'm basically at a loss. Please somebody help me figure this out.
Here is some of my code:
moveDocxFoldersFromAssetsToExternalStorage() is called first.
After that is called all the files have been moved over.
Then, I create the document.xml file and place it in the word directory where it belongs
Everything is where it should be and I now try to create the zip file.
.
private boolean moveDocxFoldersFromAssetsToExternalStorage(){
File rootDir = new File(this.externalPath);
rootDir.mkdir();
copy("");
// This is to get around a glitch in Android which doesnt list files or folders
// with an underscore at the beginning of the name in the assets folder.
// This renames them once they are saved to the device.
// We need it to show up in the list in order to move them.
File relsDir = new File(this.externalPath + "/word/rels");
File renameDir = new File(this.externalPath + "/word/_rels");
relsDir.renameTo(renameDir);
relsDir = new File(this.externalPath + "/rels");
renameDir = new File(this.externalPath + "/_rels");
relsDir.renameTo(renameDir);
// This is to get around a glitch in Android which doesnt list hidden files.
// We need it to show up in the list in order to move it.
relsDir = new File(this.externalPath + "/_rels/rels.rename");
renameDir = new File(this.externalPath + "/_rels/.rels");
relsDir.renameTo(renameDir);
return true;
}
private void copy(String outFileRelativePath){
String files[] = null;
try {
files = this.mAssetManager.list(ASSETS_RELATIVE_PATH + outFileRelativePath);
} catch (IOException e) {
e.printStackTrace();
}
String assetFilePath = null;
for(String fileName : files){
if(!fileName.contains(".")){
String outFile = outFileRelativePath + java.io.File.separator + fileName;
copy(outFile);
} else {
File createFile = new File(this.externalPath + java.io.File.separator + outFileRelativePath);
createFile.mkdir();
File file = new File(createFile, fileName);
assetFilePath =
ASSETS_RELATIVE_PATH + outFileRelativePath + java.io.File.separator + fileName;
InputStream in = null;
OutputStream out = null;
try {
in = this.mAssetManager.open(assetFilePath);
out = new FileOutputStream(file);
copyFile(in, out);
in.close();
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
private void zipFolder(String srcFolder, String destZipFile) throws Exception{
FileOutputStream fileWriter = new FileOutputStream(destZipFile);
ZipOutputStream zip = new ZipOutputStream(fileWriter);
zip.setMethod(Deflater.DEFLATED);
zip.setLevel(ZipOutputStream.STORED);
addFolderToZip(this.externalPath, "", zip);
zip.finish();
zip.close();
}
private void addFolderToZip(String externalPath, String folder, ZipOutputStream zip){
File file = new File(externalPath);
String files[] = file.list();
for(String fileName : files){
try {
File currentFile = new File(externalPath, fileName);
if(currentFile.isDirectory()){
String outFile = externalPath + java.io.File.separator + fileName;
addFolderToZip(outFile, folder + java.io.File.separator + fileName, zip);
} else {
byte[] buffer = new byte[8000];
int len;
FileInputStream in = new FileInputStream(currentFile);
zip.putNextEntry(new ZipEntry(folder + java.io.File.separator + fileName));
while((len = in.read(buffer)) > 0){
zip.write(buffer, 0, len);
}
zip.closeEntry();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
EDIT
Here is the code I wrote in order to get it working correctly based on what #edi9999 said below. I created a separate class that Im going to expand and add to and probably clean up a bit but this is working code. It adds all the files in a directory to the zip file and recursively calls itself to add all the subfiles and folders.
private class Zip {
private ZipOutputStream mZipOutputStream;
private String pathToZipDestination;
private String pathToFilesToZip;
public Zip(String pathToZipDestination, String pathToFilesToZip) {
this.pathToZipDestination = pathToZipDestination;
this.pathToFilesToZip = pathToFilesToZip;
}
public void zipFiles() throws Exception{
FileOutputStream fileWriter = new FileOutputStream(pathToZipDestination);
this.mZipOutputStream = new ZipOutputStream(fileWriter);
this.mZipOutputStream.setMethod(Deflater.DEFLATED);
this.mZipOutputStream.setLevel(8);
AddFilesToZip("");
this.mZipOutputStream.finish();
this.mZipOutputStream.close();
}
private void AddFilesToZip(String folder){
File mFile = new File(pathToFilesToZip + java.io.File.separator + folder);
String mFiles[] = mFile.list();
for(String fileName : mFiles){
File currentFile;
if(folder != "")
currentFile = new File(pathToFilesToZip, folder + java.io.File.separator + fileName);
else
currentFile = new File(pathToFilesToZip, fileName);
if(currentFile.isDirectory()){
if(folder != "")
AddFilesToZip(folder + java.io.File.separator + currentFile.getName());
else
AddFilesToZip(currentFile.getName());
} else {
try{
byte[] buffer = new byte[8000];
int len;
FileInputStream in = new FileInputStream(currentFile);
if(folder != ""){
mZipOutputStream.putNextEntry(new ZipEntry(folder + java.io.File.separator + fileName));
} else {
mZipOutputStream.putNextEntry(new ZipEntry(fileName));
}
while((len = in.read(buffer)) > 0){
mZipOutputStream.write(buffer, 0, len);
}
mZipOutputStream.closeEntry();
in.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
}
I think I've got what's wrong.
When I opened your corrupted File, and opened it on winrar, I saw antislashes at the beginning of the folders, which is unusual:
When I rezip the file after unzipping it, the antislashes are not there anymore and the file opens in Word so I think it should be the issue.
I think the code is wrong here:
String outFile = externalPath + java.io.File.separator + fileName;
should be
if (externalPath=="")
String outFile = externalPath + fileName;
else
String outFile = externalPath + java.io.File.separator + fileName;

Android/Java - When a file exists, rename the file

I can't seem to get my logic right, I'm trying to rename a file to "photo2.jpg" if, say "photo.jpg" and "photo1.jpg" exists, and so on.
At the moment when I run my code, and I take a picture, only "photo.jpg" and "photo1.jpg" ever exist, and then they get written over if a third and fourth, etc. photo is taken.
String photoName = "photo.jpg";
String i = "0";
int num = 0;
File photo = new File(Environment.getExternalStorageDirectory(), photoName);
//for (File file : photo.listFiles()){
while(photo.exists()) {
//if(file.getName().equals("photo.jpg")){
//photo.delete();
num = Integer.parseInt(i);
++num;
String concatenatedNum = Integer.toString(num);
StringBuffer insertNum = new StringBuffer(photoName);
insertNum.insert(5, concatenatedNum);
photoName = insertNum.toString();
photo.renameTo(new File(Environment.getExternalStorageDirectory(), photoName));
//}
}
try {
FileOutputStream fos=new FileOutputStream(photo.getPath());
//MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle, yourDescription);
//write jpeg to local drive
fos.write(jpeg[0]);
fos.close();
}
catch (java.io.IOException e) {}
Thanks for your time and help!
EDIT: Half solved: I realized I was overwriting the file instead of creating a NEW file. Now I can take multiple pictures and they are saved as their own file. However, the naming of the files is now:
photo.jpg
photo1.jpg
photo11.jpg
photo111.jpg, etc.
You always base your filename on i, but you never change the value of i when you find that number is used.
I know this is older, but I ended up here when I was looking for a solution.
I ended up doing the following:
String baseFilename = "photo";
File outputFile = new File(Environment.getExternalStorageDirectory(), baseFilename + ".jpg");
int i = 2; // whatever increment you want to start with, I'm copying Windows' naming convention
while (outputFile.exists()){
outputFile = new File(Environment.getExternalStorageDirectory(), baseFilename + "(" + i + ")" + ".jpg");
i++;
}
You will end up with photo.jpg, photo(2).jpg, photo(3).jpg, etc.
Obviously you can easily change how the int is appended, but like I said I just decided to follow how Windows does it.
private void savePhoto(String fileName, final String extension)
{
// First, get all the file names from the directory
String[] allFiles = new File(Environment.getExternalStorageDirectory().toString()).list();
// Create a new empty list to put all the matching file names in
// In this case all the files names that are "photo.jpg" or "photo#.jpg"
ArrayList<String> files = new ArrayList<String>();
// Skim through all the files
for(String file : allFiles)
{
// Use a regular expression to find matching files
// fileName[0-9]+\.extension|fileName\.extension
if(file.matches(fileName + "[0-9]+\\." + extension + "|" + fileName + "\\." + extension))
{
files.add(file);
}
}
files.trimToSize();
// Now sift through the list and find out what the highest number is
// Example, if you've taken 8 photos, then highestNumber will equal 8
int highestNumber = 0;
int digit;
for(String file : files)
{
try
{
digit = Integer.parseInt(file.replace(fileName, "").replace("." + extension, ""));
}
catch(NumberFormatException e)
{
digit = 1;
}
if(digit > highestNumber)
{
highestNumber = digit;
}
}
// Create the file object
fileName = fileName + highestNumber++ + "." + extension;
File file = new File(Environment.getExternalStorageDirectory().toString(), fileName);
// In not sure what you do around here, I can't find any array titled "jpeg"
// So do what you will
FileOutputStream fostream = null;
try
{
fostream = new FileOutputStream(file);
//MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle, yourDescription);
//write jpeg to local drive
fostream.write(jpeg[0]);
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(fostream != null)
{
try
{
fostream.flush();
fostream.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}

Categories

Resources