You are on page 1of 9

C# Lendo e escrevendo em arquivos textos (StreamReader/StreamWriter)

Jos Carlos Macoratti em C#

Confuso com a profuso de classes e mtodos disponveis na plataforma .NET para ler e escrever em arquivos? Afinal
quando vou acessar para ler ou escrever em um arquivo qual classe devo usar? Como fao para arquivos textos?
Antes de irmos direto para a parte prtica, vamos tentar ter uma viso geral da hierarquia de classes que a
plataforma .NET oferece para esta finalidade.
Um pouco de teoria
As operaes de input e output na plataforma .NET so gerenciadas pela classe abstrata Stream, que est no
namespace System.IO. Se voc conhece os fundamentos da programao orientada a objetos deve saber que uma
classe abstrata no pode ser instanciada diretamente. Portanto voc no pode usar a classe Stream diretamente
para acessar arquivos.
Ento para que serve esta classe? Serve para padronizar e fornecer um contrato com mtodos e propriedades que
devem ser implementadas por outras classes que herdam da classe Stream. Notou a palavra mgica herana? Pois
bem, a plataforma .NET oferece uma hierarquia de classes que podemos usar para realizar operaes
de input/output.(I/O).
A seguir vemos uma figura que mostra resumidamente a hierarquia de classes que herdam da classe Stream:

Podemos dizer que a classe Stream a raiz das classes que tratam um fluxo de dados ou stream. Como vemos
existem muitas classes que derivam a classe Stream e podemos dividi-las em duas categorias:
A primeira categoria contm todas as classes que implementam a classe Stream para uma operao especfica de
I/O. Essas classes so:
FileStream, para trabalhar com arquivos;
NetworkStream, para transferncia de dados em rede;
MemoryStream, para a troca de dados em memria.
A segunda categoria contm classes derivadas de Stream que reforam o que a classe Stream tem a oferecer. Elas
podem ser considerados como uma camada sobre a funcionalidade bsica oferecida pela classe Stream.
Esta categoria inclui os seguintes classes:
BufferedStream, que permitem realizar a operao tamponada sobre um stream. Devido ao fato que os dados no
so gravados diretamente para o stream, o nmero de operaes I/O necessrios para executar a operao menor,
aumentando assim, a execuo da operao;
CryptoStream, que permitem que os dados escritos ou lidos a partir do fluxo de dados possa ser criptografado ou
descriptografado.
Como todas as classes que tratam streams ou fluxo de dados herdam da classe Stream, vejamos a seguir os mtodos
e propriedades desta classe que as demais classes tem que implementar:

1. Propriedades
CanRead

obtm um valor indicando se o fluxo atual oferece suporte leitura.

CanSeek

obtm um valor indicando se o fluxo atual oferece suporte a busca.

CanTimeout

Obtm um valor que determina se o fluxo atual da suporte ao time out.

CanWrite

Obtm um valor indicando se o fluxo atual oferece suporte a escrita.

Length

Obtm o tamanho em bytes do fluxo.

Position

Obtm ou define a posio no fluxo atual.

ReadTimeout

Obtm ou define um valor, em milisegundos, que determina quanto tempo o fluxo tentar ler antes
do time out.

WriteTimeout

Obtm ou define um valor, em milisegundos, que determina quanto tempo o fluxo tentar escrever
antes do time out.

2. Mtodos (os principais)


BeginRead

Inicia uma operao de leitura assncrona. (Considere usar ReadAsync)

BeginWrite

Inicia uma operao de gravao assncrona. (Considere usar WriteAsync)

Close

Fecha o fluxo atual e libera os recursos (como os soquetes e identificadores de arquivo)


associados com o fluxo atual. Em vez de chamar esse mtodo, certifique-se de que o fluxo seja
descartado corretamente.

CopyTo(Stream)

Le os bytes do fluxo atual e escreve-os em outro fluxo.

Dispose()

Libera os recursos usados pelo Stream.

EndRead

Aguarda a leitura assncrona pendente terminar. (Considere usar ReadAsync)

EndWrite

Termina uma operao de gravao assncrono. (Considere usar WriteAsync)

Equals(Object)

Verifica se o objeto especificado igual ao objeto atual. (Herdado de Object.)

Finalize

Permite que um objeto tente liberar recursos e executar outras operaes de limpeza antes que
ele seja recuperado pela coleta de lixo. (Herdado de Object.)

Flush

Limpa todos os buffers para esse fluxo e faz com que alguns dados armazenados em buffer
sejam gravados no dispositivo subjacente.

Read

L uma sequncia de bytes de fluxo atual e avana a posio no fluxo pelo nmero de bytes
lidos.

Seek

Define a posio no fluxo atual.

SetLength

Define o comprimento de fluxo atual.

ToString

Retorna uma string que representa o objeto atual. (Herdado de Object.)

Write

Grava uma sequncia de bytes no fluxo atual e avana a posio atual dentro desse fluxo pelo
nmero de bytes escritos.

(fonte: http://msdn.microsoft.com/pt-br/library/system.io.stream%28v=vs.110%29.aspx acessado em fevereiro de


2014)

Ento, para ler e escrever em arquivos textos podemos use as classes StreamReader/StreamWriter. Essas classes
derivam das classes TextReader/TextWriter.
Abaixo temos uma figura onde temos as classes do namespace System.IO mostrando a hierarquia de herana das
principais classes para Input/OutPut:

As classes TextReader/TextWriter representam um leitor/escritor que podem ler/escrever uma srie sequencial de
caracteres. Elas so classes abstratas e no podem ser instanciadas diretamente.
Observe que as classes StreamReader/StreamWriter herdam de TextReader e de TextWriter. Conclumos, assim,
que StreamReader um tipo de TextReader e que StreamWriter um tipo de TextWriter. Assim,
um StreamReader obtm os seus dados de um fluxo ou stream que pode se representado por dados que esto na
memria, em um arquivo ou vindo de uma porta serial, vdeo ou capturado em um dispositivo. Dessa forma,
um StreamReader possui uma implementao especfica para leitura de caracteres de um stream como um arquivo.
StreamReader implementa um TextReader que l caracteres de um fluxo de bytes em uma codificao especfica.
TextReader representa um leitor que pode ler uma srie seqencial de caracteres.(classe abstrata).
Concluso: se eu preciso de uma rotina para ler e/ou escrever em arquivos texto, eu vou usar
um StreamReader/StreamWriter.
Escrevendo e lendo arquivos textos
Vamos comear mostrando como criar e escrever em arquivos texto usando StreamWriter.
A seguir, as principais propriedades e mtodos da classe StreamWriter:
Obtm ou define um valor indicando
se o StreamWriter ir liberar o buffer
AutoFlush()
no fluxo subjacente aps cada
chamada aWrite.
Close()

Fecha o objeto atual


de StreamWriter e o fluxo subjacente

Dispose()

Libera os recursos usados pelo objeto


de TextWriter

Flush()

Limpa todos os buffers para o gravador


atual e faz com que todos os dados
armazenados em buffer sejam
gravados no fluxo subjacente.

NewLine()
Write()

Grava no fluxo.

WriteLine()

Grava no fluxo seguido de um


terminador de linha

Para comear, temos que referenciar o namespace System.IO e declarar e inicializar uma nova instncia
de StreamWriter usando um de seus construtores.
StreamWriter writer = new StreamWriter(macoratti.txt)
Nesta declarao, um novo StreamWriter inicializado com o nome do arquivo igual macoratti.txt (voc pode usar
qualquer extenso como .dat, por exemplo).
Se o arquivo no existir, ela ser criado. No exemplo, como no definimos um local para o arquivo, ele ser criado no
mesmo diretrio da aplicao.
Para escrever no arquivo podemos usar o mtodo Write() ou WriteLine(). Estes mtodos possuem diversas
sobrecargas.
1

using (StreamWriter writer = new StreamWriter("macoratti.txt"))

writer.Write("Macoratti .net ");

writer.WriteLine("Quase tudo para Visual Basic");

writer.WriteLine("http://www.macoratti.net");

No cdigo, o mtodo Write() escreve uma linha e no anexa uma linha. J o mtodo WriteLine() anexa uma nova
linha (\r\n) ao arquivo a cada chamada. Observe que estamos usando a clusula using de forma a liberar os
recursos usados na operao aps sua utilizao. Nunca esquea de liberar os recursos usados e tambm verifique
sempre se o arquivo existe quando necessrio.
Se desejarmos escrever em um arquivo j existente anexando linhas ao arquivo podemos usar o construtor
: StreamWriter(string caminho, bool anexa).
Inicialize uma nova instncia do StreamWriter para o arquivo no caminho especificado, usando a codificao padro
e buffer. Se o arquivo existir, pode ser tanto sobrescrito ou anexado. Se o arquivo no existir, este construtor cria um
novo arquivo.
1

using System.IO;

class Program

static void Main()

// 1: Escreve um linha para o novo arquivo

using (StreamWriter writer = new StreamWriter("C:\\dados\\macoratti.txt", true))

10

writer.WriteLine("Macoratti .net");

11

12

// 2: Anexa uma linha ao arquivo

13
14

using (StreamWriter writer = new StreamWriter(@"C:\dados\macoratti.txt", true))


{

15

writer.WriteLine("Quase tudo para Visual Basic");

16

17

18

No cdigo acima inicia com um novo StreamWriter e abre o arquivo c:\dados\macoratti.txt no modo append. O
argumento true do construtor especifica a operao para anexar dados ao arquivo. No primeiro WriteLine() a string
ser anexada ao arquivo e no segundo WriteLine() estamos reabrindo o arquivo c:\dados\macoratti.txt e anexando a
nova string ao arquivo.
muito comum quando voc estiver escrevendo em um arquivo usar um array ou uma lista de strings. A melhor
forma de fazer isso usar um lao aps declarar uma instncia de um StreamWriter, conforme mostra o exemplo a
seguir:
1

using System.IO;

class Program

static void Main()

// Usamos um tipo var que mais simples

using (var writer = new StreamWriter("macoratti.txt"))

// Percorre o lao

10

for (int i = 0; i < 10; i++)

11
12

13
14

{
// Escreve uma string formatada no arquivo

writer.Write("{0:0.0} ", i);


}

15

16

17

No exemplo, a instruo using abre e prepara o arquivo e aps concluir fecha e libera os recursos usados.
Para ler um arquivo texto utilize a classe StreamReader(), criando uma instncia da classe e usando o construtor
onde informa o nome do arquivo a ser aberto.
A seguir temos os principais membros da classe StreamReader:
Close()

Fecha o StreamReader atual

Dispose()

Libera os recursos usado


pelo StreamReader

Peek()

Retorna o prximo caractere


disponvel mas no o utiliza

Read()

L o prximo caractere ou conjunto


de caracteres de um stream

ReadBlock()

L um nmero especfico de
caracteres de um stream atual e
escreve os dados em um buffer

ReadLine()

L uma linha de caractere do stream


atual e retorna os dados em uma
string

ReadToEnd()

L o stream da posio atual at o


fim do stream

No exemplo abaixo estamos acessando o arquivo macoratti.txt e lendo uma linha do arquivo texto usando o
mtodo ReadLine(). uma boa prtica sempre verificar se o arquivo a ser lido existe ou se encontra no local
indicado.
1

using System;

using System.IO;

3
4

class Program

7
8

static void Main()

{
//usando a instruo using os recursos so liberados aps a concluso da operao

string linha;

10

using (StreamReader reader = new StreamReader("macoratti.txt"))

11

12

linha = reader.ReadLine();

13

14

Console.WriteLine(linha);

15

16

A linha lida exibida no console usando a instruo Console.WriteLine(). Para ler mais de uma linha do arquivo
podemos usar um lao While e percorrer o arquivo enquanto no for encontrado um caractere null que indica o fim
de arquivo.
1

using System;

using System.IO;

namespace Operacoes_IO

class Program

static void Main(string[] args)

string arquivo = @"C:\dados\macoratti.txt";

10

if (File.Exists(arquivo))

11

12

13
14

try

{
using (StreamReader sr = new StreamReader(arquivo))

15

16

String linha;

17

// L linha por linha at o final do arquivo

18

while ((linha = sr.ReadLine()) != null)

19

20

Console.WriteLine(linha);

21

22

23

24

catch (Exception ex)

25
26

{
Console.WriteLine(ex.Message);

27

28

29

else

30

31
32

Console.WriteLine(" O arquivo " + arquivo + "no foi localizado !");


}

33
34

Console.ReadKey();
}

35
36

}
}

Este cdigo utiliza a classe StreamReader() para ler o arquivo macoratti.txt na pasta c:\dados.
Estamos usando o mtodo ReadLine() em um bloco While lendo linha a linha at encontrar o valor null que
corresponde ao final do arquivo : while ((linha = sr.ReadLine()) != null). Verificamos tambm se o arquivo existe (
s usar o mtodo esttico Exists() da classe File: if (File.Exists(arquivo)).
Estamos usando tambm um bloco try/catch para tratar qualquer exceo que ocorre quando do acesso e da
utilizao do arquivo e a clusula using est sendo usada para liberar de forma automtica os recursos usados para
acessar e ler o arquivo.
Dessa forma, sempre que formos abrir um recurso como um arquivo, primeiro devemos verificar se ele existe e
sempre devemos realizar o tratamento de exceo usando o bloco try/catch quando formos tratar arquivos com as
classes do namespace System.IO.
Finalmente no devemos esquecer de liberar os recursos usados.

You might also like