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

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

Related

How to pass the file path as an argument in RandomFileAccess Object in android?

There is a small problem in the following code that it is unable to find the text file src/main/res/raw/dictionary.txt:
RandomAccessFile ifl = new RandomAccessFile("android.resource://"
+ getPackageName() + "/" + R.raw.dict , "r");
Is there any other way by which the text file can successfully be found and opened? Is there a way if we keep these files in 'assets' folder and then access? Plz suggest.
you can better use InputStream to read text in raw folder file ,
public String readRawFile()
{
StringBuilder builder = new StringBuilder();
InputStream in = getResources().openRawResource(R.raw.yourfile);
try {
int count = 0;
byte[] bytes = new byte[32768];
while ( (count = in.read(bytes,0, 32768)) > 0) {
builder.append(new String(bytes, 0, count));
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return builder.toString();
}

Create New Text Files with Different Names in Java

Every time the code is executed I want a new Text File to be created.
The Text File should be called Person1.
Next time code is executed the Text File should be called Person2.
Then again the Text File should be called Person3. etc, etc....
At the moment, I'm able to create a Text File named "Person1" but can't create another Text File named "Person2".
private int fileNumber = 1;
fileNumber = fileNumber++;
public static void main(String[] args) {
try {
FileWriter fw = new FileWriter("Person" + fileNumber + ".txt");
PrintWriter pw = new PrintWriter(fw);
pw.println("Hello you created a text file");
pw.close();
}
catch (IOException e)
{
System.out.println("Error!");
}
}
Check for the file. If exists then increment the index
File file = new File("E:\\" + "Person1" + ".txt");
int increase=1;
while(file.exists()){
increase++;
file = new File("E:\\" + "Person" + increase+ ".txt");
}
if(!file.exists()) {
try {
String content = textfile.toString();
file.createNewFile();
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
System.out.println("Done");
}catch (IOException e){
}
Upon creating a new file, you should check if the file with such fileNumber or index already exists. While a file with such index exists, the index should be incremented. Finally, you create a new file with an index that does not exist.
Say you created an abstract representation of a file and now want to rename it to the first available index. Let's assume other files are located at C:\tmp:
File newFile;
int index = 1;
String parent = "C:\\tmp"
String name = "Person";
while ((newFile = new File(parent, name + index)).exists()) {
index++;
}
/* Here you have a newFile with name set to the first available index */
Or if you want to consider having an extension:
File newFile;
int index = 1;
String parent = "C:\\tmp"
String name = "Person";
String extension = ".txt";
while ((newFile = new File(parent, name + index + extension)).exists()) {
index++;
}
/* Here you have a newFile with name set to the first available index and extension */
UPDATE: Using the Java 8 NIO API, I've created the following method to return a Path object for the first available path that does not yet exist on the file system:
/**
* Returns the first available {#code Path} with a unique file name. The
* first available path means that, if a file with the specified
* <tt>path</tt> exists on disk, an index is appended to it. If a file with
* that path still exists, index is incremented and so on, until a unique
* path is generated. This path is then returned.
* <p>
* If a file with the specified <tt>path</tt> does not exist, this method
* trivially returns <tt>path</tt>.
* <p>
* For an example, if the parent directory of the specified path already
* contains <tt>file.txt</tt>, <tt>file-0.txt</tt> and <tt>file-1.txt</tt>,
* and the file name of this path is <tt>file.txt</tt>, then a path with
* file name <tt>file-2.txt</tt> is returned.
*
* #param path path from which the first available is returned
* #return a path with a unique file name
*/
public static Path firstAvailable(Path path) {
if (!Files.exists(path))
return path;
int namingIndex = 0;
String name = path.getFileName().toString();
String extension = "";
int dotIndex = name.lastIndexOf('.');
if (dotIndex > 0) {
extension = name.substring(dotIndex);
name = name.substring(0, dotIndex);
}
name += "-";
while (Files.exists(path)) {
path = path.resolveSibling(name + namingIndex + extension);
namingIndex++;
}
return path;
}
There are two different way to do this based on your program execution. If you want to keep the program running and within that are calling that function, then you can keep the last generated file number and increment by 1. For example, your last generated file name is Person4, so, next one will be Person5 by incrementing the number of the variable. But if you wish to run the program from beginning each time, then you have to read the index already written to your directory. When you read the filename from the directory, you can use substring(5, index.length) which will give you the number. Then increment that number for the next file.
Try this. Just change the i value in the for loop to create how many files you need
File file;
for (int i = 21; i < 32; i++) {
file = new File("Practica" + Integer.toString(i) + ".java");
try {
file.createNewFile();
} catch (Exception e) {}
}
try {
int index= 0;
File file = new File("folder\\" + "filename" + ".txt");
while (file.exists()) {
index++;
file = new File("folder\\" + "filename" + index + ".txt");
}
if (!file.exists()) {
// create file
}
} catch (IOException e) {
e.printStackTrace();
}
}

Rename duplicate files in a zip file Java

I have several files including duplicates which I have to compress into an archive.Do you know some tool able to rename duplicate files before creating the archive ex(cat.txt, cat(1).txt, cat(2).txt ...)?
I have created the following code that easily removes duplicates:
static void renameDuplicates(String fileName, String[] newName) {
int i=1;
File file = new File(fileName + "(1).txt");
while (file.exists() && !file.isDirectory()) {
file.renameTo(new File(newName[i-1] + ".txt"));
i++;
file = new File(fileName + "(" + i + ").txt");
}
}
Use is simply as well:
String[] newName = {"Meow", "MeowAgain", "OneMoreMeow", "Meowwww"};
renameDuplocates("cat", newName);
The result is:
cat.txt -> cat.txt
cat(1).txt -> Meow.txt
cat(2).txt -> MeowAgain.txt
cat(3).txt -> OneMoreMeow.txt
Keep on mind that the number of duplicates should be smaller or equal than alternative names in the array of string given. You can prevent it with while cycle modification to:
while (file.exists() && !file.isDirectory() && i<=newName.length)
In this case the remaining files will keep unnamed.
Add static field in some class with some initial value.
static int number = 1;
Then in your java code you may rename duplicates in this way using java 8 streams and Files class :
Set<String> files = new HashSet<String>();
youCollectionOfFiles.stream().forEach((file)->{
if (files.add(file.getFileName().toString()) == false) {
try {
//rename the file
Files.move(file,
file.resolveSibling(file.getFileName().toString() + (number++)));
} catch (Exception e) {
e.printStackTrace();
}
}
});;
Try an approach like this one:
File folder = new File("your/path");
HashMap<String,Integer> fileMap = new HashMap<String,Integer>();
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if(fileMap.containsKey(listOfFiles[i])){
String newName = listOfFiles[i]+"_"
+fileMap.get(listOfFiles[i]);
fileMap.put(listOfFiles[i],fileMap.get(listOfFiles[i])+1);
listOfFiles[i].renameTo(newName);
fileMap.put(newName,1); // can be ommitted
}else{
fileMap.put(listOfFiles[i],1);
}
}

Buffered Writer overwriting file when not wanted

I have this code here that takes in 3 arguments, A Directory, a Filename, and a number. The program creates the filename in the directory and writes the number in it. So I can say...
>java D: myName.txt Clay 100
which will create a file named myName.txt in D: and says 100 in it.
If myName is taken up, it changes the name to myName(2), then myName(3) (if myName(2) taken up). The only problem is that when it changes the name to myName(2) and writes, it overwrites myName. I dont want it to overwrite myName, I want it to just create a new file with that name. Ive looked at similar questions and the common answer is the flush and close the writer which ive done And it still doesnt work.
Any help would be appreciated, here is my code so fart...
import java.io.*;
public class filetasktest{
public static void main(String[] args) throws IOException{
int i = 2;
String directory = args[0];
if (directory.substring(directory.length() - 1) != "/"){
directory += "/";
}
String contactName = args[1];
String contactNumber = args[2];
String finalDirectory = directory + contactName + ".contact";
File f = new File(finalDirectory);
while (f.exists()){
finalDirectory = directory + contactName + "(" + ("" + i) + ")" + ".contact";
f.renameTo(new File(finalDirectory));
i++;
}
Writer writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(finalDirectory), "utf-8"));
writer.write(contactNumber);
} catch (IOException ex){
System.out.println(ex.getMessage());
} finally {
try {
writer.close();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
}
You need to use append mode
new BufferedWriter(new FileWriter(yourFileName, true));
here, true means that the txt should be appended at the end of file.
Check the FileWriter javadoc for more information.
Your problem is here:
while (f.exists()){
finalDirectory = directory + contactName + "(" + ("" + i) + ")" + ".contact";
f.renameTo(new File(finalDirectory));
i++;
}
The renameTo method does not change the path of a File object; it renames a file on disk. The path of f stays the same throughout the loop: it starts out as D:/myName.txt and if a file by that name exists, the file is renamed as D:/myName(1).txt. The variable f still holds the path D:/myName.txt, which no longer names a file, and the content is written to D:/myName(1).txt, overwriting the previous content.
To fix this issue change the loop to:
while (new File(finalDirectory).exists()){
finalDirectory = directory + contactName + "(" + ("" + i) + ")" + ".contact";
i++;
}
Take a look at FileInputStream(String, boolean) which will allow you to flag if the file should be appended or overwritten

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;

Categories

Resources