fbpixel
Etiquetas:
0
(0)

Vamos criar um aplicativo React Native que permite ler ou gravar um arquivo em um espaço de armazenamento interno ou externo. Ter acesso ao arquivo do sistema pode ser útil para salvar dados de uma sessão do aplicativo para outra, ou para usar ou modificar os dados em um arquivo.

Hardware

  • Dispositivo Android
  • Computador para programação
  • Um cabo USB para ligar o dispositivo Android ao PC

Configurar o projeto React Native

Para ler e escrever num ficheiro, vamos utilizar a biblioteca do Sistema de Ficheiros, react-native-fs

npm install --save react-native-fs

Utilizar uma biblioteca

A partir da biblioteca, importamos os objectos e funções que nos interessam

import { DocumentDirectoryPath, writeFile, readDir, readFile, unlink } from 'react-native-fs'; //send files for testing
  • DocumentDirectoryPath é utilizado para obter o caminho para os ficheiros da aplicação
  • writeFile permite-lhe escrever para um ficheiro
  • readDir lê um diretório
  • readFile lê um ficheiro
  • unkink apaga um ficheiro

Em seguida, criamos um componente funcional com os estados desejados

const FileSysComp = () =>  {
  const [dirPath, setDirPath] = useState(DocumentDirectoryPath);
  const [filename, setFilename] = useState("myfile.txt");
  const [textToWrite, setTextToWrite] = useState("");
  const [textFromFile, setTextFromFile] = useState("");
  const [fileInDir, setFileInDir] = useState([]);

Em seguida, adicionamos as funções úteis para o sistema de ficheiros read, write, delete

	const makeFile = async (filePath : string, content : string) => {
	  try {
		  //create a file at filePath. Write the content data to it
		  await writeFile(filePath, content, "utf8");
		  console.log("written to file");
	  } catch (error) { //if the function throws an error, log it out.
		  console.log(error);
	  }
	};

	const getFile = async (filePath : string) => {
	  try{
		  const response = await readFile(filePath);
		  setTextFromFile(response)
		  console.log("File read : ",response)
	  } catch (error) {
		  console.log(error);
	  }
	};

  const deleteFile = async (filePath : string) => {
    try {
      await unlink(filePath); //delete the item present at 'path'
      console.log("deleted : ",filePath);
    } catch (error) {
      console.log(error);
    }
  };

Quando o componente é criado, lemos o diretório predefinido

  useEffect(() => {
    /* file system*/
    console.log("FS directory path : ",dirPath);
    readDir(dirPath).then((files) => {
      console.log("files on FS: ",files);
      setFileInDir(files);
    });
  }, [filename,dirPath]);

Por fim, criamos a renderização da aplicação com os seguintes elementos

  • barra de entrada para especificar o diretório
  • barra de entrada para especificar o nome do ficheiro
  • zona de texto para o texto a escrever
  • Botão Escrever para escrever o texto no ficheiro
  • caixa de texto para mostrar os ficheiros e subdirectórios contidos no diretório
  • Botão Ler para ler o texto contido no ficheiro
  • zona de texto para visualizar o texto lido
  • Botão Apagar para apagar o ficheiro especificado
  return (
    <View style={styles.mainBody}>
      <Text
        style={styles.mainTitle}>
        AC File System
      </Text>


      <View style={styles.inputBar}>
        <TextInput
          style={styles.textInput}
          placeholder="Directory"
          value={dirPath}
          onChangeText={setDirPath} />
      </View>
      <View style={styles.inputBar}>
        <TextInput
          style={styles.textInput}
          placeholder="Filename"
          value={filename}
          onChangeText={setFilename} />
      </View>

      <View
        style={styles.inputBar}>
        <TextInput
          style={styles.textInput}
          placeholder="Text to write"
          value={textToWrite}
          onChangeText={setTextToWrite} />
        <TouchableOpacity
          onPress={() => makeFile(dirPath + "/" + filename, textToWrite)}
        style={[styles.sendButton]}>
        <Text
          style={styles.buttonText}>
          WRITE
        </Text>
      </TouchableOpacity>
    </View>
    
    
        <Text>Directory:</Text>

        <ScrollView style={styles.textOutput}>
          {fileInDir.length>0 ? fileInDir.map((filedir, idx) => (
            <Text key={idx}>{filedir.name}</Text>
          )) : <Text>Folder empty or unknown</Text>}
        </ScrollView>


        <View style={{ flexDirection: 'row', justifyContent:'space-between'}}>
          <Text>Text from file:</Text>
          <TouchableOpacity
            onPress={() => getFile(dirPath + "/" + filename)}
            style={[styles.sendButton]}>
            <Text
              style={styles.buttonText}>
              READ
            </Text>
          </TouchableOpacity>
        </View>
        <ScrollView style={styles.textOutput}>
          {textFromFile ? <Text>{textFromFile}</Text> : null}
        </ScrollView>


        <TouchableOpacity
            onPress={() => deleteFile(dirPath + "/" + filename)}
            style={[styles.sendButton]}>
            <Text
              style={styles.buttonText}>
              DELETE
            </Text>
          </TouchableOpacity>

      
    </View>
  );

Resultados

Com esta aplicação, podemos visualizar o conteúdo de um diretório e ler, escrever e apagar um ficheiro.

Ler e escrever um ficheiro num espaço de armazenamento externo

Por defeito, uma aplicação só tem autoridade sobre o seu próprio diretório

É possível atribuir direitos de acesso a um espaço de armazenamento externo, como uma chave USB.

Para tal, pode conceder direitos a partir da interface Android. Vá a Definições > Aplicações e notificações > Gestor de permissões > Ficheiros e conteúdos multimédia

Ligue a pen USB ao seu dispositivo, utilizando o adb para encontrar o caminho para o espaço de armazenamento em ls /storage/ (ex /storage/70A8-C229)

Uma vez activada a autorização, poderá visualizar e criar ficheiros na pen USB.

Código de gestão de ficheiros completo com React Native

/**
 * https://www.npmjs.com/package/react-native-fs?activeTab=readme
 * https://github.com/itinance/react-native-fs
 */

import React, {useState, useEffect, useCallback} from 'react';
import {   
  View, 
  ScrollView, 
  Text,
  TextInput,
  TouchableOpacity, 
  StyleSheet,
  Alert} from 'react-native';
import { DocumentDirectoryPath, writeFile, readDir, readFile, unlink } from 'react-native-fs'; //send files for testing

let storagePath = "/storage/70A8-C229"

/**
 * Maincomp
 */
const FileSysComp = () =>  {
  const [dirPath, setDirPath] = useState(storagePath) //DocumentDirectoryPath);
  const [filename, setFilename] = useState("myfile.txt");
  const [textToWrite, setTextToWrite] = useState("");
  const [textFromFile, setTextFromFile] = useState("");
  const [fileInDir, setFileInDir] = useState([]);

	const makeFile = async (filePath : string, content : string) => {
	  try {
		  //create a file at filePath. Write the content data to it
		  await writeFile(filePath, content, "utf8");
		  console.log("written to file");
	  } catch (error) { //if the function throws an error, log it out.
		  console.log(error);
      Alert.alert("Cannot write file. Permission denied")
	  }
	};

	const getFile = async (filePath : string) => {
	  try{
		  const response = await readFile(filePath);
		  setTextFromFile(response)
		  console.log("File read : ",response)
	  } catch (error) {
		  console.log(error);
	  }
	};

  const deleteFile = async (filePath : string) => {
    try {
      await unlink(filePath); //delete the item present at 'path'
      console.log("deleted : ",filePath);
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    /* file system*/
    console.log("FS directory path : ",dirPath);
    readDir(dirPath).then((files) => {
      console.log("files on FS: ",files);
      setFileInDir(files);
    }).catch((e) =>{
      console.log("foler does not exist");
      setFileInDir([])
    });
  }, [filename,dirPath]);

  return (
    <View style={styles.mainBody}>
      <Text
        style={styles.mainTitle}>
        AC File System
      </Text>

      <View style={styles.inputBar}>
        <TextInput
          style={styles.textInput}
          placeholder="Directory"
          value={dirPath}
          onChangeText={setDirPath} />
      </View>
      <View style={styles.inputBar}>
        <TextInput
          style={styles.textInput}
          placeholder="Filename"
          value={filename}
          onChangeText={setFilename} />
      </View>

      <View
        style={styles.inputBar}>
        <TextInput
          style={styles.textInput}
          placeholder="Text to write"
          value={textToWrite}
          onChangeText={setTextToWrite} />
        <TouchableOpacity
          onPress={() => makeFile(dirPath + "/" + filename, textToWrite)}
        style={[styles.sendButton]}>
        <Text
          style={styles.buttonText}>
          WRITE
        </Text>
      </TouchableOpacity>
    </View>
    
    
        <Text>Directory:</Text>

        <ScrollView style={styles.textOutput}>
          {fileInDir.length>0 ? fileInDir.map((filedir, idx) => (
            <Text key={idx}>{filedir.name}</Text>
          )) : <Text>Folder empty or unknown</Text>}
        </ScrollView>


        <View style={{ flexDirection: 'row', justifyContent:'space-between'}}>
          <Text>Text from file:</Text>
          <TouchableOpacity
            onPress={() => getFile(dirPath + "/" + filename)}
            style={[styles.sendButton]}>
            <Text
              style={styles.buttonText}>
              READ
            </Text>
          </TouchableOpacity>
        </View>
        <ScrollView style={styles.textOutput}>
          {textFromFile ? <Text>{textFromFile}</Text> : null}
        </ScrollView>


        <TouchableOpacity
            onPress={() => deleteFile(dirPath + "/" + filename)}
            style={[styles.sendButton]}>
            <Text
              style={styles.buttonText}>
              DELETE
            </Text>
          </TouchableOpacity>

    </View>
  );
}

export default FileSysComp;


let BACKGROUND_COLOR = "#161616"; //191A19
let BUTTON_COLOR = "#346751"; //1E5128
let ERROR_COLOR = "#C84B31"; //4E9F3D
let TEXT_COLOR = "#ECDBBA"; //D8E9A8
var styles = StyleSheet.create({

  mainBody: { flex: 1, justifyContent: 'center',  backgroundColor: BACKGROUND_COLOR},

  mainTitle:{
    color: TEXT_COLOR,
    fontSize: 30,
    textAlign: 'center',
    borderBottomWidth: 2,
    borderBottomColor: ERROR_COLOR,
  },

  backgroundVideo: {
    borderWidth: 2,
    borderColor: 'red',
    position: 'absolute',
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  },

  webVideo: {
    borderWidth: 2,
    borderColor: 'green',
    position: 'absolute',
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  },

  buttonText: {
    color: TEXT_COLOR,
    fontWeight: 'bold',
    fontSize: 12,
	  textAlign: 'center',
    textAlignVertical: 'center',
  },

  sendButton: {
    backgroundColor: BUTTON_COLOR,
    padding: 15,
    borderRadius: 15,
    margin: 2,
    paddingHorizontal: 20,
    right:0,
    },

    deviceItem: {
      flexDirection: 'row',
      flex: 3,
      marginBottom: 2,
    },
    deviceName: {
      fontSize: 14,
      fontWeight: 'bold',
    },
    deviceInfo: {
      fontSize: 8,
    },
    deviceButton: {
      backgroundColor: '#2196F3',
      padding: 10,
      borderRadius: 10,
      margin: 2,
      paddingHorizontal: 20,
    },

  inputBar:{
    flexDirection: 'row',
    justifyContent: 'space-between',
    margin: 5,
  },  

  textInput:{
    backgroundColor: '#888888',
    margin: 2,
    borderRadius: 15,
    flex:3,
  },

  textOutput:{
    backgroundColor: '#333333',
    margin: 10,
    borderRadius: 2,
    borderWidth: 1,
    borderColor: '#EEEEEE',
    textAlignVertical: 'top',
    minHeight : 50,
  }

});

Fontes

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?