Arquivo
Manipulando arquivos no .NET
Vou mostrar como manipular arquivos dentro de sua aplicação. Irei escrever no artigo duas formas de fazer isso. A primeira é usando a classe File do namespace System.IO que é a maneira mais fácil de fazer isso e funciona muito bem para a maioria das situações. Agora se você precisa tratar arquivos grandes, compactação, arquivos em memória, criptografia e etc… utilize a segunda parte do artigo aonde eu apresento a classe Stream também do namespace System.IO.
File
Com classe File você pode ler arquivos, escrever, criptografar(de acordo com Windows), alterar alguns atributos e criar backups. Vamos direto aos exemplos com os métodos mais utilizados.
File.WriteAllBytes(“teste.txt”, new byte[] { byte.MaxValue }); //Sobrescreve um array de bytes no novo arquivo ou existente
File.WriteAllLines(“teste.txt”, new String[] { “Teste 1”, “Teste 2” }); //Sobrescreve o texto (array string) no novo arquivo ou existente
File.WriteAllText(“teste.txt”, “conteúdo total”); //Sobrescreve o texto no novo arquivo ou existente
File.AppendAllText(“teste.txt”, “conteúdo”); //Adiciona um texto ao arquivo existente ou cria um novo
File.Encrypt(“teste.txt”); //Criptografa o arquivo de acordo com as configurações do Windows
File.Decrypt(“teste.txt”); //Descriptografa o arquivo de acordo com as configurações do Windows
byte[] allBytes = File.ReadAllBytes(“teste.txt”); //Recupera todos os bytes do conteúdo do arquivo
string[] allLines = File.ReadAllLines(“teste.txt”); //Recupera um array de string contento todas as linhas do arquivo
string allText = File.ReadAllText(“teste.txt”); //Recupera todo o conteúdo do arquivo para dentro de uma string
File.SetAttributes(“teste.txt”, FileAttributes.Normal); //Configura o atributo do arquivo. Ex: Normal, Leitura, Sistema
File.SetCreationTime(“teste.txt”, DateTime.Now); //Configura a data de criação do arquivo
File.SetLastAccessTime(“teste.txt”, DateTime.Now); //Configura a ultima data que o arquivo foi acessado
File.SetLastWriteTime(“teste.txt”, DateTime.Now); //Configura a ultima data que o arquivo foi escrito
File.Replace(“teste.txt”, “teste1.txt”, “testebkp.txt”); //Substitui um arquivo pelo outro e faz uma cópia de segurança do segundo arquivo
Lembrando que a classe File trabalha diretamente com o arquivo, ou seja, cada a vez que você precisar escrever ou ler alguma coisa você precisa-rá chamar o arquivo novamente e executar a tarefa. Outro item importante é que a classe File trabalha sempre com o arquivo todo, por ex: nos métodos de Read o arquivo todo é lido de uma vez.
Stream
Utilizar a classe Stream é um pouco mais complexo, porém você terá maior controle sobre o arquivo. Stream é a classe base que permite você trabalhar diretamente com dados(Arquivo, Memória, Arquivo compactado e etc..) de forma seqüencial ou randômica. (Diferente do File que trabalha com o arquivo inteiro de uma vez).
Segue abaixo um diagrama demonstrando o diagrama de classe que representa a classe Stream e as classes que a implementam.
Stream : Contém propriedades e métodos que serão usadas por todas as classes que a implementam. (Exemplo de métodos e propriedades compartilhada por todos os Streams: CanRead, Write, Position).
FileStream : Classe especializada no tratamento de arquivos.
BufferedStream : Classe especializada em prover performance por buffer de leitura e de escrita.
MemoryStream : Classe que permite você criar Streams diretamente na memoria.
DeflateStream : DeflateStream permite você compactar Streams utilizando o método de compressão Deflate.
GZipStream : GZipStream é semelhante ao DeflateStream porém com o método de compressão GZip.
UnmanagedMemoryStream : Fornece acesso a blocos não-gerenciados de memória.
Vamos explorar a classe base Stream. Todas as outras classes de Stream são baseadas nesta classe, isso quer dizer que, todos os métodos aqui serão utilizados pelas outras classes. Porém cada um dos outros Streams serão especializados em suas funções como descrevi acima. Como é uma classe abstrata, para instancia-la eu preciso determinar qual classe irá implementá-la. No caso estou usando um MemoryStream somente para exemplificar, no entanto você pode usar qualquer Stream para isso.
Stream _stream = new MemoryStream();
Segue abaixo algumas propriedades interessantes para você testar.
Console.WriteLine(_stream.CanRead); // Verifica se o Stream pode ser lido
Console.WriteLine(_stream.CanSeek); // Verifica se pode haver uma busca
Console.WriteLine(_stream.CanTimeout); // Verifica se o Stream tem um time-out
Console.WriteLine(_stream.CanWrite); // Verifica se o Stream pode ser lido
Console.WriteLine(_stream.Length); // Retorna o tamanho do Stream
Console.WriteLine(_stream.Position); //Recupera a posição do ponteiro dentro da memória
Para escrever e ler em um Stream você deve usar os métodos Write/WriteByte e Read/ReadByte. É muito importante entender o conceito do ponteiro, toda a escrita e leitura é feita a partir da posição que o ponteiro esta no momento. Segue abaixo um exemplo completo de escrita e leitura um Stream.
byte[] bytes = new byte[2] { byte.MaxValue, byte.MaxValue };
_stream.Position = 0; // Configura o ponteiro na posição 0
_stream.WriteByte(255); // Escreve o byte 255 (equivalente a ff) e passa o ponteiro para o fim da escrita
_stream.Write(bytes, 0, bytes.Length); // Recebe um array de bytes para escrever, 0 significa que não terá buffer, e o terceiro parâmetro indica quantos bytes devem ser escritos
_stream.Position = 0; //Retorna o ponteiro para posição inicial
while (_stream.Position != _stream.Length) //Executa o while enquanto o ponteiro não chegar no final
{
Console.WriteLine( _stream.ReadByte()); //Le o byte e avança uma posição no ponteiro
}
_stream.Position = 0; // Configura o ponteiro na posição 0
Console.WriteLine(_stream.Read(bytes, 0, bytes.Length));// Recebe um array de bytes para ler, 0 significa que não terá buffer, e o terceiro parâmetro indica quantos bytes devem ser lidos
Abaixo irei explicar como se inicializa os Streams mais utilizados.
FileStream : Para inicializar o você precisa indicar o path do arquivo, como será o modo de utilização do arquivo, e qual tipo de permissão ele terá.
FileStream _fileStream = new FileStream(@”C:\Teste.txt”, FileMode.Open, FileAccess.Read); //Neste exemplo eu estou indicando que o arquivo C;\Teste.txt existe fisicamente e eu irei abri-lo para utilizar, e a permissão necessária para utilização do mesmo será somente para leitura.
Podemos inicializar o FileStream direto da classe File. Segue abaixo alguns exemplos.
FileStream fileStream = File.Create(“teste.txt”); // Cria um arquivo e associa ao FileStream
FileStream fileStream = File.Open(“teste.txt”, FileMode.Open); // Abre um arquivo e associa ao FileStream
FileStream fileStream = File.OpenRead(“teste.txt”); // Abre um arquivo e associa ao FileStream permitindo a leitura
FileStream fileStream = File.OpenWrite(“teste.txt”); // Abre um arquivo e associa ao FileStream permitindo a escrita
MemoryStream : Como o MemoryStream é baseado apenas na memória sua inicialização é muito simples.
MemoryStream _memoryStream = new MemoryStream();
GzipStream : O Stream de compactação GzipStream precisa que você indique se o processo vai ser de compactação ou de descompactação e também indique qual Stream vai ser compactado ou descompactado.
GZipStream _gZipStream = new GZipStream(_fileStream, CompressionMode.Compress); //Neste exemplo estou indicando que vou compactar um FileStream
Leitura e escrita
Você pode usar o exemplo de escrita e leitura da classe base Stream que eu demonstrei para todas as classes que implementam a classe Stream, porém existe algumas classes especializadas para executar isso. Segue abaixo um diagrama que demonstra toda a estrutura completa de classes para leitura e escrita em um Stream.
TextWriter : Classe base para todas classes de escrita com exceção da BinaryWriter.
StreamWriter : Classe especializada na escrita em Stream.
HtmlTextWriter : Classe especializada na escrita de Html.
StringWriter : Classe especializada na escrita de strings.
BinaryWriter : Classe especializada na escrita de bytes.
TextReader : Classe base para todas classes de leitura com exceção da BinaryReader.
StreamReader : Classe especializada na leitura em Stream.
StringReader : Classe especializada na leitura de strings.
BinaryReader : Classe especializada na leitura de bytes.
StreamWriter
A classe StreamWriter herda as funcionalidade da classe TextWriter. Ela permite você escrever no Stream. Abaixo segue um exemplo de como utilizar.
StreamWriter sw = new StreamWriter(_fileStream); //Inicializa um StreamWriter. Utilizei um FileStream que aponta para um arquivo físico
sw.Write(“teste”); //Escreve no StreamWriter uma string que você passar como parâmetro
sw.WriteLine(); //Escreve uma quebra de linha no StreamWriter
sw.Flush(); // Escreve no Stream configurado (no caso um FileStream representando um arquivo) e limpa o buffer do StreamWriter
sw.AutoFlush = false; // Você pode utilizar o auto flush para indicar o flush será executado automaticamente cada vez que você chamar o método Write ou WriteLine do StreamWriter
Podemos inicializar o StreamWriter diretamente da classe estática File.
StreamWriter sw = File.CreateText(“teste.txt”); //Cria ou abre um arquivo físico e associa com o StreamWriter
StreamWriter sw = File.AppendText(“teste.txt”); //Associa um arquivo existente e adiciona o conteúdo que será escrito no StreamWriter com o conteúdo do arquivo
StreamReader
StreamReader é a classe responsável por ler conteúdo dos Stream e herda da classe TextReader. Abaixo eu demonstrarei com usá-la.
StreamReader sr = new StreamReader(_fileStream); //Inicializa o StreamReader. Utilizei um FileStream que aponta para um arquivo físico
Console.WriteLine(sr.ReadLine()); //Le a linha em que o ponteiro esta no momento e adianta o ponteiro para a próxima linha
Console.WriteLine(sr.ReadToEnd()); //Le todo o FileStream a partir do posição atual do ponteiro a avança o ponteiro para o final
Console.WriteLine(sr.EndOfStream); //Verifica se o ponteiro está no final do FileStream
Liberando recursos
É uma boa prática chamar o mesmo close para liberar recursos do sistema quando estamos trabalhando com memória não-gerenciável como por exemplo Streams, Writer e Reader.
_fileStream.Close();
sw.Close();
sr.Close();
E chegamos ao fim de mais um artigo. Como este assunto é muito vasto, decidi escolher os itens mais comuns de serem utilizados para demonstrar aqui, então por isso que algumas classes eu não descrevi como implementa-las.
Espero que tenham gostado.