Aprendizagem Java 4-4_IO

Java IO

  1. Conceitos básicos: sistema de entrada / saída Java

  2. Entrada e saída: a leitura de dados de fora é uma entrada (InputStream / Reader), e o programa grava os dados externamente usando a saída

  3. mapeamento da mente
    Insira a descrição da imagem aqui

  4. Fluxo de bytes e fluxo de caracteres:

    1. O fluxo de bytes é usado principalmente para processar bytes ou objetos binários.
    2. O fluxo de caracteres (um caractere ocupa dois bytes) é projetado para processar caracteres ou strings.
    3. A unidade de processamento do fluxo de caracteres é um caractere Unicode de 2 bytes , que opera caracteres, matrizes de caracteres ou strings, respectivamente, enquanto a unidade de processamento do fluxo de bytes é de 1 byte , que opera bytes e matrizes de bytes. Portanto, o fluxo de caracteres é formado pela máquina virtual Java convertendo bytes em caracteres Unicode de 2 bytes, portanto, tem melhor suporte para vários idiomas! Se for um arquivo de áudio, imagem ou música, é melhor usar o fluxo de bytes, se estiver relacionado ao chinês (texto), é melhor usar o fluxo de caracteres
  5. Nota: Ao fechar o fluxo, o fluxo da embalagem externa deve ser fechado primeiro, ou seja, "feche primeiro quando for aberto depois"

    FileOutputStream fos = new FileOutputStream("f:\\qs");
    OutputStreamWriter osw = newOutputStreamWriter(fos);
    BufferedWriter bw = newBufferedWriter(osw);
    bw.write("hello qs!");
    bw.close();
    osw.close();
    fos.close();
    

1. Parte de streaming

O mapa mental acima mostra a relação geral das várias correntes, e algumas explicações específicas são fornecidas abaixo

1.1 Fluxo de arquivos

  • FileInputStream / FileOutputStrean file byte stream, leia arquivos através do modo byte, adequado para todos os tipos de arquivos, mas não pode lidar bem com caracteres Unicode
  • FileReader / FileWriter file stream de caracteres, usado para codificação Unicode de arquivos de texto

1.2 Fluxo com buffer

O fluxo de buffer Java em si não tem as funções de leitura e gravação do fluxo de IO, mas a função de buffer é adicionada a outros fluxos (fluxos de nó ou outros fluxos de processamento) para melhorar a eficiência, assim como empacotar outros fluxos, então O fluxo de buffer é um fluxo de processamento (fluxo de empacotamento), o tamanho da área de buffer é 8192 bytes por padrão, você também pode usar outros métodos de construção para especificar o tamanho você mesmo

  • Os dois fluxos BufferedInputStream / BufferedOutputStream são fluxos de bytes em buffer.A matriz de buffer interno é usada para melhorar a eficiência de operação do fluxo.
  • BufferedReader / BufferedWriter armazena em buffer o fluxo de caracteres, aumenta o mecanismo de cache, melhora a eficiência de leitura e gravação de arquivos de texto e fornece o método readLine () para facilitar a leitura por linha. Observe que depois de escrever uma linha, use o método newLine () para quebrar .

1.3 Fluxo de dados

Usado para decorar outros fluxos de entrada, o fluxo de entrada de dados permite que os aplicativos leiam tipos de dados Java básicos do fluxo de entrada subjacente de uma maneira independente da máquina.

  • DataInputStream / DataOutputStream
DataInputStream dis = new DataInputStream(InputStream in);//构造函数

//write方法
writeBytes(String str);
writeChars(String str);
writeUTF(String str);//写入数据的同时也写入长度

//特殊的读方法
ReadUTF();//知道长度才能读
readBoolean();
readByte();
readChar();
readDouble();
readFloat();
readFully(byte[] dst);
readFully(byte[] dst, int offset, int byteCount);
readInt();
readLine();
readLong();
readShort();
readUTF(DataInput in);
readUTF();
readUnsignedByte();
readUnsignedShort();
skipBytes(int count);
//以上根据名字可以知道函数作用

Como os caracteres em java são codificados em Unicode e são bytes duplos, writeByte () apenas grava o conteúdo de byte inferior de cada caractere no dispositivo de destino. E writeChars () grava o conteúdo de dois bytes de cada caractere da string no dispositivo de destino; writeUTF () grava a string no comprimento de byte codificado em UTF para o dispositivo de destino e, em seguida, A codificação UTF de cada byte.

DataInputStream fornece apenas um método ReadUTF () para retornar uma string. Isso ocorre porque é necessário ler uma string em um fluxo contínuo de bytes. Se não houver uma marca especial como o final de uma string e o comprimento da string não for conhecido, é impossível saber onde a string é lida. O fim. Apenas o método writeUTF () na classe DataOutputStream
grava o comprimento da string no dispositivo de destino, para que também possa ler e gravar com precisão a string.

1.4 Fluxo de reserva

Todos os dados em JAVA IO são lidos em ordem, ou seja, para um fluxo de entrada, eles são lidos em ordem do início ao fim. Se algum conteúdo indesejado no fluxo de entrada for lido em , Você só pode processar esse conteúdo indesejado por meio do programa. Para resolver esse problema de processamento, um fluxo de entrada de fallback (PushbackInputStream, PushbackReader) é fornecido em JAVA, que pode retornar alguns dados que foram lidos. Retorne ao buffer do fluxo de entrada.

  • PushbackInputStream / PushbackOutputStream byte back stream

    public PushbackInputStream(InputStream in);//构造方法 将输入流放入到回退流之中。
    public int read() throws IOException;//读取数据。
    public int read(byte[] b,int off,int len) throws IOException;//读取指定范围的数据。
    public void unread(int b) throws IOException;//回退一个数据到缓冲区前面。
    public void unread(byte[] b) throws IOException//回退一组数据到缓冲区前面。
    public void unread(byte[] b,int off,int len) throws IOException//回退指定范围的一组数据到缓冲区前面。
    

    O fluxo de fallback corresponde à operação do fluxo de entrada

  • Back stream de caracteres PushbackReader / PushbackWriter

1.5 Fluxo de objeto

  • ObjectInputStream serializa os dados originais do objeto
  • ObjectOutputStream desserializa dados serializados

Apenas objetos que suportam interfaces java.io.Serializable ou java.io.Externalizable podem ser lidos no fluxo.

O método readObject () é usado para ler objetos do fluxo. A segurança de Java deve ser usada para obter o tipo desejado. Em Java, strings e arrays são tratados como objetos quando serializados e são tomados durante a leitura. Converta para o tipo desejado.

O método readObject () é responsável por ler e usar o método writeObject () correspondente para transmitir os dados gravados para restaurar o estado do objeto de sua classe específica. Este método não precisa se preocupar com o estado da superclasse ou subclasse. A restauração do estado é ler os campos e objetos do ObjectInputStream. O tipo de dados original pode ser lido pela interface DataInput.

1.6 Fluxo do pipeline

PipedOutputStream / ** PipedInputStream ** é um fluxo de pipeline de bytes.

A função é permitir que vários threads se comuniquem entre os threads por meio de tubos. Ao usar a comunicação por pipe, PipedOutputStream e PipedInputStream devem ser usados ​​juntos.

Processo de uso: Grave dados em PipedOutputStream no thread A e os dados serão enviados automaticamente para PipedInputStream correspondente a PipedOutputStream e, em seguida, armazenados no buffer de PipedInputStream; neste momento, o thread B lê os dados em PipedInputStream. Pode ser realizada comunicação thread A e thread B.

Nota: Não use PipeInpuStream e PipeOutputStream ao mesmo tempo em um thread, isso causará um deadlock

PipedOutputStream in = new PipedOutputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);//将“管道输入流”和“管道输出流”关联起来,等价于out.connect(in),只需要调用一次。

1.7 Fluxo de sequência

  • SequenceInputStream / SequenceOutputStream fluxo de sequência de bytes, primeiro leia todos os bytes no primeiro InputStream e, em seguida, leia todos os bytes no segundo InputStream. É por isso que é chamado de SequenceInputStream, porque as instâncias de InputStream são lidas sequencialmente.

Dois métodos de inicialização

SequenceInputStream sis = new SequenceInputStream(InputStream s1, InputStream s2);//通过两个参数初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2)

SequenceInputStream(Enumeration<? extends InputStream> e);//通过枚举对象来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数

//组合多个流
InputStream input1 = new FileInputStream("1.txt");
InputStream input2 = new FileInputStream("2.txt");
InputStream input3 = new FileInputStream("3.txt");

Vector<InputStream> streams = new Vector<>();
streams.add(input1);
streams.add(input2);
streams.add(input3);

//利用 Vector 对象的 elements() 方法返回 enumeration 对象
SequenceInputStream sequenceInputStream = new SequenceInputStream(streams.elements());

1.8 Array Stream

Os dados são gravados na matriz de bytes, o buffer aumentará automaticamente quando os dados forem gravados, é inválido fechar o fluxo, não haverá exceções quando o método for chamado após o fechamento do fluxo

  • ByteArrayInputStream / ** ByteArrayOutputStream ** Fluxo de matriz de bytes, cria um buffer de matriz de bytes na memória e salva os dados lidos do fluxo de entrada no buffer de matriz de bytes.

    write(int b);//写入指定的字节到此字节输出流中
    write(byte b[], int off, int len);//从指定数组的下标off开始写入len个字节到该输出流中
    writeTo(OutputStream out);//将此字节输出流的内容写入到指定的输出流中
    reset();//重置此字节输出流,废弃此前存储的数据
    toByteArray();//对输出流的数据进行检索
    
  • Fluxo de matriz de caracteres CharArrayReader / CharArrayWriter , a operação está em caracteres

    write(int oneChar);//的作用将int类型的oneChar换成char类型,然后写入到CharArrayWriter中。
    write(char[] buffer, int offset, int len);//是将字符数组buffer写入到输出流中,offset是从buffer中读取数据的起始偏移位置,len是读取的长度。
    write(String str, int offset, int count);//是将字符串str写入到输出流中,offset是从str中读取数据的起始位置,count是读取的长度。
    append(char c);//的作用将char类型的c写入到CharArrayWriter中,然后返回CharArrayWriter对象。注意:append(char c)与write(int c)都是将单个字符写入到CharArrayWriter中。它们的区别是,append(char c)会返回CharArrayWriter对象,但是write(int c)返回void。
    ppend(CharSequence csq, int start, int end);//的作用将csq从start开始(包括)到end结束(不包括)的数据,写入到CharArrayWriter中。注意:该函数返回CharArrayWriter对象!
    append(CharSequence csq);//的作用将csq写入到CharArrayWriter中。注意:该函数返回CharArrayWriter对象!
    writeTo(OutputStream out);//将该“字符数组输出流”的数据全部写入到“输出流out”中。
    

1.9 Fluxo de conversão

InputStreamReader / OutputStreamWriter

O fluxo Java IO fornece dois fluxos de conversão para converter fluxos de bytes em fluxos de caracteres.

InputStreamReader é usado para converter fluxos de entrada de bytes em fluxos de entrada de caracteres e OutputStreamWriter é usado para converter fluxos de saída de bytes em fluxos de saída de caracteres. O uso do fluxo de conversão pode evitar caracteres distorcidos até certo ponto, e você também pode especificar o conjunto de caracteres usado para entrada e saída,
OutputStreamWriter, para converter o fluxo de saída de bytes em um fluxo de saída de caracteres. Crie um OutputStreamWriter que use o conjunto de caracteres especificado. Se você não especificar um conjunto de caracteres, use o conjunto de caracteres padrão para criar um OutputStreamWriter. Você não precisa fechar o OutputStream após a conversão

//输出流中的方法
flsh();//刷新该流的缓冲
close();//关闭此流,关闭前需要刷新
getEncoding();//获取此流使用的字符编码的名称。
write(char[] ,int offset ,int length);//写入字符数组的某一部分
write(String ,int offset ,int length);//写入字符串的某一部分
write(String );//写入单个字符

Em segundo lugar, a parte sem streaming

2.1 SerializablePermission

Usado para permissões serializáveis. A execução serializável contém um nome (também chamado de "nome de destino"), mas nenhuma lista de operações.

2.2 Arquivo

As classes de arquivo Java representam nomes de arquivo e nomes de caminho de diretório de maneira abstrata. Esta classe é usada principalmente para criação de arquivos e diretórios, pesquisa e exclusão de arquivos.

Número de série Descrição do método
1 public String getName () retorna o nome do arquivo ou diretório representado por este caminho abstrato.
2 public String getParent () retorna a string do nome do caminho do nome do caminho pai desse nome de caminho abstrato ou, se o nome do caminho não especificar um diretório pai, ele retorna null.
3 public File getParentFile () retorna o nome do caminho abstrato do nome do caminho pai desse nome de caminho abstrato ou, se o nome do caminho não especificar um diretório pai, ele retorna null.
4 public String getPath () converte este nome de caminho abstrato em uma string de nome de caminho.
5 public boolean isAbsolute () testa se este nome de caminho abstrato é um nome de caminho absoluto.
6 public String getAbsolutePath () retorna a string do nome do caminho absoluto do nome do caminho abstrato.
7 public boolean canRead () testa se o aplicativo pode ler o arquivo representado por este nome de caminho abstrato.
8 public boolean canWrite () testa se o aplicativo pode modificar o arquivo representado por este nome de caminho abstrato.
9 public boolean exists () testa se o arquivo ou diretório representado por este nome de caminho abstrato existe.
10 public boolean isDirectory () testa se o arquivo representado por este caminho abstrato é um diretório.
11 public boolean isFile () testa se o arquivo indicado por este caminho abstrato é um arquivo padrão.
12 public long lastModified () retorna a hora em que o arquivo representado por este caminho abstrato foi modificado pela última vez.
13 public long length () retorna o comprimento do arquivo representado por este caminho abstrato.
14 public boolean createNewFile () throws IOException Se e somente se não houver nenhum arquivo com o nome especificado por este nome de caminho abstrato, crie atomicamente um novo arquivo vazio especificado por este nome de caminho abstrato.
15 public boolean delete () exclui o arquivo ou diretório indicado por este nome de caminho abstrato.
16 public void deleteOnExit () solicita a exclusão do arquivo ou diretório indicado por este nome de caminho abstrato quando a máquina virtual é encerrada.
17 public String [] list () retorna uma matriz de strings que consiste nos nomes de arquivos e diretórios no diretório representado por este caminho abstrato.
18 public String [] list (filtro FilenameFilter) retorna uma matriz de string que consiste nos nomes dos arquivos e diretórios contidos no diretório.Este diretório é representado por um nome de caminho abstrato que satisfaz o filtro especificado.
19 public File [] listFiles () retorna uma matriz de nomes de caminho abstratos que representam os arquivos no diretório representado por este nome de caminho abstrato.
20 public File [] listFiles (filtro FileFilter) retorna uma matriz de nomes de caminho abstratos que representam os arquivos e diretórios no diretório representado por esse nome de caminho abstrato, e esses nomes de caminho satisfazem um filtro específico.
21 public boolean mkdir () cria o diretório especificado por este nome de caminho abstrato.
22 public boolean mkdirs () cria o diretório especificado por este nome de caminho abstrato, incluindo o diretório pai que é necessário, mas não existe.
23 public boolean renameTo (File dest) renomeia o arquivo representado por este caminho abstrato.
24 public boolean setLastModified (long time) define a hora da última modificação do arquivo ou diretório especificado por este nome de caminho abstrato.
25 public boolean setReadOnly () marca o arquivo ou diretório especificado por este nome de caminho abstrato para que ele só possa ser lido.
26 public static File createTempFile (String prefix, String sufixo, File directory) lança IOException Cria um novo arquivo vazio no diretório especificado e usa o prefixo e a string de sufixo fornecidos para gerar seu nome.
27 public static File createTempFile (String prefix, String suffix) lança IOException Cria um arquivo vazio no diretório de arquivo temporário padrão e usa o prefixo e sufixo fornecidos para gerar seu nome.
28 public int compareTo (nome do caminho do arquivo) compara dois nomes de caminho abstratos em ordem alfabética.
29 public int compareTo (Object o) Compare nomes de caminhos abstratos com o objeto fornecido em ordem alfabética.
30 public boolean equals (Object obj) testa se este caminho abstrato é igual ao objeto fornecido.
31 public String toString () retorna a string do nome do caminho desse nome de caminho abstrato.

2.3 RandomAccessFile

RandomAccessFile implementa a maioria dos métodos de fluxos de entrada e saída de arquivo, mas na implementação subjacente, ele implementa as interfaces DataInput e DataOutput, não FileInputStream e FileOutputStream. RandomAccessFile usa muitos métodos nativos para implementar operações de arquivo e muitos métodos nativos se sobrepõem ao fluxo de entrada

2.4 FileDescriptor

FileDescriptor pode ser usado para representar arquivos abertos, sockets abertos, etc.

当FileDescriptor表示文件来说,当FIleDescriptor表示某文件时,我们可以通俗的将FIleDescriptor看成该文件。但是,我们不能直接通过FIleDescriptor对该文件进行操作;若需要通过FIleDescriptor对该文件进行操作,则需要创建FileDescriptor对应的FileOutputStream,再对文件进行操作。

三、补充

  1. 在文件中,换行为 \r\n

  2. 路径分隔符, linux文件路径分隔符为 / ,windows的文件路径分隔符为 \ 。System.getProperty(“file.separator”)

  3. 字节流和字符流的区别:

    1. 读写单位不同:字节流以字节(8 bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
    2. 处理对象不同:字节流能处理所有类型的数据(如图片、avi 等),而字符流只能处理字符类型的数据。
    3. 字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用 colse() 方法时,信息已经输出了,而字符流只有在调用 close() 方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用 flush() 方法。
  4. 节点流和处理流:Java io 分类方式有很多,根据是否直接处理数据,Java io又分为节点流和处理流,节点流是真正直接处理数据的;处理流是装饰加工节点流的。

  5. 什么叫对象序列化,什么是反序列化,实现对象序列化需要做哪些工作?

    • 对象序列化:将对象以二进制的形式保存在硬盘上;
    • 反序列化:将二进制的文件转化为对象读取;
    • 实现 serializable 接口可以实现对象序列化,其中没有需要实现的方法,implements Serializable 只是为了标注该对象是可被序列化的
  6. 什么是 Filter 流有哪些?

    FilterStream 是一种 IO 流,主要作用是用来对存在的流增加一些额外的功能,像给目标文件增加源文件中不存在的行数,或者增加拷贝的性能等。在 java.io 包中主要由 4 个可用的 filter Stream。两个字节 filter stream,两个字符 filter stream。FilterStream 是抽象类不能被是咯话,其子类有:DataInputStream、BufferedInputStream、PushbackInputStream

四、NIO

NIO和传统IO(一下简称IO)之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

Vários fluxos de IO estão bloqueados . Isso significa que quando um thread chama read () ou write (), o thread é bloqueado até que alguns dados sejam lidos ou os dados sejam completamente gravados. O segmento não pode fazer nada durante este período. O modo sem bloqueio do NIO permite que um thread envie uma solicitação para ler dados de um canal, mas ele só pode obter os dados disponíveis no momento. Se não houver dados disponíveis no momento, ele não obterá nada. Em vez de manter o thread bloqueado, ele pode continuar a fazer outras coisas até que os dados se tornem legíveis. O mesmo é verdadeiro para gravações sem bloqueio. Um thread solicita a gravação de alguns dados em um determinado canal, mas não precisa esperar que ele seja completamente escrito, este thread pode fazer outras coisas ao mesmo tempo. Threads geralmente usam o tempo ocioso de IO sem bloqueio para executar operações de IO em outros canais, portanto, um único thread agora pode gerenciar vários canais de entrada e saída.

Acho que você gosta

Origin blog.csdn.net/Sky_Coolssy/article/details/108855718
Recomendado
Clasificación