java nio.2: mais uma api para i/o?
TRANSCRIPT
Java NIO.2: Mais uma API para I/O?UMA RÁPIDA INTRODUÇÃO
Francisco OliveiraOzJUG - 2016
Who am I?Analista de Sistemas
● Iron Mountain do BrasilTecnólogo em Análise e Desenvolvimento de Sistemas
● Fatec IpirangaSocial
● [email protected]● @delley_fx● facebook.com/delley.fx● github.com/delley
O que há de errado com java.io.File?
●Falta de informação sobre o que está acontecendo●Operações com arquivo não são atômicas●Sem acesso em massa para atributos dos arquivos●Difilcudades para escalar listagem de diretórios●Faltam operações básicas●Não é possível copiar atributos de um arquivo
Por que outra API para a MANIPULAÇÃO de ARQUIVOS?
●Suporte limitado para metadados do arquivo●Suporte limitado para links simbólicos●Não há maneiras de estender a API para implementações
de sistemas de arquivos customizados●Não há suporte para notificações
Por que outra API para a MANIPULAÇÃO de ARQUIVOS?
O design da API NIO.2Pacotes
● java.nio.file● java.nio.file.attribute● java.nio.file.spi
Path● Um caminho no sistema de arquivos
Paths● Fábrica de objetos Path (caminho)
Files● Classe com métodos estáticos para operações mais comuns
FileSystems● Fábrica de objetos FileSystem
FileStore● Encapsula o sistema de armazenamento
A interface Path●Representa um caminho absoluto ou relativo●Iterável sobre elementos de um caminho●Imutável●Operações para:
Acesso aos elementos de caminho Combinar caminhos Comparar caminhos
Criando um caminhoPath path = FileSystems.getDefault().getPath("/foo");
Criando um caminhoPath path = Paths.get("/foo");
Criando um caminhoURI uri = URI.create("file:///foo");Path path = Paths.get(uri);
Criando um caminhoFile file = new File("/foo");Path path = file.getPath();
Acessando elementos de um caminhoPath path = Paths.get("/","foo","bar","x");Path file = path.getFileName();Path parent = path.getParent();Path root = path.getRoot();Path subpath = path.subpath(1,3);
Acessando elementos de um caminhoPath path = Paths.get("/","foo","bar","x");
for (Path element : path ) { System.out.format("%s%n", element);}
Combinando caminhosPath foo = Paths.get("/", "foo");Path bar = foo.resolve("bar");Path baz = foo.resolveSibling("baz");Path qux = Paths.get("/", "baz", "qux");Path relative = foo.relativize(qux);
Testando caminhosPath path = Paths.get("top", "foo", "bar");boolean isStart = path.startsWith("to");boolean isEnd = path.endsWith("pot");boolean isAbs = path.isAbsolute();
Outras operaçõesPath path = Paths.get("top", "foo", "bar");Path normal = path.normalize();Path abs = path.toAbsolutePath();Path real = path.toRealPath();URI uri = path.toUri();File file = path.toFile();
A classe Files●Métodos estáticas para trabalhar com arquivos●A maioria das operações espera um Path como argumento●Operações para:
Leitura e Escrita de arquivos Streams, leitores (readers), escritores (writers) Links Simbólicos Trabalhar com diretórios
●Lança exceções significativas em caso de falha
Files: Operações básicasPath file = Files.createFile(path);Path dir = Files.createDirectory(pathDir);Path dir = Files.createDirectories(pathDir);
Files: Operações básicasimport static java.nio.charset.StandardCharsets.*;
List<String> lines = Files.readAllLines(file, UTF_8);byte[] bytes = Files.readAllBytes(file);
Files.delete(path);Files.deleteIfExists(path);
Files.copy(source, target);
Files.copy(source, target, ATOMIC_MOVE, REPLACE_EXISTING, COPY_ATTRIBUTES);
Files.move(source, target);
Files: Operações básicas
Files: Links simbólicosPath link = Paths.get("top", "link");
Path target = Paths.get("top", "foo", "tar");
Files.createSymbolicLink(link, target); boolean isSymLink = Files.isSymbolicLink(link);boolean isSame = Files.isSameFile(link, target);
Path tar = Files.readSymbolicLink(link);
Leitura (reader) e escrita (Writer)import static java.nio.charset.StandardCharsets.*;
import java.nio.file.StandardOpenOption;
Path file = ...
BufferedReader reader = Files.newBufferedReader(file, UTF_8);
BufferedWriter writer = Files.newBufferedWriter(file, UTF_8, StandardOpenOption.CREATE_NEW);
StreamsPath file = ...
InputStream is = Files.newInputStream(file);
OutputStream os = Files.newOutputStream(file);
OutputStream osAppend = Files.newOutputStream(file, CREATE, APPEND);
Atributos de arquivo●Metadados dos arquivos●Exemplo:
criado, atualizado, data do último acesso rwxr--r--
●Definido pela plataforma e sistemas de arquivos
Atributos de arquivoBasicFileAttributes
●Suportado por todas as plataformas●Datas (criação, modificação, último acesso), tipo
arquivo, tamanho, chave do arquivoDosFileAttributes
●Oculto, arquivo, somente leitura, sistemaPosixFileAttributes
●Dono, grupo, conjunto de permissões
Atributos de arquivoBasicFileAttributes basicAttr = Files.readAttributes(path, BasicFileAttributes.class);
String key = basicAttr.fileKey();long size = basicAttr.size();boolean isDirectory = basicAttr.isDirectory();FileTime lastModified = basicAttr.lastModifiedTime();
Atributos de arquivoPosixFileAttributes posixAttr = Files.readAttributes(path, PosixFileAttributes.class);
UserPrincipal owner = posixAttr.owner();GroupPrincipal group = posixAttr.group();String perms = PosixFilePermissions.toString( posixAttr.permissions()));
Files.setPosixFilePermissions(path, PosixFilePermissions.fromString("rwxrwxrwx"));
Listagem de Diretório● Iteração eficiente na listagem de diretórios●Escalabilidade para grandes diretórios, sistemas de
arquivos remotos, etc.●Suporta filtros:
Glob Regex Filtros personalizados
Listagem de Diretóriostry (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dir,"*.java")) { for (Path path : dirStream) { format("%s%n", path.toAbsolutePath()); }}
Listagem de DiretórioDirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { public boolean accept(Path entry) throws IOException { return Files.size(entry) > 1024; } };
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dir,filter)) { ...}
Percorrendo árvores de diretórios● Implementa o Padrão Visitor para percorrer árvores de
diretórios●Files.walkFileTree (start, fileVisitor)
start: nó incial fileVisitor: define operaçõe que serão realizadas
●Travessia em profundidade
Percorrendo árvores de diretórios●Métodos callbacks de FileVisitor:
preVisitDirectory visitFile postVisitDirectory visitFileFailed
●Enum FileVisitResult CONTINUE TERMINATE SKIP_SUBTREE SKIP_SIBLINGS
Percorrendo árvores de diretóriosPath start = Paths.get("/foo/bar");Files.walkFileTree(start, new SimpleFileVisitor<Path>(){ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { format("preVisitDirectory: %s%n", dir); return FileVisitResult.CONTINUE; }
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { format("visitFile: %s%n", file); return FileVisitResult.CONTINUE; }});
Watch Service●Monitora mudanças
Criar, atualizar, excluir●Usa notificações nativas
Watch ServiceWatchService watcher = FileSystems.getDefault().newWatchService();
Path dir = …
WatchKey watchKey = dir.register(watcher, ENTRY_MODIFY);
Watch Serviceboolean keepWatching = true;
while(keepWatching){ WatchKey key = watcher.poll(10, TimeUnit.SECONDS); for (WatchEvent<?> event: key.pollEvents()) { if (event.kind() == ENTRY_MODIFY) { Path name = (Path) event.context(); ... } } key.reset();}
Watch ServicePontos a observar no Mundo Real●Sub-diretórios não são monitorados●Alguns editores criam um novo arquivo ao atualizar
Esperamos uma ATUALIZAÇÃO, mas recebemos um evento EXCLUIR + CRIAR
●Alguns sistemas de arquivos criam inicialmente um arquivo com zero bytes
Esperamos um evento de CRIAR, mas observamos um CRIAR + ATUALIZAÇÃO
Sistema de arquivos personalizado●Permite a criação de sistemas de arquivos personalizados
FileSystemProvider●Sistema de arquivos em memória●O Provedor de sistema de arquivo Zip é fornecido como
uma implementação de referência
Considerações finais●NIO.2 funciona de forma consistente em todas as
plataformas●Suporta novas operações●Suporta o acesso em massa para atributos de arquivo●Exceções melhores●SPI para a interface de provedores de sistemas de
arquivos personalizados
OBRIGADO!!!