quinta-feira, 9 de fevereiro de 2012

Android - Trabalhando com arquivo texto Parte 1

Olá

Hoje iremos começar mais uma série de artigos e estes agora serão voltados a manipulação de arquivos, nesse projeto serão criadas  três rotinas que são:
1º - criação de arquivos
2º - leitura de arquivos
3º - obter o System Root (diretório de armazenamento externo do Android)

Um detalhe importante para esse projeto é que será necessário habilitar a permissão WRITE_EXTERNAL_STORAGE no arquivo de manifest, é graças a essa permissão que seu aplicativo pode gravar arquivos no SD Card.

Como já de costume todos os fontes abaixo estão com vários comentários para facilitar o aprendizado.


Arquivo main.xml, layout da única tela apresentada nesse projeto:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
        
    <TextView 
        android:text="Root:" 
        android:id="@+id/txtRoot2" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"/>
    
    <TextView 
        android:text="Nome do arquivo:" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"/>
        
    <EditText 
        android:id="@+id/edtNomeArq" 
        android:text="teste.txt" 
        android:layout_height="wrap_content" 
        android:layout_width="fill_parent"/>

    <TextView 
        android:text="Texto do arquivo a ser salvo:" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"/>
        
    <EditText 
        android:id="@+id/edtSalvar" 
        android:text="Escrever arquivo" 
        android:layout_height="wrap_content" 
        android:layout_width="fill_parent"/>

    <TextView 
        android:text="Arquivo lido:" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"/>

    <EditText 
        android:id="@+id/edtLer" 
        android:text=""
        android:layout_height="wrap_content" 
        android:layout_width="fill_parent"/>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical">
        <Button
            android:layout_width="0dip"
            android:layout_weight="1.0"
            android:layout_height="wrap_content" 
            android:onClick="click_Salvar"
            android:text="Salvar" />
        <Button
            android:layout_width="0dip"
            android:layout_weight="1.0"
            android:layout_height="wrap_content"
            android:onClick="click_Ler" 
            android:text="Abrir" />
        <Button
            android:layout_width="0dip"
            android:layout_weight="1.0"
            android:layout_height="wrap_content"
            android:onClick="click_Limpar" 
            android:text="Limpar" />
    </LinearLayout>
</LinearLayout>

Arquivo AndroidManifest.xml, contém configurações iniciais do aplicativo:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="br.com.EscolaDeAndroid.ArquivoTexto"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    
</manifest>


Arquivo main.java, classe que contém todo o fonte necessário para este projeto:
package br.com.EscolaDeAndroid.ArquivoTexto;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class main extends Activity {
    private TextView txtRoot;
    private TextView txtNomeArq;
    private TextView txtSalvar;
    private TextView txtLer;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            setContentView(R.layout.main);

            txtRoot = (TextView) findViewById(R.id.txtRoot2);
            txtNomeArq = (TextView) findViewById(R.id.edtNomeArq);
            txtSalvar = (TextView) findViewById(R.id.edtSalvar);
            txtLer = (TextView) findViewById(R.id.edtLer);
        
        
            txtRoot.append(GetRoot());        
        
        } catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }        
    }
    
    public void click_Salvar(View v)
    {
        SalvarArquivo();
    }

    public void click_Ler(View v)
    {
        LerArquivo();
    }

    public void click_Limpar(View v)
    {
        txtNomeArq.setText("teste.txt");
        txtSalvar.setText("");
        txtLer.setText("");
    }
    
    //Exibir o diretório de armazenamento externo do Android
    private String GetRoot()
    {
        File root = android.os.Environment.getExternalStorageDirectory(); 
        return root.toString();
    }
    
    private void SalvarArquivo()
    {
        String lstrNomeArq;
        File arq;
        byte[] dados;
        try
        {
            //pega o nome do arquivo a ser gravado
            lstrNomeArq = txtNomeArq.getText().toString();
            
            arq = new File(Environment.getExternalStorageDirectory(), lstrNomeArq);
            FileOutputStream fos;
            
            //transforma o texto digitado em array de bytes
            dados = txtSalvar.getText().toString().getBytes();
            
            fos = new FileOutputStream(arq);
            
            //escreve os dados e fecha o arquivo
            fos.write(dados);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }        
    }

    private void LerArquivo()
    {
        String lstrNomeArq;
        File arq; 
        String lstrlinha;
        try
        {
            //pega o nome do arquivo a ser lido
            lstrNomeArq = txtNomeArq.getText().toString();

            //limpa a caixa de texto que irá receber os dados do arquivo
            txtLer.setText("");

            
            arq = new File(Environment.getExternalStorageDirectory(), lstrNomeArq);
            BufferedReader br = new BufferedReader(new FileReader(arq));
            //efetua uma leitura linha a linha do arquivo a carrega 
            //a caixa de texto com a informação lida
            while ((lstrlinha = br.readLine()) != null) {
                if (!txtLer.getText().toString().equals(""))
                {
                    txtLer.append("\n");
                }
                txtLer.append(lstrlinha);
            }            
            
        } catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }        
    }

    public void toast (String msg)
    {
        Toast.makeText (getApplicationContext(), msg, Toast.LENGTH_SHORT).show ();
    } 
    
    private void trace (String msg) 
    {
        toast (msg);
    }    
}

Abaixo temos o resultado prático de nosso projeto:


O funcionamento do projeto será o seguinte:
1º - na primeira caixa de texto será o local onde o usuário irá informar o nome do arquivo a ser salvo, por padrão o nome do arquivo será teste.txt, mas o usuário poderá informar o nome que desejar.
2º - na segunda caixa de texto será para digitar o conteúdo de nosso arquivo, em seguida o usuário deve clicar no botão "Salvar" para efetuar a gravação do arquivo.
3º - clicando no botão "Abrir" o sistema irá buscar o arquivo de acordo com a primeira caixa de texto e exibir o conteúdo na terceira caixa de texto.
4º - clicando no botão "Limpar" o aplicativo limpará a segunda e a terceira caixa de texto.

Obs.: não fiz tratamento de erro do tipo, arquivo não encontrado, se deseja substituir o arquivo já existente, esses serão temas para os próximos artigos.



Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.


Desenv com qualidade!

16 comentários:

Alexandre Gonçalves disse...

Boa Tarde, teria como você postar um exemplo de como ALTERAR uma determinada linha de um arquivo já gravado?

OBrigado.

Marcio de Souza disse...

Alexandre,


Isso está nos planos é que por enquanto estou um pouco mais focado em layouts, assim que possível eu post sim.

Continue acompanhando.

Obrigado pela visita!

Fábio Rodrigues de sousa disse...
Este comentário foi removido pelo autor.
Fábio Rodrigues de sousa disse...

o ex e muito legal só que eu não estou conseguindo salva os dados no sd
e não sei como da as pemiçoes necessárias para isto mais parabéns pelo tutorial

Marcio de Souza disse...

Fabio,

É bem provável que você não inseriu permissão no arquivo manifest, conforme demonstrado no exemplo.



Obrigado pela visita.

Edson S Santos disse...

Parabéns pelo blog.

Marcio de Souza disse...

Edson,

Obrigado, espero que continue visitando.

Até mais...

Alan Moraes disse...

Tem como visualizar o arquivo salvo, fora do aplicativo?

Marcio de Souza disse...

Alan,

Tem sim, se você estiver utilizando um aparelho é só clicar no ícone "Aplicações" e depois clicar no ícone "Meus arquivos". isso também vale para o emulador AVD.

Você pode visualizar esse arquivo até mesmo pelo Eclipse, clicando no Menu DDMS, que fica em Windows / Open Perspective / DDMS, desde que seu emulador esteja carregado.

Obrigado pela visita e até mais...

Valtuir Jr. disse...

Tem como postar um exemplo passo-a-passo para copiar um arquivo de um diretório para outro?

Por exemplo, quero copiar uma imagem da pasta "/sdcard/Pictures/image1.jpg"

para pasta /sdcard/Aplicativos/image1.jpg"

ambas as pastas ficam no sdcard do android... achei alguns exemplos na net do utilizando FileChannel e TransferTo mas não estou conseguindo copiar o arquivo.

Marcio de Souza disse...

Valtuir,

No momento estou sem tempo, pois meu filho vai nascer agora em poucos dias...

Provavelmente por uns 2 meses vai sem bem corrido.

Estou anotando varias solicitações e assim que tiver tempo pretendo responder todas no blog.

Obrigado!

thiagu disse...

Muito bom exemplo! show!

e pra quem nao saber add a permissao
e so abrir o AndroidManifest.xml
e antes da tag application e depois da tag uses dsk
poe esse codigo


<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

Felipe Gomes disse...

bah me ajudou bastante, vlw ae

Fábio Rodrigues de sousa disse...

Boa Tarde eu gostei muito do seu material sobre android só que estou com uma curiosidade tem como eu ler um arquivo em xml atraves do android da mesma forma como voçê ler os arquivos em txt deis de já deixo meu muito obrigado

Amauri Menegalli disse...

Alexandre,
Parabéns pelo tópico.

Preciso obter todos campos ( delimitados por "/" dentro de cada linha.

Ex: 11111/22222/33333

a=11111
b=22222
c=33333

Obrigado!

Lexy Ferrari disse...

Oi, estou com um problema, ao tentar gravar o arquivo na pasta, o logcat me da o seguinte erro:

Error: java.io.FileNotFoundException: /storage/sdcard/teste.txt: open failed: EROFS (Read-only file system)


Mesmo usando a permissao




Socorro T.T