This question already has answers here:
How to add new elements to an array?
(19 answers)
Closed 8 years ago.
First, let me show you the code I have so far:
public void populateArray(){
//NOTE: THIS METHOD SHOULD BE RUN FIRST. Many of the methods in this class rely on a populated file array to function.
// This method will populate our file array.
// First, we note the directory we want to pull files from.
File folder = new File("HR");
File dir = new File("");
File file = new File("");
//Then we fill an array with the list of documents in that directory
//This will also include folders.
int count = 0;
allDocs = folder.listFiles();
int fileCount = 0;
int dirCount = 0;
System.out.println("Displaying contents of directory...");
while (count < allDocs.length){
System.out.println("Found: " + allDocs[count]);
count++;
}
System.out.println("Sorting directories and files separately...");
count = 0;
while (count < allDocs.length){
if (allDocs[count].isDirectory()){
dir = new File(allDocs[count].getPath());
dirs[dirCount] = dir;
System.out.println("Document " + allDocs[count].getPath() + " sorted into -Directory- array at position " + dirCount);
dirCount++;
}
else{
file = new File(allDocs[count].getPath());
files[fileCount] = file;
System.out.println("Document " + allDocs[count].getPath() + " sorted into -File- array at position " + fileCount);
fileCount++;
}
count++;
}
return;
}
files, dirs, and allDocs are arrays declared within the class outside of any methods.
allDocs is the array I use to get every directory and file in the directory of interest, HR. I do this with allDocs = folder.listFiles();
I want files to be the array to store all of the files in the directory HR, and I want dirs to be the array to store all of the directories in HR, but I don't want to store any of the contents of the directors in HR.
I try to do this with the loop under the println "Sorting directories and files separately."
The problem is here:
else{
file = new File(allDocs[count].getPath());
files[fileCount] = file;
System.out.println("Document " + allDocs[count].getPath() + " sorted into -File- array at position " + fileCount);
fileCount++;
}
It's here because the first element in allDocs is a file. The problem also occurs when the first element is a directory. The problem is a null pointer exception on the files[fileCount] = file; line, which I don't understand. "file" is not null, I just assigned it a value. Of course files[fileCount] is null in this case, but why does that matter if I'm assigning it a value?
Files declaration:
public class Methods
{
private static File[] files;
You might prefer to simplify:
List<File> fileList = new ArrayList<>();
List<File> dirList = new ArrayList<>();
while (count < allDocs.length){
if (allDocs[count].isDirectory()){
dirList.add(allDocs[count]);
System.out.println("Document " + allDocs[count].getPath()
+ " sorted into -Directory- array at position " + dirCount);
dirCount++;
}
else{
fileList.add[allDocs[count]);
System.out.println("Document " + allDocs[count].getPath()
+ " sorted into -File- array at position " + fileCount);
fileCount++;
}
count++;
}
dirs = dirist.toArray(new File[dirList.size()]);
dirCount = dirs.length;
files = fileList.toArray(new File[fileList.size()]);
fileCount = files.length;
Using a List<File> instead of File[] seems appropiate, as you do not know the array sizes in advance, and you need:
File[] files = new File[n];
if intending to fill in a File:
files[fileCount] = ...
You might have forgotten to allocate the array - like this:
java.io.File [] files = new java.io.File[10];
If you only declared it like this:
java.io.File [] files;
files will be null and files[fileCount] will cause a NullPointerException.
As mentioned in the comments, you might like to change it to:
java.util.List<java.io.File> files = new ArrayList<>();
and add the files like:
files.add(file);
This way you won't have to know the number of entries in advance.
Related
i am creating a file and when i create that file, i check if it already exists. If it already exists, i want to create it with the same name, but with the (1) after it. I am able to do that and here is the code :
File apkReceived = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName + ".apk");
if(apkReceived.exists()){
apkReceived=new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName + "(1)"+".apk");
}
byte[] buffer = new byte [8192];
FileOutputStream fos=new FileOutputStream(apkReceived);
then it would continue... (i am writing things on the file).
This works but the problem is that in this situation :
FileTest.apk
FileTest(1).apk
If I receive another Filetest, it will sub my FileTest(1), since it will create it again.
A solution for this would be to check if the file exists again, but then i would have to be doing that for ever.
My goal would be to create (1) and then (2) , etc.
Does any one of you know how to do this ?
EDIT: Obviously i could use a cicle to check it. The problem is on how to get the (1) and then the (2) and don't get the (1)(2)
To avoid reinventing the wheel I suggest using Timestamp it hardly ever will have collisions.
java.util.Date date= new java.util.Date();
Timestamp tstamp = new Timestamp(date.getTime());
File apkReceived = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName + tstamp + ".apk");
Do Something like this
File apkReceived = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName + ".apk");
if(apkReceived.exists()){
int new_int_postfix;
//Below _MAX is max numbers of file eg. _MAX = 100
for(int i = 1; i < _MAX; i++) {
apkReceived = = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName +"("+ i +")"+".apk");
if(!apkReceived.exists()) {
String []name_without_pre = receivedApkName.split("\\(");
receivedApkName = name_without_pre[0];
new_int_postfix = i;
break;
}
}
apkReceived = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName + "("+new_int_postfix+")"+".apk");
}
byte[] buffer = new byte [8192];
FileOutputStream fos=new FileOutputStream(apkReceived);
Some pseudocode to get you started:
Fetch a list of all files in the directory
For the one you want to copy: check if you already have one or more copies
If you already have "file_(n)"; use "file_(n+1)" as new filename.
Obviously: you should clarify your requirements on the "maximum" n you want to allow; and what to happen when n copies were created; and another is asked for.
If you only store that one type of file in your directory you can do:
File folder = new File("your/path");
File[] listOfFiles = folder.listFiles();
count the size and size + 1 for your next filename.
you can also separate each file with similiar filename on their own directory.
try this
String filename =Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName + ".apk";
File f = new File(filename);
String extension = ".apk";
int g = 0;
while(f.exists()) {
int i = f.lastIndexOf('.');
if (i > 0)
{ extension = fileName.substring(i+1); }
f.renameTo(f.getPath() + "\" + (f.getName() + g) + "." + extension)
}
In my assets folder, I have a directory called "maps" which contains a list of images I want to load.
When running:
Gdx.files.internal("maps").exists();
This returns true
and:
Gdx.files.internal("maps/Africa.png").exists();
also returns true
However, trying to list these files seems to be unfeasible:
Gdx.files.internal("maps").list().length;
returns a value of 0 for the number of files in that directory
Moreover:
Gdx.files.internal("maps").isDirectory();
returns false.
This is very puzzling for what could have seemed to been a very straightforward way of getting files from a directory.
Does anyone have any ideas to circumvent this?
Since desktop builds cannot use the list() method on internal directories, I created this script to write the file names to a text file. It uses Apache commons.io (you can put compile "commons-io:commons-io:2.4+" into your build.gradle to include it in your desktop module):
//directories within assets that you want a catalog of
static final String[] directories = {
"completeMaps",
"typeAMaps",
"typeBMaps",
"sfx",
"music"
};
public static void main (String[] args){
String workingDir = System.getProperty("user.dir");
for (String dir : directories){
File directory = new File(workingDir + "/" + dir);
File outputFile = new File(directory, "catalog.txt");
FileUtils.deleteQuietly(outputFile); //delete previous catalog
File[] files = directory.listFiles();
try {
for (int i = 0; i < files.length; i++) {
FileUtils.write(outputFile, files[i].getName() + (i == files.length - 1 ? "" : "\n"), true);
}
} catch (IOException e){
Util.logError(e);
}
}
}
Then to get a file list in a directory:
private FileHandle[] readDirectoryCatalogue (String directory){
String[] fileNames = Gdx.files.internal(directory + "/catalog.txt").readString().split("\n");
FileHandle[] files = new FileHandle[fileNames.length];
for (int i = 0; i < fileNames.length; i++) {
files[i] = Gdx.files.internal(directory + "/" + fileNames[i].replaceAll("\\s+",""));
}
return files;
}
i have a fileserver and client and want to rename files, if they already exists in downloadfolder. what is the best way to do that? I tried that code but it always create one copy and the next copy overwrites the first one.
File f = new File(FILE_DIR + fileName);
if(f.exists()) {
System.out.print("file already exists");
fileName = "copy_of_" + fileName;
}
In your class you declare :
private static int X = 0;
and then change the code to this:
File f = new File(FILE_DIR + fileName);
if(f.exists()) {
System.out.print("file already exists");
fileName = "copy_of_ " + X + fileName;
x++;
}
so everytime the x will increase by 1, (x++), so they will have different names.
I have an issue with my logic and I would appreciate some pointers. My code produces the Array Out Of Bounds Exception when I try to iterate through an array of files in a directory and store the files that end in .txt within another array.
I think my issue is that the array of all files is larger than the array of txt files, that seems the most logical reason for the error. The problem is I don't know why its finding more occurrences of txt files in the second loop vs the first.
Here is the code:
public static void ListFiles(String file_dir) {
String files;
int txtCounter = 0;
File folder = new File(file_dir);
File[] listOfFiles = folder.listFiles();
//Count all txt files
for (int y = 0; y < listOfFiles.length; y++) {
if (listOfFiles[y].isFile()) {
files = listOfFiles[y].getName();
if (files.endsWith(".txt") || files.endsWith(".TXT")) {
txtCounter++;//Add to the count
}
}
}
//Create array for the list of txt files.
String txtFiles[] = new String[txtCounter];
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
files = listOfFiles[i].getName();
if (files.endsWith(".txt") || files.endsWith(".TXT")) {
//Add all txt files to new array txtFiles
txtFiles[i] = folder + files;
System.out.println(txtFiles[i]);
}
}
}
//Send array back to Main
//return txtFiles[];
}
Am I making this harder than it has to be? I'm trying to take a list of text files, replace certain words in the files, and combine them all into one file when complete.
Thanks!
UPDATED:
public static String[] ListManualSections(String file_dir) {
file_dir = file_dir + "\\manualSections\\";
String files;
//Create list of all files in the manualSections directory.
File folder = new File(file_dir);
File[] listOfFiles = folder.listFiles();
//Dynamic list of text files
ArrayList al = new ArrayList();
//Add each occurrence of a text file to the ArrayList
for (int i = 0; i < listOfFiles.length; i++) {
files = listOfFiles[i].getName();
if (listOfFiles[i].isFile() && files.toLowerCase().endsWith(".txt")) {
al.add(folder + "\\" + files);
//System.out.println(al);
}
}
//Send list back to Main
String[] txtFiles = (String[]) al.toArray(new String[al.size()]);
return txtFiles;
}
This second for loop seems confused about whether it's iterating over txtFiles or over listOfFiles, which could have different lengths. In particular, you should probably not be writing to txtFiles[i] when i could be larger than the length of txtFiles.
Mostly, though, this code would be simpler if you just used an ArrayList.
As addition to the answer of #Louis, you could go with a separate counter for the file and txt-file. Like this:
int txtidx = 0;
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
files = listOfFiles[i].getName();
if (files.endsWith(".txt") || files.endsWith(".TXT")) {
//Add all txt files to new array txtFiles
txtFiles[txtidx] = folder + files;
System.out.println(txtFiles[txtidx]);
txtidx++;
}
}
}
instead of complicating matters, you can do this
Use Apache Commons io to list all your files
Collection<File> files = FileUtils.listFiles(new File("file_dir"), new String[]{"txt"}, true);
//use true if you want it to be recursive, i.e. to search subdirectories of file_dir
for (File file : files)
{
//you can then play with your file object here
}
Let me know if you have issues.
You're making this harder than it has to be.
You're passing over an array once to count how many text files there are and then, a second time, to add text files to another array.
Any implementer of the List<E> interface would be more appropriate than an array; you can then add elements on the fly. If you must have an array afterwards. you can always use the toArray method at the end.
Well look at this scenario -
listOfFiles is size 6, first loop you find 5 txt files, and the last element in listOfFiles is a txt file.
Then at the last iteration of second loop, you are trying to do txtFiles[5] = folder+files. That will throw the error because txtFiles is only 0-4.
Like Louis said, use ArrayList.
You could simply use File.listFiles(FileNameFilter) to get the files matching your criteria.
private File[] getTextFiles(String dir)
{
File folder = new File(dir);
return folder.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".txt");
}
});
}
Your second for loop iterates over all of the files, meaning that i = 0 .. N where N is the number of total files. But your text files could occur at any i here. The so even if there are only 2 text files, if they are found on the 6th iteration of the N total files, that is not the index you want to be using for your text file array.
I would suggest you create a counter for the index of the text file array and increment it as you add, or use a List.
String txtFiles[] = new String[txtCounter];
int txtIndex = 0;
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
files = listOfFiles[i].getName();
if (files.endsWith(".txt") || files.endsWith(".TXT")) {
//Add all txt files to new array txtFiles
txtFiles[txtIndex] = folder + files;
txtIndex++;
System.out.println(txtFiles[i]);
}
}
}
I have a list of files, the names of these files are are made of a classgroup and an id (eg. science_000000001.java)
i am able to get the names of all the files and split them so i am putting the classgroups into one array and the ids in another.. i have it so that the arrays cant have two of the same values.
This is the problem, i want to create a directory with these classgroups and ids, an example:
science_000000001.java would be in science/000000001/science_000000001.java
science_000000002.java would be in science/000000002/science_000000002.java
maths_000000001.java would be in maths/000000001/maths_000000001.java
but i cannot think of a way to loop through the arrays correctly to create the appropriate directories?
Also i am able to create the folders myself, its just getting the correct directories is the problem, does anyone have any ideas?
Given:
String filename = "science_000000001.java";
Then
File fullPathFile = new File(filename.replaceAll("(\\w+)_(\\d+).*", "$1/$2/$0"));
gives you the full path of the file, in this case science/000000001/science_000000001.java
If you want to create the directory, use this:
fullPathFile.getParentFile().mkdirs();
The above answer is really good for creating new files with that naming convention. If you wanted to sort existing files into their relative classgroups and Ids you could use the following code:
public static void main(String[] args) {
String dirPath = "D:\\temp\\";
File dir = new File(dirPath);
// Get Directory Listing
File[] fileList = dir.listFiles();
// Process each file
for(int i=0; i < fileList.length; i++)
{
if(fileList[i].isFile()) {
String fileName = fileList[i].getName();
// Split at the file extension and the classgroup
String[] fileParts = fileName.split("[_\\.]");
System.out.println("One: " + fileParts[0] + ", Two: " + fileParts[1]);
// Check directory exists
File newDir = new File(dirPath + fileParts[0] + "\\" + fileParts[1]);
if(!newDir.exists()) {
// Create directory
if(newDir.mkdirs()) {
System.out.println("Directory Created");
}
}
// Move file into directory
if(fileList[i].renameTo(new File(dirPath + fileParts[0] + "\\" + fileParts[1] + "\\" + fileName))) {
System.out.println("File Moved");
}
}
}
}
Hope that helps.