O que é um fluxo?

136

O que é um fluxo no mundo da programação? Por que precisamos disso?

Por favor, explique com a ajuda de uma analogia, se possível.

pokrate
fonte
10
Esta é uma duplicata do stackoverflow.com/questions/507747/… .
318 John Saunders

Respostas:

161

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:

  • leia um byte. Na próxima vez que você ler, receberá o próximo byte e assim por diante.
  • ler vários bytes do fluxo em uma matriz
  • seek (mova sua posição atual no fluxo, para que da próxima vez que você ler obtenha bytes da nova posição)
  • escreva um byte
  • escreva vários bytes de uma matriz no fluxo
  • pule bytes do fluxo (isso é como leitura, mas você ignora os dados. Ou, se preferir, é como procurar, mas só pode avançar).
  • empurre bytes de volta para um fluxo de entrada (isso é como "desfazer" para leitura - você move alguns bytes de volta para o fluxo, para que da próxima vez que ler seja o que você verá. Às vezes é útil para analisadores, como:
  • espiar (observe os bytes sem lê-los, para que eles ainda estejam no fluxo para serem lidos mais tarde)

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 :-)

Steve Jessop
fonte
3
De longe a melhor explicação que já li. Juntamente com o que diz no SICP ("O processamento de fluxo nos permite modelar sistemas que possuem estado sem nunca usar atribuição ou dados mutáveis"), acho que finalmente entendi. Obrigado!
precisa
85

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.

  • O MSDN fornece uma boa visão geral dos fluxos em .Net.
  • A Sun também tem uma visão geral de sua classe OutputStream geral e classe InputStream .
  • No C ++, aqui está a documentação istream (fluxo de entrada), ostream (fluxo de saída) e iostream (fluxo bidirecional).

Sistemas operacionais UNIX também suportam o modelo de fluxo com entrada e saída de programa, conforme descrito aqui .

IRBMe
fonte
13

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.

A metáfora

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:

  1. você quer encher uma piscina vazia com água. Uma maneira de conseguir isso é conectar uma mangueira a uma torneira, colocando a ponta da mangueira na piscina e ligando a água.

a mangueira é a corrente

  1. Da mesma forma, se você quisesse reabastecer seu carro com gasolina, iria a uma bomba de gasolina, inseria o bico no tanque de combustível e abriria a válvula apertando a alavanca de travamento.

a mangueira, o bico e os mecanismos associados para permitir que o gás flua para o seu tanque é o fluxo

  1. se você precisar trabalhar, começaria a dirigir de sua casa para o escritório usando a rodovia.

a rodovia é o córrego

  1. se você quiser conversar com alguém, use seus ouvidos para ouvir e sua boca para falar.

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 .

Removendo a abstração

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.

O que é um arquivo?

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?

Lendo um arquivo

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.

Definição

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.

rekurzion
fonte
Portanto, um fluxo é o meio pelo qual os dados fluem. Ele deve estar conectado à fonte dos dados e pode executar operações em si mesmo e nos dados que fluem através deles.
KingBryan
sim. minha única razão para escrever uma resposta adicional foi esclarecer que um fluxo pode existir mesmo que os dados não estejam fluindo por ele. enquanto que uma corrente IRL (com água e outras coisas) deixa de ser uma corrente quando a água para de fluir e pode causar confusão ao pensar sobre a analogia.
rekurzion
1
Atualmente, estou aprendendo Java, e sua resposta me ajudou a entender isso.
KingBryan
6

Além das coisas mencionadas acima, há um tipo diferente de fluxos - conforme definido nas linguagens de programação funcional, como Scheme ou Haskell - uma estrutura de dados possivelmente infinita, gerada por alguma função sob demanda.

EFraim
fonte
6

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.

Marcus
fonte
isso significa que em um fluxo, você tem que seguir em frente não pode se mover para trás. Além disso os dados anteriores excluídos como u ir para a frente que salvar a memória certo?
Muhammad Faizan Khan
5

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

Premraj
fonte