17

My React Native app (on android only) is a basic app that will collect some sensors data when users start recording video. I have three arrays of sensors data: accelerometer, gyroscope, and light. I want to save them to the device as .csv files so I can use them for the next steps. Currently, I can save them in .txt (using react-native-fs, but they do not support .csv extension) but what I want is .csv. Is there any way to do that in React Native?

Data will look like this:

this.accelerometer = [
  {x: 12, y: 15, z: 17},
  {x: 12, y: 15, z: 17},
  ...
  {x: 12, y: 15, z: 17},
]

this.gyroscope = [
  {x: 12, y: 15, z: 17},
  {x: 12, y: 15, z: 17},
  ...
  {x: 12, y: 15, z: 17},
]

this.light = [6, 7, 8, 9, 10,.., 11]

Desired .csv, for example accelerometer.csv:

x ,y ,z
12,15,17
1
  • 1
    Have a look at fs. You can create a string and save it as csv. Afterall, csv is just a string with commas and newlines right? Commented Aug 13, 2017 at 20:11

2 Answers 2

26

You can use react-native-fetch-blob to write to the device's file system. (I was wondering this too!)

We start by converting an array of values to a string. If our values are separated by , commas and our rows are separated by \n newlines, then our string is csv. We can take that string, write it to a file with a .csv file extension, and voila we have a .csv file.

here's code that does just this:

import RNFetchBlob from 'react-native-fetch-blob';

const values = [
  ['build', '2017-11-05T05:40:35.515Z'],
  ['deploy', '2017-11-05T05:42:04.810Z']
];

// construct csvString
const headerString = 'event,timestamp\n';
const rowString = values.map(d => `${d[0]},${d[1]}\n`).join('');
const csvString = `${headerString}${rowString}`;

// write the current list of answers to a local csv file
const pathToWrite = `${RNFetchBlob.fs.dirs.DownloadDir}/data.csv`;
console.log('pathToWrite', pathToWrite);
// pathToWrite /storage/emulated/0/Download/data.csv
RNFetchBlob.fs
  .writeFile(pathToWrite, csvString, 'utf8')
  .then(() => {
    console.log(`wrote file ${pathToWrite}`);
    // wrote file /storage/emulated/0/Download/data.csv
  })
  .catch(error => console.error(error));

this approach worked for me on an Android 7.x test device.

in case it's helpful, I'll also share a link to the equivalent code inside my react-native project

Sign up to request clarification or add additional context in comments.

5 Comments

note that there are many packages for csv encoding, if you want to do fancy things and handle strange edge cases. this time, this simple approach worked for me. npmjs.com/search?q=encode+csv
Probably a little off-topic but is there a way to let the user know that the file got downloaded/created? Kind of like "Downloaded" notification. I do see that we can use .config for .fetch but doesn't seem to appear for .fs. My solution right now has been to use extra notification package and notify on .then but that seems a little un-necessary given how react-native-fetch-blob should have this already.
This was a great help, but if you're on iOS, remember to use DocumentDir instead of DownloadDir (which is Android only). Also, the project has been forked and renamed: npmjs.com/package/rn-fetch-blob
This is a great way to construct the csv data. You can also use react-native-fs to write the file.
Any solution for Expo project?
1

Some other way

    createFile = () => {
    csvString = `${HEADER}`;
    RNFetchBlob.fs
        .writeFile(FILE_PATH, csvString, "utf8")
        .then(() => {
            alert("File created succesfully");
            this.saveData(JSON.stringify([]));
            this.setState({
                users: []
            });
        })
        .catch(error => console.error(error));
};

writeCSV = () => {
    try {

        let rowData = [{
            Name: "ABC",
            MobileNo: 9999999999,
            Age: 23
        }, {
            Name: "DEF",
            MobileNo: 9999999998,
            Age: 24
        }]


        const csvString = `${HEADER}${this.ConvertToCSV(rowData)}`;
        RNFetchBlob.fs
            .writeFile(FILE_PATH, csvString, "utf8")
            .then(() => {
                alert("File updated succesfully");

            })
            .catch(error => alert(error));

    } catch (error) {
        // Error retrieving data
    }
};


ConvertToCSV = objArray => {
    var array = typeof objArray != "object" ? JSON.parse(objArray) : objArray;
    var str = "";

    for (var i = 0; i < array.length; i++) {
        var line = "";
        for (var index in array[i]) {
            if (line != "") line += ",";

            line += array[i][index];
        }

        str += line + "\r\n";
    }

    return str;
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.