visão geral
As operações Java I/O referem-se a operações de entrada/saída de dados.
As classes de operação de E/S do Java estão no pacote java.io, divididas principalmente nas seguintes categorias:
- Interface de E/S baseada em operação de byte: InputStream e OutputStream
- Interface de E/S baseada na operação de caractere: Escritor e Leitor
- Interface de E/S baseada na operação do disco: Arquivo
1. Introdução às aulas principais
- Operações de E/S baseadas em byte, o núcleo é operar o byte array byte[], que pode operar qualquer tipo de fluxo de dados
- Operações de E/S baseadas em caracteres, o núcleo é operar a matriz de caracteres char[] e só pode operar dados de fluxo de tipo de caractere. Se forem dados de fluxo sem caracteres (como fotos, vídeos, etc.), vai ficar truncado
1. Fluxo de entrada de bytes
tipo | Função | ilustrar |
---|---|---|
ByteArrayInputStream | Use o buffer de memória como um InputStream | Conecte-o ao objeto FilterInputStream para armazenar o fluxo de bytes no arquivo |
FileInputStream | ler informações de um arquivo | Converta o objeto de arquivo Arquivo em um fluxo de entrada para ler os dados no arquivo |
FilterInputStream | Uma classe abstrata que atua como uma interface decoradora que fornece funcionalidade útil para outras classes InputStream | |
BufferedInputStream | Fornece operações de buffer para melhorar o desempenho de IO; adiciona função de buffer para fluxos de entrada de entrada | Subclasse FilterInputStream |
DataInputStream | Usado em conjunto com DataOutputStream para ler tipos de dados básicos de fluxos de maneira portada; inclui todas as interfaces para leitura de tipos de dados básicos | Subclasse FilterInputStream |
2. Fluxo de saída de bytes
tipo | Função | ilustrar |
---|---|---|
ByteArrayOutputStream | Crie um buffer na memória. Todos os dados enviados para o stream são colocados neste buffer | É conveniente converter o fluxo de entrada em uma matriz de bytes |
FileOutputStream | para gravar informações em um arquivo | |
FilterOutputStream | Classe abstrata, interface que atua como decorador, fornecendo funcionalidade útil para outros OutputStreams | |
BufferedOutputStream | Fornece operações de buffer para melhorar o desempenho de E/S; adicione a função de buffer ao fluxo de saída de entrada, você pode chamar flush() para limpar o buffer | Subclasse FilterOutputStream |
DataOutputStream | Usado em conjunto com DataInputStream, os tipos de dados básicos podem ser gravados no fluxo de maneira transplantada; inclui todas as interfaces para gravação de tipos de dados básicos | Subclasse FilterOutputStream |
3. Fluxo de entrada de caracteres
tipo | Função | ilustrar |
---|---|---|
InputStreamReader | Converter fluxo de entrada de bytes InputStream em fluxo de entrada de caracteres | |
Leitor de arquivos | Converte o objeto de arquivo Arquivo em um fluxo de entrada de caractere | Subclasse de InputStreamReader |
BufferedReader | Fornece função de buffer para melhorar o desempenho da operação do leitor de fluxo de entrada de caracteres | |
StringReader | Converter uma string em uma operação de fluxo de caracteres |
4. Fluxo de saída de caracteres
tipo | Função | ilustrar |
---|---|---|
OutputStreamWriter | Converter fluxo de saída de bytes OutputStream para fluxo de saída de caracteres | |
FileWriter | Converte o objeto de arquivo Arquivo em um fluxo de saída de caractere | Subclasse de OutputStreamWriter |
BufferedWriter | Forneça função de buffer para melhorar o desempenho da operação do fluxo de saída de caracteres Writer | |
StringWriter | Converter uma string em uma operação de fluxo de caracteres |
2. Introdução às principais operações
1. Feche o fluxo
Todos os fluxos de dados precisam chamar o método close para fechar após a conclusão da operação. Em 1.7 e posterior, é recomendável usar a try-with-resources
instrução para usar o fluxo, o que pode evitar chamar o método close () explicitamente, reduzir algum código repetitivo, e chame close automaticamente após a conclusão da operação.
try-with-resources
A instrução pode fechar automaticamente todos java.io.Closeable
os objetos de subclasse que implementam a interface.
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
bos.write(content.getBytes());
bos.flush();
}
2. Atualize o cache
O método flush() é usado para forçar o objeto OutputStream a escrever os dados armazenados temporariamente no buffer interno imediatamente (em geral, não é necessário chamar este método manualmente, e os dados reais serão executados automaticamente após o buffer interno ser full. A operação de gravação também chamará automaticamente o método flush() ao chamar o método close())
3. Fluxo de serialização e fluxo de desserialização
A serialização de um objeto é converter o objeto em uma sequência de bytes e vice-versa é chamada de desserialização, ObjectOutputStream é um fluxo de serialização e ObjectInputStream é um fluxo de desserialização.
O objeto a ser operado deve implementar a interface de serialização Serializable. Caso você não queira que um determinado campo seja serializado, você pode usar transiente para modificar o campo para que o campo não seja serializado, ou você pode serializá-lo manualmente reescrevendo e métodos writeObjectOverride()
.readObjectOverride()
As variáveis estáticas também não podem ser serializadas, porque todos os objetos compartilham o mesmo valor de variável estática
1) fluxo de serialização ObjectOutputStream
O método principal é writeObject, que armazena a classe do objeto, a assinatura da classe e os valores de todos os campos não estáticos e não transitórios nesta classe e em suas classes pai
public final void writeObject(Object obj) throws IOException {
if (enableOverride) {
writeObjectOverride(obj);
return;
}
try {
writeObject0(obj, false);
} catch (IOException ex) {
if (depth == 0) {
writeFatalException(ex);
}
throw ex;
}
}
2) Fluxo de desserialização ObjectInputStream
O método principal é readObject, que lê a classe do objeto, a assinatura da classe e os valores de todos os campos não estáticos e não transitórios nesta classe e suas superclasses
public final Object readObject()
throws IOException, ClassNotFoundException
{
if (enableOverride) {
return readObjectOverride();
}
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
try {
Object obj = readObject0(false);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
throw ex;
}
if (depth == 0) {
vlist.doCallbacks();
}
return obj;
} finally {
passHandle = outerHandle;
if (closed && depth == 0) {
clear();
}
}
}
3. Exemplo de código
import org.springframework.util.StopWatch;
import java.io.*;
public class FileUtilTest {
/**
* 复制文件
*/
public static void copyFile(String fromFileName, String toFileName) throws Exception {
File fromFile = new File(fromFileName);
File toFile = new File(toFileName);
StopWatch watch = new StopWatch("fileTest");
watch.start("copy");
if (!fromFile.exists()) {
System.out.println("源文件不存在");
System.exit(1);
}
if (!toFile.getParentFile().exists()) {
toFile.getParentFile().mkdirs();
}
try (InputStream is = new FileInputStream(fromFile);
OutputStream os = new FileOutputStream(toFile)) {
int temp = 0;
byte[] data = new byte[4096];
while ((temp = is.read(data)) != -1) {
os.write(data, 0, temp);
}
watch.stop();
System.out.println(watch.prettyPrint());
}
}
/**
* 通过字符流将字符串写入到文件中
*/
public static void write(String fileName, String content) throws IOException {
File file = new File(fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try (Writer out = new FileWriter(file)) {
out.write(content);
out.flush();
}
}
/**
* 通过字节流将字符串写入到文件中,增加缓冲区功能
*/
public static void writeBuffer(String fileName, String content) throws IOException {
File file = new File(fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
bos.write(content.getBytes());
bos.flush();
}
}
/**
* 通过字符流将字符串写入到文件中,增加缓冲区功能
*/
public static void writeBufferedWriter(String fileName, String content) {
File file = new File(fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(content);
bw.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过字符流,从文件中读取字符串内容
*/
public static void readChar(String fileName) {
File file = new File(fileName);
if (!file.exists()) {
return;
}
try (Reader in = new FileReader(file)) {
char[] data = new char[4096];
int len;
StringBuilder sb = new StringBuilder();
while ((len = in.read(data)) != -1) {
sb.append(new String(data, 0, len));
}
in.close();
System.out.println(sb);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过字节流,从文件中读取字符串内容
*/
public static void readByte(String fileName) throws IOException {
File file = new File(fileName);
if (!file.exists()) {
return;
}
try (InputStream in = new FileInputStream(file)) {
byte[] data = new byte[4096];
int len;
StringBuilder sb = new StringBuilder();
while ((len = in.read(data)) != -1) {
sb.append(new String(data, 0, len));
}
System.out.println(sb);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过字符流,从文件中读取字符串内容,增加缓冲区功能
*/
public static void readBufferReader(String fileName) throws Exception {
File file = new File(fileName);
if (!file.exists()) {
return;
}
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
}
/**
* 通过字节流,从文件中读取字符串内容,增加缓冲区功能
*/
public static void readBuffer(String fileName) throws Exception {
File file = new File(fileName);
if (!file.exists()) {
return;
}
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
int len;
byte[] data = new byte[4096];
while ((len = bis.read(data)) != -1) {
System.out.println(new String(data, 0, len));
}
}
}
/**
* 将文件内容转换成字节数组
*/
public static byte[] file2OutStream(String fileName) throws Exception {
File file = new File(fileName);
if (!file.exists()) {
return null;
}
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
int len;
byte[] data = new byte[4096];
while ((len = bis.read(data)) != -1) {
bos.write(data, 0, len);
}
return bos.toByteArray();
}
}
/**
* 将Java对象序列化存储在到文件中
*/
public static void objWrite(String fileName) {
File file = new File(fileName);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
oos.writeObject("Hello ,World");
oos.writeBoolean(false);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 从序列化文件中反序列化出Java对象
*/
public static void objRead(String fileName) {
File file = new File(fileName);
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
Object o = ois.readObject();
System.out.println(o.getClass());
System.out.println("o = " + o);
System.out.println("ois.readBoolean() = " + ois.readBoolean());
} catch (Exception e) {
e.printStackTrace();
}
}
}