Skip to content

Commit bfd84db

Browse files
committed
feat(recursive-access): Seção de acessar diretórios.
Criação da seção sobre acesso de diretório, de forma recursiva ou não, utilizando DirectoryStream e FileVisitor. Ref. Issue #35
1 parent e2a1623 commit bfd84db

9 files changed

+493
-1
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
:java-package: src/org/j6toj8/fileio
2+
:section-java-package: ../../../{java-package}
3+
4+
=== DirectoryStream e FileVisitor
5+
6+
.Objetivo
7+
--------------------------------------------------
8+
Recursively access a directory tree by using the DirectoryStream and FileVisitor interfaces
9+
-
10+
Acessar recursivamente uma árvore de diretório usando as interfaces DirectoryStream e FileVisitor
11+
--------------------------------------------------
12+
13+
Nestão seção serão apresentadas duas classes para percorrer diretórios: `DirectoryStream` e `FileVisitor`.
14+
15+
. É possível checar vários atributos de um `Path` utilizando a classe `Files`.
16+
+
17+
[source,java,indent=0]
18+
.{java-package}/recursiveaccess/Recursive_DirectoryStream.java
19+
----
20+
include::{section-java-package}/recursiveaccess/Recursive_DirectoryStream.java[tag=code]
21+
----
22+
+
23+
.Saída no console
24+
[source,console]
25+
----
26+
Path: /home/rinaldo/arquivos
27+
/home/rinaldo/arquivos/arquivo1.txt
28+
/home/rinaldo/arquivos/arquivo3.txt
29+
/home/rinaldo/arquivos/subpasta1
30+
/home/rinaldo/arquivos/arquivo2.txt
31+
/home/rinaldo/arquivos/arquivo1.txt
32+
/home/rinaldo/arquivos/arquivo3.txt
33+
/home/rinaldo/arquivos/subpasta1
34+
/home/rinaldo/arquivos/arquivo2.txt
35+
----
36+
+
37+
Perceba que a instância de `DirectoryStream`:
38+
+
39+
* Pode ser utilizada com try-with-resources.
40+
* Pode ser iterada com a sintaxe de for-each.
41+
* Pode ser iterada com o método `forEach` que recebe uma expressão lambda.
42+
* Lança exceção caso o arquivo não exista.
43+
* Não lista os subdiretórios de forma recursiva, mas sim apenas o primeiro nível.
44+
* Não tem relação com a API de _Streams_ do Java 8.
45+
46+
. É possível acessar toda uma árvore de diretórios utilizando um `FileVisitor`.
47+
+
48+
[source,java,indent=0]
49+
.{java-package}/recursiveaccess/Recursive_SimpleFileVisitor.java
50+
----
51+
include::{section-java-package}/recursiveaccess/Recursive_SimpleFileVisitor.java[tag=code]
52+
----
53+
+
54+
.Saída no console
55+
[source,console]
56+
----
57+
Path: /home/rinaldo/arquivos
58+
Arquivo visitado: /home/rinaldo/arquivos/arquivo1.txt. Tamanho: 2
59+
Arquivo visitado: /home/rinaldo/arquivos/arquivo3.txt. Tamanho: 10
60+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta12/arquivo122.txt. Tamanho: 10
61+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta12/arquivo121.txt. Tamanho: 10
62+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo11.txt. Tamanho: 10
63+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo12.txt. Tamanho: 2
64+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo13.txt. Tamanho: 2
65+
Arquivo visitado: /home/rinaldo/arquivos/arquivo2.txt. Tamanho: 2
66+
----
67+
+
68+
Perceba que todos os arquivos do diretório e subdiretórios foram visitados e impressos no console ao invocar `Files.walkFileTree`. Para cada arquivo encontrado foi invocado o método `visitFile` da instância de `MeuFileVisitor`.
69+
+
70+
Veja que foi retornado `FileVisitResult.CONTINUE` do método `visitFile`. Isso instrui o FileVisitor a continuar visitando a árvore de arquivos. Também é possível retornar `TERMINATE`, `SKIP_SUBTREE` e `SKIP_SIBLINGS`, que serão apresentados a seguir.
71+
72+
. É possível finalizar a visitação quando for necessário retornando `FileVisitResult.TERMINATE`.
73+
+
74+
[source,java,indent=0]
75+
.{java-package}/recursiveaccess/Recursive_VisitorTerminate.java
76+
----
77+
include::{section-java-package}/recursiveaccess/Recursive_VisitorTerminate.java[tag=code]
78+
----
79+
+
80+
.Saída no console
81+
[source,console]
82+
----
83+
Path: /home/rinaldo/arquivos
84+
Arquivo visitado: /home/rinaldo/arquivos/arquivo1.txt. Tamanho: 2
85+
Arquivo visitado: /home/rinaldo/arquivos/arquivo3.txt. Tamanho: 10
86+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta12/arquivo122.txt. Tamanho: 10
87+
Arquivo encontrado. Finalizando.
88+
----
89+
90+
. Também é possível tomar decisões antes e depois de visitar diretórios.
91+
+
92+
[source,java,indent=0]
93+
.{java-package}/recursiveaccess/Recursive_VisitorDirectory.java
94+
----
95+
include::{section-java-package}/recursiveaccess/Recursive_VisitorDirectory.java[tag=code]
96+
----
97+
+
98+
.Saída no console
99+
[source,console]
100+
----
101+
Path: /home/rinaldo/arquivos
102+
Arquivo visitado: /home/rinaldo/arquivos/arquivo1.txt. Tamanho: 2
103+
Arquivo visitado: /home/rinaldo/arquivos/arquivo3.txt. Tamanho: 10
104+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo11.txt. Tamanho: 10
105+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo12.txt. Tamanho: 2
106+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo13.txt. Tamanho: 2
107+
Arquivo visitado: /home/rinaldo/arquivos/arquivo2.txt. Tamanho: 2
108+
----
109+
110+
. Também é possível ignorar todos os elementos que estão no mesmo nível de um `Path`.
111+
+
112+
[source,java,indent=0]
113+
.{java-package}/recursiveaccess/Recursive_VisitorIgnoreSiblings.java
114+
----
115+
include::{section-java-package}/recursiveaccess/Recursive_VisitorIgnoreSiblings.java[tag=code]
116+
----
117+
+
118+
.Saída no console
119+
[source,console]
120+
----
121+
Path: /home/rinaldo/arquivos
122+
Arquivo visitado: /home/rinaldo/arquivos/arquivo1.txt. Tamanho: 2
123+
Arquivo visitado: /home/rinaldo/arquivos/arquivo3.txt. Tamanho: 10
124+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta12/arquivo122.txt. Tamanho: 10
125+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta12/arquivo121.txt. Tamanho: 10
126+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo11.txt. Tamanho: 10
127+
Arquivo visitado: /home/rinaldo/arquivos/arquivo2.txt. Tamanho: 2
128+
----
129+
130+
. É possível implementar diretamente a interface `FileVisitor`, ao invés de `SimpleFileVisitor`, e implementar todos os seus métodos.
131+
+
132+
[source,java,indent=0]
133+
.{java-package}/recursiveaccess/Recursive_FileVisitor.java
134+
----
135+
include::{section-java-package}/recursiveaccess/Recursive_FileVisitor.java[tag=code]
136+
----
137+
+
138+
.Saída no console
139+
[source,console]
140+
----
141+
Path: /home/rinaldo/arquivos
142+
Antes de visitar o diretório: /home/rinaldo/arquivos
143+
Arquivo visitado: /home/rinaldo/arquivos/arquivo1.txt
144+
Arquivo visitado: /home/rinaldo/arquivos/arquivo3.txt
145+
Antes de visitar o diretório: /home/rinaldo/arquivos/subpasta1
146+
Antes de visitar o diretório: /home/rinaldo/arquivos/subpasta1/subpasta12
147+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta12/arquivo122.txt
148+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta12/arquivo121.txt
149+
Após de visitar o diretório: /home/rinaldo/arquivos/subpasta1/subpasta12
150+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo11.txt
151+
Antes de visitar o diretório: /home/rinaldo/arquivos/subpasta1/subpasta11
152+
Após de visitar o diretório: /home/rinaldo/arquivos/subpasta1/subpasta11
153+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo12.txt
154+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo13.txt
155+
Após de visitar o diretório: /home/rinaldo/arquivos/subpasta1
156+
Arquivo visitado: /home/rinaldo/arquivos/arquivo2.txt
157+
Após de visitar o diretório: /home/rinaldo/arquivos
158+
----
159+
160+
. É possível definir opções adicionais e limitar a profundidade utilizando outra versão do método `walkFileTree`.
161+
+
162+
[source,java,indent=0]
163+
.{java-package}/recursiveaccess/Recursive_VisitorOptionsAndDepth.java
164+
----
165+
include::{section-java-package}/recursiveaccess/Recursive_VisitorOptionsAndDepth.java[tag=code]
166+
----
167+
+
168+
.Saída no console
169+
[source,console]
170+
----
171+
Path: /home/rinaldo/arquivos
172+
Arquivo visitado: /home/rinaldo/arquivos/arquivo1.txt
173+
Arquivo visitado: /home/rinaldo/arquivos/arquivo3.txt
174+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta12
175+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo11.txt
176+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/subpasta11
177+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo12.txt
178+
Arquivo visitado: /home/rinaldo/arquivos/subpasta1/arquivo13.txt
179+
Arquivo visitado: /home/rinaldo/arquivos/arquivo2.txt
180+
----
181+
182+
****
183+
184+
* Working with Directories
185+
+
186+
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide (p. 617). Wiley. Edição do Kindle.
187+
188+
* https://www.baeldung.com/java-list-directory-files[List Files in a Directory in Java.]
189+
190+
* https://www.baeldung.com/java-nio2-file-visitor[A Guide To NIO2 FileVisitor.]
191+
192+
* https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html[Class DirectoryStream.] Java Plataform SE 7.
193+
194+
* https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileVisitor.html[Class FileVisitor.] Java Plataform SE 7.
195+
196+
* https://docs.oracle.com/javase/tutorial/essential/io/pathOps.html[Path Operations.] The Java™ Tutorials.
197+
198+
****

ch07-java-file-io.asc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
== Java File I/O (NIO.2)
33

44
include::book/07-java-file-io/sections/01-paths.asc[]
5-
include::book/07-java-file-io/sections/02-files.asc[]
5+
include::book/07-java-file-io/sections/02-files.asc[]
6+
include::book/07-java-file-io/sections/03-recursive-access.asc[]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.j6toj8.fileio.recursiveaccess;
2+
3+
import java.io.IOException;
4+
import java.nio.file.DirectoryStream;
5+
import java.nio.file.Files;
6+
import java.nio.file.Path;
7+
import java.nio.file.Paths;
8+
9+
public class Recursive_DirectoryStream {
10+
11+
public static void main(String[] args) {
12+
// tag::code[]
13+
String userHome = System.getProperty("user.home");
14+
Path path = Paths.get(userHome, "arquivos");
15+
System.out.println("Path: " + path);
16+
17+
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path)) {
18+
// iteração com sintaxe for-each
19+
for (Path subPath : directoryStream) {
20+
System.out.println(subPath);
21+
}
22+
} catch (IOException e) {
23+
e.printStackTrace();
24+
}
25+
26+
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path)) {
27+
// iteração com operação forEach e expressão lambda
28+
directoryStream.forEach(p -> System.out.println(p));
29+
} catch (IOException e) {
30+
e.printStackTrace();
31+
}
32+
// end::code[]
33+
}
34+
35+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.j6toj8.fileio.recursiveaccess;
2+
3+
import java.io.IOException;
4+
import java.nio.file.FileVisitResult;
5+
import java.nio.file.FileVisitor;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.Paths;
9+
import java.nio.file.attribute.BasicFileAttributes;
10+
11+
public class Recursive_FileVisitor {
12+
13+
// tag::code[]
14+
static class MeuFileVisitor implements FileVisitor<Path> {
15+
@Override
16+
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
17+
System.out.println("Arquivo visitado: " + file);
18+
return FileVisitResult.CONTINUE;
19+
}
20+
21+
@Override
22+
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
23+
System.out.println("Antes de visitar o diretório: " + dir);
24+
return FileVisitResult.CONTINUE;
25+
}
26+
27+
@Override
28+
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
29+
System.out.println("Após de visitar o diretório: " + dir);
30+
return FileVisitResult.CONTINUE;
31+
}
32+
33+
@Override
34+
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
35+
System.out.println("Falhou ao visitar o arquivo: " + file);
36+
return FileVisitResult.CONTINUE;
37+
}
38+
}
39+
40+
public static void main(String[] args) {
41+
String userHome = System.getProperty("user.home");
42+
Path path = Paths.get(userHome, "arquivos");
43+
System.out.println("Path: " + path);
44+
try {
45+
Files.walkFileTree(path, new MeuFileVisitor());
46+
} catch (IOException e) {
47+
e.printStackTrace();
48+
}
49+
}
50+
// end::code[]
51+
52+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.j6toj8.fileio.recursiveaccess;
2+
3+
import java.io.IOException;
4+
import java.nio.file.FileVisitResult;
5+
import java.nio.file.Files;
6+
import java.nio.file.Path;
7+
import java.nio.file.Paths;
8+
import java.nio.file.SimpleFileVisitor;
9+
import java.nio.file.attribute.BasicFileAttributes;
10+
11+
public class Recursive_SimpleFileVisitor {
12+
13+
// tag::code[]
14+
// Implementação simples de um SimpleFileVisitor
15+
static class MeuFileVisitor extends SimpleFileVisitor<Path> {
16+
@Override
17+
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
18+
// Método que será invocado a cada arquivo encontrado
19+
System.out.println("Arquivo visitado: " + file + ". Tamanho: " + attrs.size());
20+
return FileVisitResult.CONTINUE; // instrui o FileVisitor a continuar seguindo a árvore de arquivos
21+
}
22+
}
23+
24+
public static void main(String[] args) {
25+
String userHome = System.getProperty("user.home");
26+
Path path = Paths.get(userHome, "arquivos");
27+
System.out.println("Path: " + path);
28+
try {
29+
// Utilização da classe MeuFileVisitor para acessar
30+
// todos os arquivos no diretório e seus subdiretórios
31+
Files.walkFileTree(path, new MeuFileVisitor());
32+
} catch (IOException e) {
33+
e.printStackTrace();
34+
}
35+
}
36+
// end::code[]
37+
38+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.j6toj8.fileio.recursiveaccess;
2+
3+
import java.io.IOException;
4+
import java.nio.file.FileVisitResult;
5+
import java.nio.file.Files;
6+
import java.nio.file.Path;
7+
import java.nio.file.Paths;
8+
import java.nio.file.SimpleFileVisitor;
9+
import java.nio.file.attribute.BasicFileAttributes;
10+
11+
public class Recursive_VisitorDirectory {
12+
13+
// tag::code[]
14+
static class MeuFileVisitor extends SimpleFileVisitor<Path> {
15+
@Override
16+
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
17+
System.out.println("Arquivo visitado: " + file + ". Tamanho: " + attrs.size());
18+
return FileVisitResult.CONTINUE;
19+
}
20+
21+
@Override
22+
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
23+
// Ação que será executada antes de visitar um diretório
24+
if (dir.getFileName().toString().equals("subpasta12")) {
25+
return FileVisitResult.SKIP_SUBTREE; // ignora o diretório subpasta12
26+
}
27+
return FileVisitResult.CONTINUE;
28+
}
29+
30+
@Override
31+
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
32+
// Ação que será executada depois de visitar um diretório
33+
return FileVisitResult.CONTINUE;
34+
}
35+
36+
}
37+
38+
public static void main(String[] args) {
39+
String userHome = System.getProperty("user.home");
40+
Path path = Paths.get(userHome, "arquivos");
41+
System.out.println("Path: " + path);
42+
try {
43+
Files.walkFileTree(path, new MeuFileVisitor());
44+
} catch (IOException e) {
45+
e.printStackTrace();
46+
}
47+
}
48+
// end::code[]
49+
50+
}

0 commit comments

Comments
 (0)