You are on page 1of 13

Operações com arquivos

A Microsoft forneceu modelos de objetos muito intuitivos para:

• Explorar a estrutura de diretórios, encontrar arquivos e pastas e


checar suas propriedades

• Mover, copiar e deletar arquivos e pastas

• Leitura e escrita de arquivos texto

• Leitura e escrita de arquivos binários

Gerenciamento do sistema de arquivos

As classes que são utilizadas para navegar pelo sistema de arquivos e


realizar operações, como mover, copiar, e deletar arquivos, são
mostradas na figura 1. O namespace de cada classe é mostrado em
parênteses abaixo do nome da classe.

A lista a seguir explica a função de cada classe:

• FileSystemInfo  classe base que representa qualquer sistema de


arquivos

• File e FileInfo  classes que representam um arquivo

• Directory e DirectoryInfo  classes que representam uma pasta

• Path  classe que contém membros que ajudam a manipular


nomes de caminhos de arquivos
Object
(System)

MarshalByRefObject
(System)

Directory File Path


FileSystemInfo (System.IO) (System.IO) (System.IO)
(System.IO)

DirectoryInfo FileInfo
(System.IO) (System.IO)

Figura 1. Hierarquia de classes para manipulação de arquivos e pastas

Classes DotNet que representam arquivos e pastas

Você deve ter notado na lista mostrada que há duas classes usadas para
representar uma pasta e duas classes para representar um arquivo.
Qual delas você deve utilizar vai depender muito de quantas vezes você
precisa acessar o arquivo ou pasta.

As classes Directory e File contêm apenas métodos estáticos (métodos


de classe) e nunca são instanciadas (você não cria objetos a partir
delas). Você usa essas classes fornecendo um caminho para o sistema
de arquivos apropriado sempre que você chama um de seus métodos.
Se você quer realizar uma operação em uma pasta ou um arquivo então
usar essas classes é mais eficiente, porque isso economiza o tempo de
criar objetos.

As classes DirectoryInfo e FileInfo implementam basicamente os mesmo


métodos que Directory e File, assim como propriedades, mas seus
métodos não são estáticos. Você precisa instanciar essas classes antes
de utilizá-las. Isso significa que essas classes são mais interessantes no
caso em que você deseja realizar várias operações usando o mesmo
objeto.

Vejamos uma comparação entre as duas abordagens:


FileInfo meuArquivo = new FileInfo(@“c:\program files\my
program\readme.txt”);
meuArquivo.CopyTo(@“d:\copies\readme.txt”);

Tem o mesmo efeito de:

File.Copy(@“c:\program files\my program\readme.txt”,


@“d:\copies\readme.txt”);

O primeiro fragmento de código será sutilmente mais lento ao ser


executado, porque é necessário instanciar um objeto FileInfo,
meuArquivo, mas, em compensação, ele deixa meuArquivo pronto para
que você possa realizar outras ações com ele. No segundo exemplo, não
foi necessário criar uma instância de um objeto para copiar o arquivo.

Para instanciar as classes FileInfo ou DirectoryInfo você fornece um


parâmetro para o construtor da classe, que é uma string contendo o
caminho do arquivo ou pasta. O primeiro exemplo faz isso para um
arquivo. Vejamos como seria para uma pasta.

DirectoryInfo minhaPasta = new DirectoryInfo(@“c:\program


files”);

Se o caminho representar um objeto que não existe, então embora nada


aconteça na hora da instanciação, uma exceção será lançada na hora
que você tentar utilizar o objeto chamando algum método ou
propriedade dele. Uma forma de saber se o objeto existe, e se é do tipo
apropriado, é utilizar a propriedade Exists:

FileInfo teste = new FileInfo(@“c:\windows”);


MessageBox.Show(teste.Exists.ToString());

A propriedade Exists retorna true caso o objeto exista e seja do mesmo


tipo que você instanciou. Ou seja, se você pediu um arquivo chamado
“windows” no “c:\” (como no exemplo) e se ele encontrar um arquivo
com esse nome, ela retornará true. Contudo, se ao invés de encontrar
um arquivo, for encontrada uma pasta chamada “windows” então ela
retornará false porque foi pedido um arquivo e não uma pasta.

Tendo conseguido definir se arquivo ou pasta existe, você pode obter


informações (usando as classes FileInfo e DirectoryInfo) sobre o arquivo
ou pasta usando as propriedades mostradas a seguir:

Nome Descrição
CreationTime Momento em que o arquivo ou
pasta foi criada
DirectoryName (apenas na Caminho completo da pasta que
FileInfo) contém o arquivo
Parent (apenas na DirectoryInfo) A pasta pai da pasta especificada
Exists Se o arquivo ou pasta existe
Extension Extensão do arquivo, ou branco se
for pasta
FullName Caminho completo do arquivo ou
da pasta
LastAccessTime Última vez que o arquivo ou a
pasta foi acessada
LastWriteTime Última vez que o arquivo ou a
pasta foi modificada
Name O nome do arquivo ou da pasta
Root (apenas na DirectoryInfo) O diretório raiz (unidade) do
caminho para a pasta
Length (apenas na FileInfo) O tamanho do arquivo em bytes

Você também pode realizar ações no arquivo ou na pasta usando os


métodos a seguir:

Nome Função
Create() Cria uma pasta ou um arquivo
vazio com um nome dado como
parâmetro. Para um FileInfo esse
método retorna um objeto de
arquivo que permite que você
escreva nele (veremos isso mais à
frente).
Delete() Exclui o arquivo ou a pasta. Para
pastas há uma para exclusão de
todo o conteúdo (sub-pastas ou
somente o conteúdo da pasta
dada)
MoveTo() Move e/ou renomeia uma pasta ou
arquivo
CopyTo() (Apenas para FileInfo) Copia o
arquivo. Note que não há método
de cópia para pastas.
GetDirectories() (Apenas para DirectoryInfo)
Retorna um array de objetos
DirectoryInfo representando todas
as sub-pastas contidas em uma
pasta.
GetFiles() (Apenas para DirectoryInfo)
Retorna um array de objetos
FileInfo representando todos os
arquivos contidos em uma pasta.
GetFileSystemInfos() (Apenas para DirectoryInfo)
Retorna objetos FileInfo e
DirectoryInfo representando todos
os objetos (arquivos e pastas)
contidas em uma pasta, como um
array de referências do tipo
FileSystemInfo.

Repare que as listas acima contêm apenas os principais métodos e


propriedades.

A classe Path

A classe Path não é uma classe instanciável. Ao invés disso, ela expõe
alguns métodos estáticos que fazem as operações com strings de
caminhos (de arquivos e pastas) mais fáceis.

Por exemplo, o fragmento de código a seguir utiliza o método


Path.Combine() para unir um caminho de pasta com um nome de
arquivo:

DirectoryInfo dirInfo = new


DirectoryInfo(@“c:\Upload\Documents”);
string strArquivo = “teste.txt”;
string strCaminho = Path.Combine(dirInfo.FullName, arquivo);

A tabela a seguir mostra os principais métodos da classe Path.

Nome Função
Combine() Combina um caminho com um
nome de arquivo ou pasta
ChangeExtension() Modifica a extensão atual do
arquivo na string. Se nenhuma
extensão for especificada então a
extensão atual será removida.
GetDirectoryName() Retorna todos as informações de
uma pasta, a qual esteja
explicitada entre o primeiro e o
último caractere separador de
pastas (“\”)
GetFileName() Retorna apenas o pedaço do
caminho que é o nome do arquivo
GetFileNameWithouExtension() Retornar apenas o pedaço do
caminho que é o nome do arquivo
mas sem a extensão
GetFullPath() Transforma um caminho relativo
em caminho absoluto usando a
pasta atual como referência. Por
exemplo, se “c:\temp” é a pasta
atual, então chamar GetFullPath()
de um nome de arquivo como
“teste.txt” retornará
“c:\temp\teste.txt”.
GetPathRoot() Obtém uma string com a pasta raiz
(por exemplo, “c:\”) de um
caminho absoluto. Se o caminho
for relativo, retorna nulo (null)
HasExtension() Retorna true se o caminho termina
com uma extensão e false caso
contrário.
IsPathRooted() Retorna true se o caminho é
absoluto e false se for um caminho
relativo.

Embora a classe Path contenha métodos para aprofundar um caminho


(adicionando pastas ao caminho), ele não fornece métodos para o
contrário (remover pastas de um caminho). Contudo, é possível
contornar essa limitação usando o método Combine() com caminho
relativo “..”, que significa “mova para uma sub-pasta acima na
hierarquia”. Veja o exemplo a seguir:

string strCaminho = @“c:\temp\subpasta”;

strCaminho = Path.Combine(strCaminho, “..”);


//agora strCaminho contém a string “c:\temp\subpasta\..”

strCaminho = Path.GetFullPath(strCaminho);
//strCaminho agora contém a string “c:\temp”

Obs.: Na maioria dos casos, uma exceção será lançada se você utilizar
os métodos da classe Path com caminhos com caracteres inválidos.
Contudo, caracteres curingas (* ou ?) são aceitos se causar exceções.
Estudo de caso: Um navegador de arquivos

Vamos agora colocar a mão na massa e criar um exemplo de uma


aplicação C# chamada Navegador de Arquivos que apresenta uma
interface simples com o usuário (Windows Forms) que permitirá que o
usuário navegue pelo sistema de arquivos, e veja a data e hora de
criação, data e hora do último acesso, data e hora da última
modificação, e tamanho dos arquivos.

A aplicação funcionará assim: você digita o nome da pasta ou do


arquivo na caixa de texto principal no topo da janela e clica o botão
“Mostrar”. Se você digitou um caminho para uma pasta, seu conteúdo
será listado nas caixas de listagens. Se você digitou um caminho para
um arquivo, seus detalhes serão mostrados nos rótulos no assoalho da
janela e o conteúdo da sua pasta será mostrado nas caixas de listagem.

A figura 2 mostra o layout da aplicação Navegador de Arquivos.

O usuário poderá facilmente navegar pelo sistema de arquivos clicando


em qualquer pasta na caixa de listagem do lado direito para ver o
conteúdo dessa pasta ou clicar no botão “Subir” para acessar a pasta pai
da pasta atual.

Nós criamos o projeto como uma aplicação Windows padrão C# no


Visual Studio DotNet, e adicionamos os vários, rótulos, caixas de texto,
caixas de listagem.

É necessário indicar que vamos utilizar o namespace System.IO.

using System.IO;

É necessário fazer isso para todos os sistemas relacionados com


arquivos que criarmos.

Na classe Form1, vamos criar um atributo para armazenar o caminho da


pasta que estiver sendo mostra no momento.

private string strCaminhoPastaAtual;


Figura 2. O navegador de arquivos

Em seguida vamos criar tratadores de eventos para os eventos que


possam ser gerados pelo usuário.

• Clique do usuário no botão “Mostrar”. Temos que testar se o que o


usuário digitou na caixa de texto é um caminho de arquivo ou de
pasta. Se for uma pasta listaremos os arquivos e sub-pastas dessa
pasta nos caixas de listagens. Se for um arquivo, nós faremos o
mesmo para a pasta que contém o arquivo, mas também
devemos mostrar as propriedades do arquivo nos rótulos.

• Usuário clica no nome do arquivo na caixa de listagem de


arquivos. Nesse caso, mostramos as propriedades do arquivo
clicado nos rótulos.
• Usuário clica no nome do folder na caixa de listagem de pastas.
Nesse caso limpamos todos os controles e então mostramos o
conteúdo dessa pasta nas caixas de listagens.

• Usuário clica no botão “Subir”. Nesse caso, nós limpamos todos os


controles e então mostramos o conteúdo da pasta pai da pasta
atual.

É interessante criarmos métodos (funções) que realizem as tarefas


principais. Primeiramente, vamos criar um método que limpa o conteúdo
dos controles.

public void LimpaCampos()


{
listBox1.Items.Clear();
listBox2.Items.Clear();
textbox1.Text = “”;
label2.Text = “”;
label4.Text = “”;
label6.Text = “”;
label8.Text = “”;
label10.Text = “”;
}

Em seguida, definimos um método, MostraInfoArquivo(), que mostra as


informações de um dado arquivo nos rótulos. Esse método recebe um
parâmetro, o caminho completo do arquivo, como string, e ele cria um
objeto FileInfo baseado nesse caminho:

public void MostraInfoArquivo(string strCaminho)


{
FileInfo arquivo = new FileInfo(strCaminho);
if (!arquivo.Exists)
{
throw new FileNotFoundException (“Arquivo não
encontrado: “ + strCaminho);
}
else
{
label2.Text = arquivo.Name;
label4.Text = arquivo.Length.ToString() + “bytes”;
label6.Text =
arquivo.CreationTime.ToLongTimeString();
label8.Text =
arquivo.LastAccessTime.ToLongDateString();
label10.Text =
arquivo.LastWriteTime.ToLongDataSting();
}

Repare que tomamos a precaução de lançar um exceção se houver


algum problema em localizar o arquivo no local especificado. A exceção
será tratada na rotina que chama esse método. Finalmente, definiremos
o método ListaPasta(), que mostra o conteúdo de uma determinada
pasta em duas caixas de listagem. O caminho completo do arquivo é
passado como parâmetro para esse método.

public void ListaPasta(string strCaminho)


{
DirectoryInfo pasta = new DirectoryInfo (strCaminho);
if (!pasta.Exists)
{
throw new DirectoryNotFoundException (“Pasta não
encontrada: “ + strCaminho);
}
else
{
LimpaCampos();
textBox1.Text = pasta.FullName;

//lista todas as sub-pastas da pasta


foreach (DirectoryInfo proximaSubPasta in
pasta.GetDirectories())
{
listBox1.Items.Add(proximaSubPasta.Name);
}

//lista todos os arquivos na pasta


foreach (FileInfo proximoArquivo in
pasta.GetFiles())
{
listBox2.Items.Add(proximoArquivo.Name);
}
}
}

Agora podemos cuidar dos tratadores de eventos. O tratador de evento


que gerencia o evento de clique no botão “Mostrar” é o mais complexo,
porque ele precisa cuidar de três possibilidades diferentes para o texto
que o usuário coloca na caixa de texto. Pode ser o nome de um arquivo,
o nome de uma pasta, ou texto inútil:
public void OnButton1_ButtonClick(object sender, EventArgs e)
{
try
{
string strCaminho = textBox1.Text;
DirectoryInfo pasta = new
DirectoryInfo(strCaminho);
if (pasta.Exists)
{
//é pasta
ListaPasta(pasta.FullName);
return;
}
FileInfo arquivo = new FileInfo(strCaminho);
if (arquivo.Exists)
{
//é arquivo
ListaPasta(arquivo.Directory.FullName);
int index =
listBox2.Items.IndexOf(arquivo.Name);
listBox2.SetSelected(index, true);
return;
}

//é texto inútil


throw new FileNotFoundException(“Não há arquivo ou
pasta com esse nome: “ + strCaminho);
}
catch(Exception objExcecao)
{
MessageBox.Show(objExcecao.Message);
}
}

Estabelecemos que se o texto fornecido representar uma pasta ou um


arquivo, criamos o objeto respectivo e examinamos se ele existe. Se
nenhum existir, então lançamos uma exceção. Se ele for pasta,
chamamos o ListaPasta() para popular as caixas de listagem. Se ele for
arquivo, populamos as caixas de listagem com os dados da pasta pai do
arquivo. Então programaticamente fazemos o nome do arquivo ficar
selecionado na caixa de listagem de arquivos. Isso tem o mesmo efeito
de o usuário clicar no nome do arquivo na caixa de listagem.

O código a seguir é o tratador de evento que é chamado quando um


item da caixa de listagem de arquivos é selecionada, seja pelo usuário,
ou como indicado acima, por nós mesmos, programaticamente. Ele
simplesmente constrói o caminho completo do arquivo selecionado, e o
passa para a função MostraInfoArquivo() que foi criada anteriormente.

public void OnListBox1Selected(object sender, EventArgs e)


{
try
{
string strSelecionado=
listBox1.SelectedItem.ToString();
string strCaminho =
Path.Combine(strCaminhoPastaAtual, strSelecionado);
MostraInfoArquivo(strCaminho);
}
catch(Exception objExcessao)
{
MessageBox.Show(objExcessao.Message);
}
}

O tratador de eventos para seleção de pasta na caixa de listagem de


pastas é implementado de forma muito parecida, exceto que nesse
caso, nós chamamos o método ListaPasta() para atualizar o conteúdo
das caixas de listagem:

public void OnListBox2FoldersSelected(object sender,


EventArgs e)
{
try
{
string strSelecionado =
listBox2.SelectedItem.ToString();
string strCaminho =
Path.Combine(strCaminhoPastaAtual, strSelecionado);
DisplayFolderList(strCaminho);
}
catch(Exception objExcecao)
{
MessageBox.Show(objExcecao.Message);
}
}

Finalmente, quando o botão “Subir” for clicado, ListaPasta() também


deve ser chamado, porém dessa vez precisamos obter o caminho para a
pasta pai da pasta atual. Isso é feito com o a propriedade
DirectoryName que retorna o caminho para a pasta pai.
public void OnButton2ButtonClick(object sender, EventArgs e)
{
try
{
string strCaminhoPasta = new
FileInfo(strCaminhoPastaAtual).DirectoryName;
ListaPasta (strCaminhoPasta);

//atualiza a pasta atual


strCaminhoPastaAtual = strCaminhoPasta;
}
catch(Exception objExcecao)
{
MessageBox.Show(objExcecao.Message);
}
}

You might also like