O conceito de "stream" origina-se do conceito de pipe no UNIX. No UNIX, um pipe é um fluxo de bytes ininterrupto usado para implementar a comunicação entre programas ou processos, ou para ler e gravar dispositivos periféricos, arquivos externos, etc. Ele protege os detalhes do processamento de dados no dispositivo de E/S real. Um fluxo deve ter uma origem e um destino, que podem ser determinadas áreas da memória do computador, arquivos de disco ou até mesmo uma URL na Internet. A direção do fluxo é importante De acordo com a direção do fluxo, o fluxo pode ser dividido em duas categorias: fluxo de entrada e fluxo de saída. Na verdade, entrada/saída é para memória. Na verdade, a origem e o destino do fluxo podem ser simplesmente considerados produtores e consumidores de bytes. Para o fluxo de entrada, você não precisa se preocupar com sua origem, desde que simplesmente leia os dados do fluxo. para o fluxo de entrada O fluxo de saída também pode não ter conhecimento de seu destino e simplesmente gravar dados no fluxo.
a. Stream: Um conjunto de sequências de dados ordenadas.
b Fluxo de bytes: A menor unidade de dados no fluxo de dados são os bytes.
c. Fluxo de caracteres: A menor unidade de dados no fluxo de dados é um caractere.
1. As classes do pacote java.io correspondem a dois tipos de streams
Um tipo de fluxo lê ou grava diretamente de um local especificado (como um arquivo de disco ou área de memória). Esse tipo de fluxo é chamado de fluxo de nó e outros fluxos são chamados de fluxos de filtro (fluxos de empacotamento).
Filtragem de fluxos: alguns fluxos podem receber bytes de arquivos e de outros lugares, e outros fluxos podem combinar bytes em tipos de dados mais úteis. Um construtor que passa um fluxo existente para outro fluxo e combina os dois fluxos. O fluxo combinado é chamado de fluxo filtrado. O fluxo de entrada do filtro geralmente usa outros fluxos de entrada como fonte de entrada. Após a filtragem ou processamento, ele é fornecido ao usuário na forma de um novo fluxo de entrada. Raramente usamos uma única classe para criar um objeto de fluxo, mas em vez disso fornecemos a funcionalidade desejada sobrepondo vários objetos (ou seja, o padrão de design do decorador).
Os fluxos de entrada e saída comumente usados em Java são, na verdade, herdados de quatro classes abstratas, que são:
Baseado em InputStream de byte único, classe OutputStream (E/S orientada a bytes)
Classes de leitor e gravador baseadas em unidades de código Unicode de byte duplo (E/S orientada a caracteres)
Depois que o fluxo de entrada for aberto, o programa poderá ler dados serialmente do fluxo de entrada. O processo de leitura/gravação de dados do fluxo de entrada é geralmente o seguinte: abrir um canal de fluxo -> ler/gravar informações -> fechar o canal de fluxo.
Na plataforma Java, existem duas maneiras de obter o tipo de codificação de caracteres da plataforma local:
(a) System.getProperty("arquivo.encoding");
(b) Conjunto de caracteres cs=Charset.defaultCharset();
Todos os fluxos de entrada e fluxos de saída podem ser divididos em fluxos de bytes (entrada, saída) e fluxos de caracteres (entrada, saída). Aqueles que processam bytes são principalmente séries (OutputStream/InputStream), e aqueles que processam caracteres são principalmente (Reader/Write). ) série
2. Fluxos de entrada orientados a bytes (série InputStream), essas classes podem ser conectadas a objetos FileInputStream para fornecer interfaces úteis:
ByteArrayInputStream: Use um buffer na memória como um InputStream
StringBufferInputStream (obsoleto em java1.1): use um objeto String como um InputStream e a implementação subjacente usa StringBuffer
FileInputStream: Use um arquivo como InputStream para implementar a operação de leitura de arquivo (nome do arquivo, arquivo, objeto FileDescriptor)
PipedInputStream: implementa o conceito de pipe, usado principalmente em threads (como fonte de dados em múltiplos processos)
SequenceInputStream: Combine vários InputStreams em um InputStream
Fluxos de saída orientados a bytes (série OutputStream) podem ser conectados a objetos FilterOutputStream para fornecer interfaces úteis:
ByteArrayOutputStream: crie um buffer na memória, armazene informações em um buffer na memória e inicialize o tamanho do buffer (opcional)
FileOutputStream: armazena informações em um arquivo (nome do arquivo, arquivo, FileDescriptor)
PipedOutputStream: implementa o conceito de pipe, usado principalmente em threads (especifica o destino dos dados para multi-threads)
3. A série correspondente (leitor/gravador) :
Leitor: Correspondente a InputStream, adaptador InputStreamReader
Writer: corresponde a OutputStream e o adaptador é OutputStreamWriter
FileReader: corresponde a FileOutputStream
FileWriter: corresponde a FileOurputStream
StringReader: Nenhuma classe correspondente
StringWriter: corresponde a ByteArrayInputStream
CharArrayReader: corresponde a ByteArrayOutputStream
CharArrayWriter: corresponde a ByteArrayOutputStream
PipedReader: corresponde a PipedInputStream
PipedWriter: corresponde a PipedOutputStream
4. Conversão entre dois fluxos irrestritos ( usando classe de adaptador)
InputStreamReader e OutputStreamReader: convertem um fluxo orientado a bytes em um fluxo orientado a caracteres.
InputStreamReader é uma ponte de um fluxo de bytes para um fluxo de caracteres: ele lê bytes usando um conjunto de caracteres especificado e os decodifica em caracteres. O conjunto de caracteres usado pode ser especificado por nome ou fornecido explicitamente, ou pode aceitar o conjunto de caracteres padrão da plataforma.
OutputStreamWriter é uma ponte do fluxo de caracteres para o fluxo de bytes: os caracteres a serem gravados no fluxo podem ser codificados em bytes usando o conjunto de caracteres especificado. O conjunto de caracteres usado pode ser especificado por nome ou fornecido explicitamente, caso contrário, o conjunto de caracteres padrão da plataforma será aceito
5. Leia os dados de InputStream por meio de FilterInputStream :
DataInputStream: lê dados do tipo básico (int, char, long, etc.) do fluxo.
BufferedInputStream: Use um buffer para evitar ter que executar uma operação de leitura real toda vez
LineNumberInputStream: registrará o número de linhas no fluxo de entrada e, em seguida, chamará getLineNumber() e setLineNumber(int)
PushbackInputStream: Raramente usado, geralmente usado para desenvolvimento de compilador
Escreva em OutputStream por meio de FilterOutputStream:
DataIOutputStream: dados do tipo básico (int, char, long, etc.) podem ser enviados para o fluxo de acordo com o método de transplante.
BufferedOutputStream: Use um buffer para evitar a gravação real toda vez que você enviar dados
PrintStream: produz saída formatada, onde DataOutputStream lida com armazenamento de dados e PrintStream lida com exibição
6. Altere o comportamento do stream
Embora BufferedOutputStream seja uma subclasse de FilterOutputStream, BufferedWriter não é uma subclasse de FilterWriter (FilterWriter é uma classe abstrata e não possui subclasses)
Não há classe correspondente para DataInputStream. Use DataInputStream, a menos que você use BufferedReader quando quiser usar readLine()
BufferedReader: corresponde a BufferedInputStream
LineNumberReader: corresponde a LineNumberInputStream
PushBackReader: corresponde a PushbackInputStream
BufferedWrite: corresponde a BufferedOutStream
PrintWrite: corresponde a PrintStream
7. Classe autoindependente: RandomAccessFile
Esta classe é adequada para arquivos compostos por registros de tamanho conhecido. Além de implementar as interfaces DataInput e DataOutput (DataInputStream e DataOutputStream também implementam essas duas interfaces), RandomAccessFile é uma classe completamente independente e possui outros tipos de E/S inerentemente. comportamentos diferentes, podem avançar e retroceder dentro de um arquivo e são derivados diretamente de Object.
As operações de leitura e gravação em arquivos podem ser concluídas por meio do objeto RandomAccessFile.
Ao gerar um objeto, você pode especificar a natureza do arquivo a ser aberto: r, somente leitura w, somente gravação rw pode ler e escrever;
Você pode ir diretamente para o local especificado no arquivo
A maioria (mas não todas) das funcionalidades do RandomAccessFile foram substituídas por arquivos de mapeamento de armazenamento nio