Visão geral
- E/S significa Entrada/Saída, ou seja, entrada/saída durante a transmissão de dados, e entrada e saída são relativas à memória.
- Fluxos Java IO (entrada/saída) são o principal componente usado por Java para lidar com leitura e gravação de dados
- Mídias de E/S comuns incluem
- Arquivo ( entrada | saída )
- rede ( entrada | saída )
- Teclado ( saída )
- Exibição ( saída )
- cenas a serem usadas
- Cópia de arquivo (Arquivo)
- Upload e download de arquivos
- Importação e exportação de Excel
- Transmissão de dados em programas de rede (ferramentas de chat)
Classificação
Visão geral
Quase todas as operações IO em Java requerem o uso do pacote java.io; os fluxos podem ser classificados da seguinte forma
- Dividido pela direção do fluxo (os processos de entrada e saída são geralmente considerados da perspectiva do programa)
- Fluxo de entrada (entrada)
- Saída
- De acordo com o tipo de processamento de fluxo
- Fluxo de bytes (byte): Byte é a unidade básica da capacidade de armazenamento do computador (Byte), 1B = 8b, ocupa 8 bits em binário
- Fluxo de caracteres (char): Caractere é o nome coletivo para texto ou símbolos
Nota: O fluxo de bytes pode ler qualquer tipo de arquivo, como arquivos do tipo binário (fotos, vídeos, áudios, arquivos compactados, etc.), enquanto o fluxo de caracteres é usado para ler arquivos do tipo texto.
- De acordo com a função do fluxo
- Fluxo do nó (interagir diretamente com fontes de entrada e saída)
- Processando streams (streams que agrupam outros streams: encapsulando streams)
Fluxo de bytes (InputStream && OutputStream)
Fluxos de bytes comumente usados em processos de desenvolvimento diários:
FileInputStream && FileOutputStream: comumente usado para implementar cópia/cópia de arquivo
BufferedInputStream && BufferedOutputStream: Para reduzir o número de vezes de IO e melhorar a eficiência de leitura
PrintStream: derivado de OutputStream, fluxo de saída de impressão de bytes padrão (princípio de implementação da estrutura de log)
ZipOutputStream && ZipInputStream: usado para compactação/descompactação de arquivos
Fluxo de caracteres (leitor e escritor)
Fluxos de caracteres comumente usados em processos diários de desenvolvimento:
FileReader&&FileWriter: usa FileInputStream && FileOutputStream
BufferedReader&&BufferedWriter: A função é a mesma que BufferedInputStream && BufferedOutputStream, ao mesmo tempo, BufferedReader fornece um método de leitura de texto linha por linha para facilitar o processamento de texto.
Extensão: sabemos que os fluxos de bytes podem ler qualquer arquivo, por que precisamos projetar um fluxo de caracteres?
- Para arquivos de caracteres, primeiro transfira-os como bytes -> depois converta-os em caracteres, o que consome mais tempo.
- Para arquivos de caracteres, se o texto for chinês, ele será facilmente distorcido.
Padrões de design
Uma variedade de padrões de design são usados em fluxos de E/S, incluindo os seguintes:
modo adaptador
O padrão Adapter permite que classes trabalhem juntas que de outra forma não funcionariam juntas devido a interfaces incompatíveis .
Para realizar a conversão mútua entre fluxo de caracteres e fluxo de bytes em Java IO, duas classes de adaptadores são projetadas.
InputStreamReader e OutputStreamWriter
InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
BufferedReader bufferedReader = new BufferedReader(isr);
Padrão de decorador
O padrão decorador pode anexar dinamicamente novas funcionalidades a objetos existentes sem alterar a funcionalidade dos objetos existentes. FilterInputStream, uma subclasse de InputStream, FilterOutputStream, uma subclasse de OutputStream, BufferedReader e FilterReader, subclasses de Reader, e BufferedWriter, FilterWriter e PrintWriter, subclasses de Writer, são todas classes decorativas abstratas. Funcionalidade aprimorada de objetos de subclasse.
prática
ZipOutputStream&&FileOutputStream&&FileInputStream implementa compactação de arquivo
/**
* 功能: 通过ZipOutputStream压缩文件,最后返回压缩包
* @param files
* @param fileName
* @return
*/
public File zipFiles(File[] files,String fileName) {
File zipFile = null;
FileOutputStream fosZipFile = null;
ZipOutputStream zosZipFile = null; //压缩文件输出流
try {
zipFile = downloadAttachmentService.createFile("", fileName); //创建一个空的文件目录
fosZipFile = new FileOutputStream(zipFile); //以文件流从内存中输出
zosZipFile = new ZipOutputStream(fosZipFile); //以压缩流从内存中输出
for (File file : files) {
FileInputStream fis = new FileInputStream(file); //对每个文件创建输入流,读取文件到内存
ZipEntry zipEntry = new ZipEntry(file.getName()); //ZipEntry用来创建压缩文件
zosZipFile.putNextEntry(zipEntry); //加入需要压缩的文件
byte[] bytes = new byte[1024];
int length;
while((length = fis.read(bytes)) >= 0) { //读取文件到内存
zosZipFile.write(bytes, 0, length); //文件写入压缩流
}
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally { //关闭流
try {
zosZipFile.close();
fosZipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return zipFile; //返回压缩包
}
/**
* @Title: createFile
* @Description: 创建下载目录文件
* @author Bierce
* @param rootPath
* @param filename
* @return
* @throws IOException
*/
public File createFile(String rootPath, String filename) throws IOException {
// Default root path
if (rootPath.isEmpty()) {
rootPath = "download-cache";
}
File fRoot = new File(rootPath);
if (!fRoot.exists() || !fRoot.isDirectory()) {
fRoot.mkdirs();
}
// job sub path
String uuid = UUID.randomUUID().toString();
String directoryJob = rootPath + File.separator + getClass().getSimpleName() + File.separator + uuid;//文件名称随机生成保证唯一
File dirJob = new File(directoryJob);
if (!dirJob.exists() || !dirJob.isDirectory()) {
dirJob.mkdirs();
}
String filePath = directoryJob + File.separator + filename;
File file = new File(filePath);
if (!file.exists()) {
file.createNewFile();
}
return file;
}
//-----------------扩展方法-文件名去重保证唯一-----------------
/**
* @Title: snFileName_noUIID
* @Description: 去除sn文件UUID以及解决sn文件名重复问题
* @author Bierce
* @return file
*/
public File snFileName_noUIID(String fileParentPath,String snFileName,File file){
//snFileName:完整文件名 sn-xx..UUID..xx.xlsx
//snFileName_delUIID: sn.xlsx
//snFileName_prefix: sn
//suffix:xlsx
//文件名:如sn.xlsx
String snFileName_delUIID = snFileName.substring(0,snFileName.length() - 42) + ".xlsx";//42是固定长度:UUID+.xlsx
String snFileName_prefix = snFileName.substring(0,snFileName.length() - 42);//文件前缀
String suffix = snFileName.substring(snFileName.lastIndexOf("."));//文件后缀:.xlsx
try {
file = new File(fileParentPath + snFileName_delUIID);//设置sn文件所在目录为计划交接文件目录下
int i = 1;
//对于同名SN文件情况重新命名
while(file.exists()) {//保证文件夹下不存在同名文件
String newFileName = snFileName_prefix + "(" + i + ")" + suffix;
String parentPath = file.getParent();
file = new File(parentPath + File.separator + newFileName);
i++;
}
file.createNewFile();//new File 只是创建了一个File对象,还需要调用createNewFile()方法才能实现文件的成功创建
} catch (Exception e) {
}
return file;
}