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);
}
}
Related
I'm reading all the files of a directory and trying to save all the words, from all the files associated within that directory to a hash map, these words will be stored under a key which is the name of the directory.
for instance, a directory called atheism contains one file called a0.txt which contains the word Gott, another file in the same directory called a1.txt contains the word ist, and a third file called a2.txt contains the word tot. I want to save all these words under the hash map key atheism.
Later I want to generalize this to be able to accomidate big multi-line documents behind the key value of a particular directory, below I've posted the code which I'm working with right now to populate the hash map.
I had a look at this trying to adapt it but finally I didn't find it aplicable to my situation.
What I want to do is access the array associated with a specific key from within the hashmap, and just add the new words onto the end of it. How to do that?
I need these words because this is part of a program to implement the perceptron algorithm, I'm saving the words as part of the process of generating a bag-of-words model feature vector.
public static void iterateDirectory( File directory,
boolean globo_dict_fixed,
Map<String, ArrayList<String> > fileDict,
Set<String> GLOBO_DICT) throws IOException
{
for (File file : directory.listFiles())
{
if (file.isDirectory())
{
iterateDirectory(directory, globo_dict_fixed, fileDict, GLOBO_DICT );
}
else
{
String line;
BufferedReader br = new BufferedReader(new FileReader( file ));
ArrayList<String> document_words_on_line = new ArrayList<String>();
while((line = br.readLine()) != null)
{
String[] words = line.split(" ");//those are your words
if(globo_dict_fixed == false)
{
Data_GloboPop.populate_globo_dict( words, GLOBO_DICT );
}
else
{
String word;
for (int i = 0; i < words.length; i++)
{
word = words[i];
document_words_on_line.add(word);
}
}
}
String key_file_loke = file.getPath()
.toString()
.replaceAll("/[^/]*$", "")
.replaceAll("/home/matthias/Workbench/SUTD/ISTD_50.570/assignments/practice_data/data/train/", "")
.replaceAll("/home/matthias/Workbench/SUTD/ISTD_50.570/assignments/practice_data/data/test/", "");
//this should be here, meaning that the line is null and the file is over
//put all documents from the same directory under the same key
fileDict.put( key_file_loke , document_words_on_line );
}
}
}
Well you want to -- "access the array associated with a specific key from within the hashmap"
Sure, instead of initializing the ArrayList each time, you can always replace this line
ArrayList<String> document_words_on_line = new ArrayList<String>();
with this line
ArrayList<String> document_words_on_line = fileDict.get(key_file_loke);
And compute the key_file_loke before the assignment of document_words_on_line.
[Update] :
If you get a null then initialize it, else use the same reference.
In short :
String key_file_loke = Insert your existing logic;
ArrayList<String> document_words_on_line = fileDict.get(key_file_loke);
if(document_words_on_line == null){
ArrayList<String> document_words_on_line = new ArrayList<String>();
}
First of all, you may want to replace this part of code
if (file.isDirectory())
{
iterateDirectory(directory, globo_dict_fixed, fileDict, GLOBO_DICT );
}
with fhis
if (file.isDirectory())
{
iterateDirectory(file, globo_dict_fixed, fileDict, GLOBO_DICT );
}
Next, you should put new key-value pair into hashmap as soon as you find a new directory, before you start looking for words in this directory. So you don't need to check and create new List and key-value pair for each file in the same directory (assuming you have a directory with lots of files).
For example
for (File file : directory.listFiles())
{
if (file.isDirectory())
{
fileDict.put(getDirectoryName(file), new LinkedList<>());
iterateDirectory(file, globo_dict_fixed, fileDict, GLOBO_DICT );
}
else
{
final String directoryName = getDirectoryByFilePath(file); // you should extract this method from your code
List<String> wordsList = fileDict.get(directoryName);
if(wordsList == null) { // just in case
wordsList = new LinkedList<>();
fileDict.put(directoryName, wordsList);
}
String line;
BufferedReader br = new BufferedReader(new FileReader( file ));
while((line = br.readLine()) != null) {
String[] words = line.split(" ");//those are your words
if(globo_dict_fixed == false)
{
Data_GloboPop.populate_globo_dict( words, GLOBO_DICT );
}
else
{
for (int i = 0; i < words.length; i++)
{
wordsList.add(words[i]);
}
}
}
}
}
And if it you do not care about accessing words by random index, I recommend to use LinkedList instead of ArrayList.
Why can't you try this model
Map<String,Map<String,String>> directoryFiles = new HashMap<>();
Map<String,String> fileNameAndContents = new HashMap<>();
//Create all file contents map add it to main map
directoryFiles.put("directory", fileNameAndContents);
public static void main(String[] d) throws Exception {
Map<String,Map<String,String>> directoryFiles = new HashMap<>();
listfileContent("d:/f1",directoryFiles);
System.out.println(directoryFiles.toString());
}
public static void listfileContent(String directoryName,Map<String,Map<String,String>> directoryFiles) {
File directory = new File(directoryName);
// get all the files from a directory
File[] files = directory.listFiles();
Map<String,String> fileNameAndContents = new HashMap<>();
for (File file : files) {
if (file.isFile()) {
fileNameAndContents.put(file.getName(), "FileContent " );
directoryFiles.put(directoryName, fileNameAndContents);
} else if (file.isDirectory()) {
listfileContent(file.getAbsolutePath(),directoryFiles);
}
}
}
I think this will help you. "FileContent " place you can write a function to get the data from a 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();
}
}
}
}
I have a Java program that searches through your cookies files and then saves each file into an array. I then try to search through each of those files for a certain string, however when I try to search the files I KNOW exist, java tells me that they don't. Any ideas?
Here is my code so far:
import java.io.*;
import java.util.*;
public class CheckCookie
{
static String[] textFiles = new String[100];
static String userName = "";
public static void findCookies()
{
String path = "pathtocookies";
String files;
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++)
{
if (listOfFiles[i].isFile())
{
files = listOfFiles[i].getName();
if (files.endsWith(".txt") || files.endsWith(".TXT"))
{
textFiles[i] = files;
}
}
}
}
public static boolean searchCookies()
{
for(int j = 0; j < textFiles.length; j++) {
String path2 = "pathtocookies"+textFiles[j];
File file = new File(path2);
try {
Scanner scan = new Scanner(file);
while (scan.hasNext()) {
String line = scan.nextLine();
if(line.contains("ineligible_age")) {
System.out.println("A cookie for ineligible age was set.");
return true;
}
}
}
catch(FileNotFoundException e) {
System.out.println("File was not found.");
return false;
}
}
System.out.println("A cookie for ineligible age was not set.");
return false;
}
public static void main(String[] args)
{
findCookies();
searchCookies();
System.out.println();
System.out.println("Finished searching for cookies. Yum.");
}
}
Actual path:
C:/Users/lucas.brandt/AppData/Roaming/Microsoft/Windows/Cookies
Use a List, instead of an array to store the textFiles.
Imagine a directory with 2 files. The first is "abc.doc", the second "itsme.txt"
Your textFiles array will look like this:
textFiles[0]: null
textFiles[1]: "itsme.txt"
So you try to access "pathtocookies" + "null" which will fail, you go to the catch and return out of the function.
Further hints:
Return the list from the first function, use it as an argument for the second function
Use a debugger or "debug" print statements to debug your code to see whats happening
More hints depends on the actual use case.
--tb
In this line:
String path2 = "pathtocookies"+textFiles[j];
You are missing the File separator between the directory name and the file name. java.io.File has a constructor that takes the parent path and the file name as separate arguments. You can use that or insert File.separator:
String path2 = "pathtocookies" + File.separator + textFiles[j];
You are also picking up directories in your array. Check that it is a file before you try to scan it.
Also, consider the other answer where the files are saved in a List, eliminating the directories.
files = listOfFiles[i].getName();
Try to change to
files = listOfFiles[i].getAbsolutePath();
EDIT
You can also initiate directectly an array of File (instead of String),
and you have to use .canRead() method to verify File access.
Why don't you just store the File instances in a File[] or List<File>?
I think you would also benefot from using a StringBuilder, when doing a lot of string concatenstions...
I was writing a program in Java to search for a piece of text
I took these 3 as inputs
The directory, from where the search should start
The text to be searched for
Should the search must be recursive (to or not to include the directories inside a directory)
Here is my code
public void theRealSearch(String dirToSearch, String txtToSearch, boolean isRecursive) throws Exception
{
File file = new File(dirToSearch);
String[] fileNames = file.list();
for(int j=0; j<fileNames.length; j++)
{
File anotherFile = new File(fileNames[j]);
if(anotherFile.isDirectory())
{
if(isRecursive)
theRealSearch(anotherFile.getAbsolutePath(), txtToSearch, isRecursive);
}
else
{
BufferedReader bufReader = new BufferedReader(new FileReader(anotherFile));
String line = "";
int lineCount = 0;
while((line = bufReader.readLine()) != null)
{
lineCount++;
if(line.toLowerCase().contains(txtToSearch.toLowerCase()))
System.out.println("File found. " + anotherFile.getAbsolutePath() + " at line number " + lineCount);
}
}
}
}
When recursion is set true, the program returns a FILENOTFOUNDEXCEPTION
So, I referred to the site from where I got the idea to implement this program and edited my program a bit. This is how it goes
public void theRealSearch(String dirToSearch, String txtToSearch, boolean isRecursive) throws Exception
{
File[] files = new File(dirToSearch).listFiles();
for(int j=0; j<files.length; j++)
{
File anotherFile = files[j];
if(anotherFile.isDirectory())
{
if(isRecursive)
theRealSearch(anotherFile.getAbsolutePath(), txtToSearch, isRecursive);
}
else
{
BufferedReader bufReader = new BufferedReader(new FileReader(anotherFile));
String line = "";
int lineCount = 0;
while((line = bufReader.readLine()) != null)
{
lineCount++;
if(line.toLowerCase().contains(txtToSearch.toLowerCase()))
System.out.println("File found. " + anotherFile.getAbsolutePath() + " at line number " + lineCount);
}
}
}
}
It worked perfectly then. The only difference between the two snippets is the way of creating the files, but they look the same to me!!
Can anyone point me out where I messed up?
In the second example it is used listFiles() whichs returns files. In your example it is used list() which returns only the names of the files - here the error.
The problem in the first example is in the fact that file.list() returns an array of file NAMES, not paths. If you want to fix it, simply pass file as an argument when creating the file, so that it's used as the parent file:
File anotherFile = new File(file, fileNames[j]);
Now it assumes that anotherFile is in the directory represented by file, which should work.
You need to include the base directory when you build the File object as #fivedigit points out.
File dir = new File(dirToSearch);
for(String fileName : file.list()) {
File anotherDirAndFile = new File(dir, fileName);
I would close your files when you are finished and I would avoid using throws Exception.
Let's say, I have a folder called maps and inside maps I have map1.txt, map2.txt, and map3.txt. How can I use Java and the BufferReader to read all of the .txt files in folder maps (if it is at all possible)?
Something like the following should get you going, note that I use apache commons FileUtils instead of messing with buffers and streams for simplicity...
File folder = new File("/path/to/files");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
File file = listOfFiles[i];
if (file.isFile() && file.getName().endsWith(".txt")) {
String content = FileUtils.readFileToString(file);
/* do somthing with content */
}
}
I would take #Andrew White answer (+1 BTW) one step further, and suggest you would use FileNameFilter to list only relevant files:
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".txt");
}
};
File folder = new File("/path/to/files");
File[] listOfFiles = folder.listFiles(filter);
for (int i = 0; i < listOfFiles.length; i++) {
File file = listOfFiles[i];
String content = FileUtils.readFileToString(file);
// do something with the file
}
final File folder = new File("C:/Dev Tools/apache-tomcat-6.0.37/webapps/ROOT/somefile");
for (final File fileEntry : folder.listFiles()) {
System.out.println("FileEntry Directory "+fileEntry);
With NIO you can do the following:
Files.walk(Paths.get("/path/to/files"))
.filter(Files::isRegularFile)
.filter(path -> path.getFileName().toString().endsWith(".txt"))
.map(FileUtils::readFileToString)
// do something
To read the file contents you may use Files#readString but, as usual, you need to handle IOException inside lambda expression.
I think it's good way to read all .txt files from maps and sub folder's
private static void addfiles (File input,ArrayList<File> files)
{
if(input.isDirectory())
{
ArrayList <File> path = new ArrayList<File>(Arrays.asList(input.listFiles()));
for(int i=0 ; i<path.size();++i)
{
if(path.get(i).isDirectory())
{
addfiles(path.get(i),files);
}
if(path.get(i).isFile())
{
String name=(path.get(i)).getName();
if(name.lastIndexOf('.')>0)
{
int lastIndex = name.lastIndexOf('.');
String str = name.substring(lastIndex);
if(str.equals(".txt"))
{
files.add(path.get(i));
}
}
}
}
}
if(input.isFile())
{
String name=(input.getName());
if(name.lastIndexOf('.')>0)
{
int lastIndex = name.lastIndexOf('.');
String str = name.substring(lastIndex);
if(str.equals(".txt"))
{
files.add(input);
}
}
}
}
If you want a better way of doing this using the new java.nio api, then this is the way, taken from the java docs
Path dir = ...;
try (DirectoryStream<Path> stream =
Files.newDirectoryStream(dir, "*.txt")) {
for (Path entry: stream) {
System.out.println(entry.getFileName());
}
} catch (IOException x) {
// IOException can never be thrown by the iteration.
// In this snippet, it can // only be thrown by newDirectoryStream.
System.err.println(x);
}
Using only JDK, If all your files are in one directory:
File dir = new File("path/to/files/");
for (File file : dir.listFiles()) {
Scanner s = new Scanner(file);
// do something with file
s.close();
}
To exclude files, you can use listFiles(FileFilter)