O conceito de fluxo de IO:
- fluxos de E/S, opere read() e write() da mesma maneira para diferentes entradas e saídas; crie diferentes tipos de fluxos, existem diferentes métodos de implementação, diferentes tipos de fluxos e seus próprios métodos de operação exclusivos.
- Independentemente de como funciona internamente, todos os fluxos de E/S apresentam o mesmo padrão simples, uma sequência de dados entrando ou saindo do programa.
Fluxo de entrada, fluxo de saída:
- Fluxo de entrada, a superclasse de operação do fluxo de saída, suporta subclasses para operar dados binários na forma de bytes básicos
- classe abstrata java.io.InputStream: subclasse básica, ByteArrayInputStream, FileInputStream, etc.;
- int read() lança IOException, o método abstrato é implementado por uma subclasse concreta, retorna o próximo byte no fluxo (deve ser um inteiro entre 0-255), se não houver byte legível no final do fluxo, retorna - 1.
- classe abstrata java.io.OutputStream: subclasse básica, ByteArrayOutputStream, FileOutputStream, etc.;
- void write(int b) lança o método abstrato IOException. Grava em bytes decimais no fluxo de saída.
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Paths; public class TestIO { public static void main(String[] args) { try { getByteStreams(); } catch (IOException e) { e.printStackTrace(); } } public static void getByteStreams()throws IOException { FileInputStream in=new FileInputStream("C:/Users/yu/Desktop/a.txt"); FileOutputStream out=new FileOutputStream("C:/Users/yu/Desktop/b.txt"); int c; while((c=in.read())!=-1){ System.out.println("读取字节的10进制整数:"+c); out.write(c); } in.close();//有个问题就在于一旦异常了资源就无法关闭; out.close(); } }
Fechamento do objeto de recurso:
Fechando arquivos de recursos: Arquivos de recursos, como fluxos de E/S, não liberarão automaticamente os recursos ocupados devido à perda de referência como outros objetos. Portanto, eles devem ser fechados corretamente, caso contrário, causará estouro de memória. Tome fluxos de E/S como exemplo, a fim de garantir Independentemente de ocorrer uma exceção, o recurso é fechado, e o recurso deve ser fechado manualmente no bloco finally, mas isso tornará o programa muita redundância;
Solução: introduza a interface java.lang.AutoCloseable, qualquer tipo que implemente a interface AutoCloseable é um tipo de recurso que suporta fechamento automático. Em seguida, use try-with-resources, na instrução try, declare os recursos que precisam ser fechados, para garantir que, independentemente de o bloco try lançar uma exceção ou não, os recursos serão fechados automaticamente após o término do bloco try ( Java7);
A interface java.io.Closeable herda a interface AutoCloseable. Todos os recursos que precisam ser fechados manualmente chamando o método close(), todos suportam o fechamento automático de try-with-resources.
A instrução try-with-resources simplifica bastante o código de processamento de recursos, para que os desenvolvedores não precisem se preocupar com o status do recurso, a ordem na qual os objetos de recurso são criados ou a maneira correta de fechar os objetos de recurso.
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Paths; public class TestIO { public static void main(String[] args) { getByteStreams(); } public static void getByteStreams() { try (FileInputStream in = new FileInputStream("C:/Users/yu/Desktop/a.txt"); FileOutputStream out = new FileOutputStream("C:/Users/yu/Desktop/b.txt");) { int c; while ((c = in.read()) != -1) { System.out.println("读取字节的10进制整数:" + c); out.write(c); } in.close();//有个问题就在于一旦异常了资源就无法关闭; out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
Perceber:
(1) O desligamento automático de recursos nada tem a ver com exceções. Como lidar com a exceção ainda é como lidar com ela.
(2) Após declarar o recurso na instrução try, a sequência de execução:
Sem exceção, após a execução do bloco try, o recurso é fechado automaticamente, finalmente bloco
- Há uma exceção, feche automaticamente o recurso, capture o bloco, finalmente bloqueie
Processamento de operação de E/S com base no buffer de matriz de caracteres:
- O método read()/write() básico baseado em byte único mencionado acima é usado apenas para entender o processo de execução do fluxo de E/S e não será usado no desenvolvimento real. O método de operação IO baseado no buffer de array de bytes é usado:
int read(byte[] b), o método declarado em InputStream, lê os bytes do fluxo no array de bytes b, o primeiro byte é colocado na posição 0 do array... até a palavra com o comprimento do array b é a posição da seção lida; retorna o comprimento dos bytes lidos; se não houver bytes legíveis, retorna -1.
- write(byte[] b, int off, int len), o método declarado em OutputStream, inicia a leitura do array de bytes b, off position, e termina no comprimento len;
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Paths; public class TestIO { public static void main(String[] args) { getByteStreams(); } public static void getByteStreams() { try (FileInputStream in = new FileInputStream("C:/Users/yu/Desktop/a.txt"); FileOutputStream out = new FileOutputStream("C:/Users/yu/Desktop/b.txt");) { byte []buffer=new byte[2]; int len=0; while((len=in.read(buffer))!=-1){ out.write(buffer,0,len); } in.close();//有个问题就在于一旦异常了资源就无法关闭; out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
caminho:
Caminho absoluto, sempre incluindo o elemento raiz e a lista completa de diretórios necessários para localizar os arquivos. Por exemplo, D:/test/a.txt. Todas as informações necessárias para encontrar o arquivo estão incluídas na declaração do caminho
Um caminho relativo, por exemplo, a.txt. O programa não estará acessível sem mais informações. Ou seja, caminhos relativos devem, em última análise, também ser descritos com base em caminhos absolutos.
Por que usar o NIO:
A classe Java.io.File contém classes que combinam declarações de caminho de arquivo e métodos de operação de arquivo; e é bloqueada de forma síncrona
NIO2 (java8), separa caminhos de arquivo de operações de arquivo; e suporta não-bloqueio assíncrono
Interface java.nio.file.Path, representando o caminho absoluto/relativo dos arquivos/diretórios do sistema
A classe de ferramenta java.nio.file.Files contém métodos para lidar com operações de arquivo, incluindo criação, exclusão, cópia, movimentação etc.
Interface de caminho: Caminho representa um caminho de arquivo independente do sistema. Ou seja, a implementação específica do Path é diferente em diferentes sistemas operacionais (windows/linux), mas os desenvolvedores precisam apenas descrever o caminho para o Path, sistemas diferentes e não precisam se preocupar com as diferenças nos sistemas operacionais.
Path get(String path): O método mais comumente usado para converter a string de caminho convertida em um objeto Path.
Path define muitos métodos para obter informações de dados de arquivos e métodos de emenda para caminhos:
Path getFileName(), retorna o nome do arquivo ou o último elemento de uma sequência de elementos de nome. Ou seja, a última descrição do caminho, que pode ser um nome de arquivo ou um nome de diretório
Path getParent(), retorna o caminho do diretório pai
Path getRoot(), retorna a raiz do caminho
Método de resolução de caminho (caminho outro), que une o caminho em um novo caminho
boolean equals(Object obj): reescreve equals para determinar se os caminhos são os mesmos
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; public class TestIO { public static void main(String[] args) { Path p= Paths.get("C:/Users/yu/Desktop"); Path p1=Paths.get("a.txt"); System.out.println(p.getClass().getName());//Path是一个接口输出实现类的名字 System.out.println(p); System.out.println(p.getFileName());//返回文件名或名称元素序列的最后一个元素。即,最后一个路径描述,可能是文件名也可能是目录名 System.out.println(p.getParent());//返回父目录的路径 System.out.println(p.getRoot());//返回路径的根 p.resolve(p1);//将路径拼接为一个新路径 p.equals(p1);//重写了equals判断路径是否相同 } }
Classe de ferramenta de arquivos:
A classe de ferramenta java.nio.file.Files fornece uma variedade de métodos estáticos baseados em operações de Caminho, leitura/gravação/operação, arquivos e diretórios. Classificação do método:
Julgamento de arquivo ou diretório:
boolean existe(caminho do caminho)/notExists(caminho do caminho), se o caminho do caminho existe
Boolean isDirectory(Path path), se o caminho é um diretório
Criação de um arquivo ou diretório:
Path createDirectory(Path dir) lança IOException. Exceção se o caminho do diretório já existir; o caminho do diretório é um diretório multinível, exceção
Path createDirectories(Path dir) lança IOException. Crie automaticamente um diretório multinível que não existe; o diretório já existe, sem exceção
Path createFile(path) lança IOException. Cria um arquivo com base no caminho especificado. arquivo existe, exceção
Cópia do arquivo ou diretório:
A cópia do caminho (Origem do caminho, destino do caminho, opções CopyOption...) lança IOException, copia o arquivo para o arquivo de destino. Por padrão, se o arquivo já existir, uma exceção
Se source for um diretório, os arquivos nele não serão copiados, é apenas equivalente a criar um diretório vazio
java.nio.file.StandardCopyOption enumeração, implementa a interface CopyOption, opções de cópia
Movimento de arquivos ou diretórios:
Path move(Path source, Path target, CopyOption... options) lança IOException, move ou renomeia o arquivo para o arquivo de destino.
Por padrão, se o arquivo de destino existir, ele será anormal, e a opção de movimentação pode ser declarada através do parâmetro options
Se você mover neste diretório, é equivalente a renomear o arquivo
Exclusão de um arquivo ou diretório:
void delete(path path) lança IOException. Exclua o caminho especificado; o caminho não existe, exceção
boolean deleteIfExists(Path path) lança IOException. O caminho não existe e não é excluído. Retorna se a exclusão foi bem-sucedida
Se o caminho for um diretório e o diretório contiver arquivos (ou seja, não estiver vazio), ambas as exclusões serão anormais
Traversal do caminho especificado (método Files):
Stream<Path> walk(Path start, int maxDepth) lança IOException: Traverse, atravesse diretórios e arquivos no caminho com base na profundidade especificada
Stream<Path> walk(Path start) lança IOException: Percorra todos os diretórios e arquivos no caminho, incluindo subdiretórios, observe a ordem de saída durante o percurso e os produza hierarquicamente. Observe que o valor de retorno é um fluxo e você pode usar operações de fluxo posteriormente, como filtragem, classificação e outras funções. Você pode excluir diretórios não vazios com a ajuda deste método
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.function.Consumer; public class TestIO { public static void main(String[] args) { try { path(); } catch (IOException e) { e.printStackTrace(); } } public static void path() throws IOException { Path p= Paths.get("C:/Users/yu/Desktop"); Path p1=Paths.get("a.txt"); Path p2=Paths.get("C:/Users/yu/Desktop/b.txt"); Path p3=Paths.get("C:/Users/yu/Desktop/a.txt"); // System.out.println(Files.exists(p));//Path路径是否存在 // System.out.println(Files.isDirectory(p));//path是否为目录 // System.out.println(Files.createDirectory(p));//目录的创建,目录路径已存在则异常;目录路径为多级目录,异常 // System.out.println(Files.createDirectories(p));//目录的创建,自动创建多级不存在目录;目录已存在,无异常 // System.out.println(Files.createFile(p2));//文件的创建,基于指定路径,创建文件。文件存在,异常; // Files.copy(p2,p3, StandardCopyOption.REPLACE_EXISTING);/*将文件复制到目标文件。默认,如果文件已经存在,异常 // 如果source为目录,不会复制里面的文件,仅相当于创建一个空目录 // java.nio.file.StandardCopyOption枚举,实现了CopyOption接口,复制选项*/ // Files.move(p2,p3,StandardCopyOption.REPLACE_EXISTING)/*将文件移动或重命名为目标文件。 // 默认,如果目标文件存在,则异常,可通过options参数声明移动选项 // 如果在本目录下移动,相当于文件改名*/ // Files.delete(p2);/*路径不存在,不删除。返回是否删除成功 //如果路径为目录,目录中包含文件(即不为空),2种删除均异常*/ Files.walk(p3).forEach(System.out::println); } }