Capture filename in directory

Asked

Viewed 5,903 times

4

The following method takes the name of the files of a given directory and displays them on the screen, the problem is that the .listfiles() returns the number of bytes and not the number of files, despite showing the name of the files I ended up having an error of Arrayindexoutofboundsexception since I am trying to access values that do not exist. How can I get the name of the directory files without errors?

   public static void getImgs(String path){
    File file = new File(path);
    File[] arquivos = file.listFiles();

    for (int i=0; i<file.length(); i++) {
        System.out.println(arquivos[i]);
    }
}

5 answers

5


The easiest way not to fall into this Exception is to use a foreach. Example:

public static void getImgs(String path){
    File file = new File(path);
    File[] arquivos = file.listFiles();

    for (File arquivo : arquivos) {
        System.out.println(arquivo);
    }
}

In for (File arquivo : arquivos) JVM itself is responsible for iterating through the files on your list, and it ensures that you will never have a arquivo that does not exist in the array (but the variable itself depends on its list, so in other cases arquivo could contain the value null, for example).

4

Whenever possible prefer the new Java 8 API that uses the class Path.

For example, you can list the files in a directory like this:

Files.walk(Paths.get("/tmp"), 1, FileVisitOption.FOLLOW_LINKS)
        .forEach(path -> System.out.printf("%s%n", path.toAbsolutePath().toString()));

The first parameter is the directory itself, which is a Path built using the method Paths.get(). Note that this method can receive an arbitrary amount of parameters, so you no longer have to worry about bars, because you can always specify each component of the path in a separate parameter.

The second argument defines whether the routine will read subdirectories. In this case, 1 (a) means that I am listing only the current directory. To read all subdirectories, use Integer.MAX_VALUE.

The third parameter receives FileVisitOption.FOLLOW_LINKS to indicate to Java that it should consider the shortcuts as used in linux/Unix. I consider it important to always use this parameter.

The method walk returns a Stream, which is the functional form of Java 8 to traverse a sequence of elements. The forEach allows you to execute a command for each element of the Stream, which in this case prints the absolute path within the expression lambda.

If you want to, for example, filter file types, you can do so:

Files.walk(Paths.get("/tmp"), 1, FileVisitOption.FOLLOW_LINKS)
        .filter(path -> path.toString().endsWith(".log"))
        .forEach(path -> System.out.printf("%s%n", path.toAbsolutePath().toString()));

The difference here is the filter that leaves in the Stream all paths that end with .log. The syntax may not be easy at first, but what the code does is pretty obvious.

Finally, there is a shortcut to already filter the files at the time of listing, the method Files.find. Example:

Files.find(Paths.get("/tmp"), 1,
        (path, attributes) -> attributes.isRegularFile() && path.toString().endsWith(".log"),
        FileVisitOption.FOLLOW_LINKS
).forEach(path -> System.out.println(path.toAbsolutePath()));

This method is more efficient and allows you to easily access file attributes. In case, I am checking if it is a normal file and not a directory or symbol using attributes.isRegularFile().

3

Can use DirectoryStream<T> where the generic type is an interface Path:

// C:\Users\Fulano\Desktop
Path diretorio = Paths.get("C:", "Users", "Fulano", "Desktop");

try (DirectoryStream<Path> stream = Files.newDirectoryStream(diretorio){
  for(Path path : stream)
     System.out.println(path.getFileName());
}

If you need to list files with specific extensions, use the second method parameter Files#newDirectoryStream() passing a string with the filtered extensions template:

// Listando todos os arquivos com extensão ".java"
try (DirectoryStream<Path> stream = Files.newDirectoryStream(diretorio, "*.java"){
  for(Path path : stream)
     System.out.println(path.getFileName());
}
// Listando arquivos com extensão .jpg, .gif e .png     
try (DirectoryStream<Path> stream = Files.newDirectoryStream(diretorio, "*.{jpg,gif,png}"){
  for(Path path : stream)
     System.out.println(path.getFileName());
}

In case you want to go further and also get the files that are in folders in that same directory, I found in that reply [en] a solution using recursiveness.

3

Another approach is to use the library Apache Commons IO. It has several utility methods.

For example the method listFiles(java.io.File, java.lang.String[], boolean). Where you define a root directory, a String array with extensions and a Boolean indicating whether the search should be recursive (in subdirectories). At the end you can manipulate the Collection resultant.

-1

Follow a simple way that helped me and can help you too:

Components used:

  1. 01 Jtextfield with the name "txtCaminho";
  2. 01 Jbutton with the name "btnBusca";

JFileChooser fc = new JFileChooser();
fc.showOpenDialog(this);

try {

  File arquivo = fc.getSelectedFile();
  String caminho = arquivo.getAbsolutePath();
  caminho = caminho.replace('\\', '/');

  // aqui eu mostro numa JTextField o caminho absoluto
  txtLocal.setText(caminho);                 

  String nomeArq = new File(caminho).getName();
  System.out.println(nomeArq);

} catch (Exception e) {
  System.out.println("Deu tudo errado...);
}
  • 1

    It would be interesting to remove the swing components as this is irrelevant to the solution of the problem.

  • Yes, of course! I actually posted the code I’m using here. But it was worth the alert!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.