Respostas:
Um fluxo representa uma sequência de objetos (geralmente bytes, mas não necessariamente), que podem ser acessados em ordem sequencial. Operações típicas em um fluxo:
Um fluxo específico pode suportar leitura (nesse caso, é um "fluxo de entrada"), gravação ("fluxo de saída") ou ambos. Nem todos os fluxos são procuráveis.
O retrocesso é bastante raro, mas você sempre pode adicioná-lo a um fluxo envolvendo o fluxo de entrada real em outro fluxo de entrada que contém um buffer interno. As leituras são provenientes do buffer e, se você empurrar para trás, os dados são colocados no buffer. Se não houver nada no buffer, o fluxo de retorno lerá do fluxo real. Este é um exemplo simples de um "adaptador de fluxo": fica no "final" de um fluxo de entrada, é um fluxo de entrada propriamente dito e faz algo extra que o fluxo original não fez.
Stream é uma abstração útil porque pode descrever arquivos (que são realmente matrizes, portanto, a busca é direta), mas também entrada / saída de terminal (que não pode ser procurada a menos que seja armazenada em buffer), soquetes, portas seriais, etc. Então, você pode escrever um código que diz ou "Eu quero alguns dados e não me importo de onde eles vêm ou como chegaram aqui" ou "Eu produzirei alguns dados, e cabe ao meu interlocutor o que acontece com eles". O primeiro aceita um parâmetro de fluxo de entrada, o último aceita um parâmetro de fluxo de saída.
A melhor analogia em que consigo pensar é que um fluxo é uma correia transportadora vindo em sua direção ou se afastando de você (ou às vezes de ambos). Você tira coisas de um fluxo de entrada, coloca coisas em um fluxo de saída. Alguns transportadores que você pode imaginar saindo de um buraco na parede - eles não são procuráveis, ler ou escrever é um negócio único. Alguns transportadores estão dispostos à sua frente, e você pode escolher o paradeiro no fluxo que deseja ler / escrever - o que está procurando.
Como o IRBMe diz, no entanto, é melhor pensar em um fluxo em termos das operações que ele oferece (que variam de implementação para implementação, mas têm muito em comum) e não por analogia física. Fluxos são "coisas que você pode ler ou escrever". Ao iniciar a conexão de adaptadores de fluxo, você pode pensar neles como uma caixa com uma esteira transportadora e uma esteira transportadora conectada a outros fluxos e, em seguida, a caixa realiza alguma transformação nos dados (compactando-os ou alterando as alimentações de linha UNIX para os do DOS, ou o que for). Tubos são outro teste completo da metáfora: é aí que você cria um par de fluxos, para que qualquer coisa que você escreva em um possa ser lida no outro. Pense em buracos de minhoca :-)
Um fluxo já é uma metáfora, uma analogia, então não há realmente necessidade de apoiar outro. Você pode pensar nisso basicamente como um cano com um fluxo de água onde a água é realmente dados e o cano é o fluxo. Suponho que seja uma espécie de tubo bidirecional se o fluxo for bidirecional. É basicamente uma abstração comum colocada sobre coisas em que há um fluxo ou sequência de dados em uma ou ambas as direções.
Em linguagens como C #, VB.Net, C ++, Java etc., a metáfora do fluxo é usada para muitas coisas. Existem fluxos de arquivos, nos quais você abre um arquivo e pode lê-lo ou gravá-lo continuamente; Existem fluxos de rede em que a leitura e gravação no fluxo lê e grava em uma conexão de rede estabelecida subjacente. Os fluxos para gravação apenas são normalmente chamados de fluxos de saída, como neste exemplo, e da mesma forma, os fluxos que são apenas para leitura são chamados de fluxos de entrada, como neste exemplo.
Um fluxo pode executar a transformação ou codificação de dados (um SslStream em .Net, por exemplo, irá consumir os dados de negociação SSL e ocultá-lo; Um TelnetStream pode ocultar as negociações Telnet de você, mas fornecer acesso aos dados; O ZipOutputStream em Java permite gravar em arquivos em um arquivo zip sem ter que se preocupar com os detalhes internos do formato do arquivo zip.
Outra coisa comum que você pode encontrar são fluxos de texto que permitem escrever seqüências de caracteres em vez de bytes, ou alguns idiomas fornecem fluxos binários que permitem escrever tipos primitivos. Uma coisa comum que você encontrará em fluxos de texto é uma codificação de caracteres, da qual você deve estar ciente.
Alguns fluxos também suportam acesso aleatório, como neste exemplo. Um fluxo de rede, por outro lado, por razões óbvias, não o faria.
Sistemas operacionais UNIX também suportam o modelo de fluxo com entrada e saída de programa, conforme descrito aqui .
As respostas dadas até agora são excelentes. Estou fornecendo apenas outro para destacar que um fluxo não é uma sequência de bytes ou específico de uma linguagem de programação, pois o conceito é universal (embora sua implementação possa ser única). Muitas vezes vejo muitas explicações online em termos de SQL, C ou Java, que fazem sentido quando um fluxo de arquivos lida com locais de memória e operações de baixo nível. Mas eles geralmente abordam como criar um fluxo de arquivos e operar o arquivo em potencial no idioma especificado, em vez de discutir o conceito de fluxo.
Como mencionado, a stream
é uma metáfora, uma abstração de algo mais complexo. Para que sua imaginação funcione, ofereço outras metáforas:
a mangueira é a corrente
a mangueira, o bico e os mecanismos associados para permitir que o gás flua para o seu tanque é o fluxo
a rodovia é o córrego
seus ouvidos e olhos são correntes
Espero que você note nesses exemplos que as metáforas do fluxo existem apenas para permitir que algo viaje através dele (ou no caso da rodovia) e nem sempre representam o que estão transferindo. Uma distinção importante. Não nos referimos aos nossos ouvidos como uma sequência de palavras. Uma mangueira ainda é uma mangueira se não houver água fluindo através dela, mas temos que conectá-la a uma torneira para que ela funcione corretamente. Um carro não é o único 'tipo' de veículo que pode atravessar uma estrada.
Assim, pode existir um fluxo que não possui dados que viajem através dele, desde que esteja conectado a um arquivo .
Em seguida, precisamos responder a algumas perguntas. Vou usar arquivos para descrever fluxos, então ... O que é um arquivo? E como lemos um arquivo? Tentarei responder a isso mantendo um certo nível de abstração para evitar complexidade desnecessária e usarei o conceito de um arquivo em relação a um sistema operacional Linux devido à sua simplicidade e acessibilidade.
Um arquivo é uma abstração :)
Ou, simplesmente, como posso explicar, um arquivo é uma estrutura de dados de parte que descreve o arquivo e uma parte de dados que é o conteúdo real.
A parte da estrutura de dados (chamada de inode nos sistemas UNIX / linux) identifica informações importantes sobre o conteúdo, mas não inclui o conteúdo em si (ou o nome do arquivo). Uma das informações que ele mantém é um endereço de memória para onde o conteúdo é iniciado. Portanto, com um nome de arquivo (ou um link físico no linux), um descritor de arquivo (um nome numérico de arquivo com o qual o sistema operacional se importa) e um local inicial na memória, temos algo que podemos chamar de arquivo.
(o principal argumento é um 'arquivo' é definido pelo sistema operacional, pois é o sistema operacional que, em última análise, precisa lidar com isso. e sim, os arquivos são muito mais complexos).
Por enquanto, tudo bem. Mas como obtemos o conteúdo do arquivo, digamos uma carta de amor ao seu namorado, para que possamos imprimi-lo?
Se começarmos do resultado e retrocedermos, quando abrirmos um arquivo em nosso computador, todo o seu conteúdo será exibido na tela para que possamos ler. Mas como? Muito metodicamente é a resposta. O conteúdo do arquivo em si é outra estrutura de dados. Suponha uma matriz de caracteres. Também podemos pensar nisso como uma string.
Então, como 'lemos' essa string? Ao encontrar sua localização na memória e iterar através de nossa matriz de caracteres, um caractere de cada vez até atingir o final do caractere do arquivo. Em outras palavras, um programa.
Um fluxo é 'criado' quando seu programa é chamado e possui um local de memória para conectar ou conectar-se . Muito parecido com o nosso exemplo de mangueira de água, a mangueira é ineficaz se não estiver conectada a uma torneira. No caso do fluxo, ele deve estar conectado a um arquivo para que ele exista.
Os fluxos podem ser refinados ainda mais, por exemplo, um fluxo para receber entrada ou um fluxo para enviar o conteúdo de um arquivo para a saída padrão. O UNIX / linux conecta e mantém abertos 3 filestreams para nós imediatamente, stdin (entrada padrão), stdout (saída padrão) e stderr (erro padrão). Os fluxos podem ser construídos como estruturas de dados ou objetos, o que nos permite executar operações mais complexas dos dados transmitidos por eles, como abrir o fluxo, fechar o fluxo ou verificar erros no arquivo ao qual um fluxo está conectado. C ++ cin
é um exemplo de um objeto de fluxo.
Certamente, se você quiser, pode escrever seu próprio fluxo.
Um fluxo é um pedaço de código reutilizável que abstrai a complexidade de lidar com dados, fornecendo operações úteis para executar dados.
Outra analogia: você não pode nadar contra um fluxo, é por isso que você pode tirar o próximo bit, byte, string ou objeto do fluxo, enquanto os dados já lidos são excluídos. Um bilhete de ida ... ou basicamente apenas uma fila sem armazenar persistência.
Então, precisamos de filas? Você decide.
A palavra "fluxo" foi escolhida porque representa (na vida real) um significado muito semelhante ao que queremos transmitir quando o usamos.
Comece a pensar na analogia com um fluxo de água. Você recebe um fluxo contínuo de dados, assim como a água flui continuamente em um rio. Você não sabe necessariamente de onde vêm os dados e, na maioria das vezes, não precisa; seja de um arquivo, soquete ou qualquer outra fonte, não importa (não deveria) realmente importar. Isso é muito semelhante ao recebimento de um fluxo de água, pelo qual você não precisa saber de onde ele vem; seja de um lago, de uma fonte ou de qualquer outra fonte, não importa (não deveria) realmente importar. fonte