0

This is my poor attempt at trying to create an array inside a static method. What this program does is list documents that have a certain extension. I want to be able to store them in an array and access that array from main. Is it possible? This is my code so far:

package recogniseKeywords;

import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;

import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

public class KeywordsRecognition {

    public static void listFilesForFolder(final File folder) {

        String[] files = {};
        int fileSize = 0;

        String[] extensions = {".doc", ".docm", ".xls"};

        for (final File fileEntry : folder.listFiles()) {
            if (fileEntry.isDirectory()) {
                listFilesForFolder(fileEntry);
            } else {

                for(int i=0; i<extensions.length; i++) {
                    //Check if contains one of the extensions and isn't a temporary file(~$)
                    if (fileEntry.getName().contains(extensions[i]) && !fileEntry.getName().startsWith("~$")) {
                        System.out.println(fileEntry.getName());
                        files[fileSize] = fileEntry.getName();
                        fileSize++;
                    }
                }
            }
        }

    }

    public static void main(String[] args) throws Exception {

        String[] keywords = {"Performance Enhancement", "Functional Specification", "Technical Specification", "Faults", "Arval", "Vehicle", "Fines", "Insurance"};


            final File folder = new File("C:/work");
            listFilesForFolder(folder);

            System.out.println(Arrays.toString(files));

        }
    }
}

I am aware that this is a static method and that int, as well as the array, is not treated as in a non-static method, however, I don't know how to proceed further.

5
  • 1
    Why don't you return the array from your static method? Commented Jan 25, 2018 at 9:50
  • 1
    There are two simple solutions: 1. return the array, 2. create a static array and access it after calling the method. Commented Jan 25, 2018 at 9:51
  • It looks like the files are not inserted into an array properly. I've checked how fileSize is incremented and it goes like 1,2,1,2,3... Commented Jan 25, 2018 at 9:55
  • Is this code working? Array has fixed length in Java, you should create a List append to it and then convert it to an array if needed, because you only know the number of entries afterwards. Commented Jan 25, 2018 at 9:55
  • @dsafasfsafasfsa yes that's another problem, you call it recursively, the file list and counter should be on class level not inside the method. Commented Jan 25, 2018 at 10:01

2 Answers 2

1

The best pointer I can give you is to leave the clutches of the static realm and go into instance-land, the land of object-oriented opportunities!

In your main method do this:

public static void main(String[] args) throws Exception {    
    KeywordsRecognition app = new KeywordsRecognition();
    app.start();
}

Then implement the start method and start your work there. Doing this will give you more options in your code design, allowing you to write more readable and testable code, and thus code with less bugs and maintenance issues.

To access the result of listFilesForFolder you can either return it, assign it to a field, or add it to a collection. Since you are recursing I would say: add it to a collection.

Rationale: each recursion adds to the same collection. You don't want intermediate results visible to other code than the recursion so avoid a field and use a method parameter. Also, it's quite common to pass data through a recursion in this manner, so other developers will understand it.

private static final String ROOT_FOLDER_DEFAULT = "C:/work";
private static final String[] EXTENSIONS = {".doc", ".docm", ".xls"};
// TODO: the keywords are not used anywhere yet
private static final String[] KEYWORDS = {"Performance Enhancement", "Functional Specification", "Technical Specification", "Faults", "Arval", "Vehicle", "Fines", "Insurance"};

public void start(String rootFolder) {       
    List<String> files = new ArrayList<>();
    readFilesRecursively(new File(rootFolder), files);
    // trick to print list contents by converting to array
    System.out.println(Arrays.toString(files.toArray()));
}        

// recursion is not that common so when you use it, 
// it's a good idea to clearly indicate this in the method name
public void readFilesRecursively(File folder, List<String> files) {
    for (File file : folder.listFiles()) {
        if (file.isDirectory()) {
            readFilesRecursively(file, files);
        } else {
            for(String extension : EXTENSIONS) {
                String fileName = file.getName();
                if (fileName.contains(extension ) && !isTemporaryFile(fileName)) {
                    files.add(fileName);
                }
            }
        }
    }
}

// if you find yourself adding a comment in the middle of your code
// that usually means you need to extract a method for that bit
private boolean isTemporaryFile(String fileName) {
    return fileName.startsWith("~$");
}

public static void main(String[] args) throws Exception {    
    KeywordsRecognition app = new KeywordsRecognition();
    app.start(getRootFolder(args));
}

private static String getRootFolder(String[] args) {
    if(args != null && args.length > 0) {
        return args[0];
    }
     else {
        return ROOT_FOLDER_DEFAULT:
    }
}

Sidenote: you cannot increase the size of an array; once you create it, its size is fixed. So either initialize the array to the correct length, or use a java.util.List instead (optionally converting the List to an array after it has been fully populated):

List<String> values = new ArrayList<>();
values.add("1");
values.add("foo");
values.add("elderberries");
String[] valuesAsArray = values.toArray();

Either that, or:

String[] valuesAsArray = new String[3];
values[0] = "1";
values[1] = "foo";
values[2] = "elderberries";
Sign up to request clarification or add additional context in comments.

3 Comments

There were some bugs and improvements but I'm think I'm done now. Didn't check it by compiling/running though. Thanks for the accept.
Adriaan Koster is it possible to get the files from oracle database table that are stored as blobs instead of directories on the pc?
Yes of course that's possible. You'll not need the recursive directory walking in your current code. But this has nothing to do with the current question. First try to solve it yourself and if you get stuck ask a new question in which you show your attempt and what exactly goes wrong.
0

The reason that main can't see the files variable in listFilesForFolder is that files is a local variable. Its scope is the listFilesForFolder method itself. (This would still be true if you declared main and listFilesForFolder as instance methods.)

There are a number of possible solutions. The most straightforward are:

  1. Return the value files as the result of listFilesForFolder, and use the returned value in main.

  2. Declare files as a static variable rather than a local variable.

  3. Declare files as an instance variable, and then change the code to be more object oriented; see Adrian's answer for an example.

Of these approaches, 1 and 3 are better. Approach 2 will work in a simple example like this, but is problematic (for various reasons) in a large application.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.