Codementor Events

Speed Up React Native File System (RNFS) on Android

Published Jan 22, 2019

Start writingI had the displeasure of reading and writing a relatively large string to disk using RNFS on a React Native app. It took about 16 seconds to write to a file and 20 seconds to read from the file. I didn’t get enough answers online so I tinkered with the source code.

It boils down to changing the methods in the file

node-modules/react-native-fs/android/source/main/java/com/rnfs/RNFSManager.java

From here...

@ReactMethod
public void readFile(String filepath, Promise promise) {
  try {
    File file = new File(filepath);

    if (file.isDirectory()) {
      rejectFileIsDirectory(promise);
      return;
    }

    if (!file.exists()) {
      rejectFileNotFound(promise, filepath);
      return;
    }

    FileInputStream inputStream = new FileInputStream(filepath);
    byte[] buffer = new byte[(int)file.length()];
    inputStream.read(buffer);

    String base64Content = Base64.encodeToString(buffer, Base64.NO_WRAP);

    promise.resolve(base64Content);
  } catch (Exception ex) {
    ex.printStackTrace();
    reject(promise, filepath, ex);
  }
}

To

@ReactMethod
public void readFile(final String filepath, final Promise promise) {
  new Thread(new Runnable() {
    public void run() {
      try {
        File file = new File(filepath);

        if (file.isDirectory()) {
          rejectFileIsDirectory(promise);
          return;
        }

        if (!file.exists()) {
          rejectFileNotFound(promise, filepath);
          return;
        }

        FileInputStream inputStream = new FileInputStream(filepath);
        byte[] buffer = new byte[(int)file.length()];
        inputStream.read(buffer);
        String str = new String(buffer, "UTF-8");
        promise.resolve(str);
      } catch (Exception ex) {
        ex.printStackTrace();
        reject(promise, filepath, ex);
      }
    }
  }).start();
}

To write to a file, I changed

@ReactMethod
public void writeFile(String filepath, String base64Content, Promise promise) {
  try {
        byte[] bytes = Base64.decode(base64Content, Base64.DEFAULT);
        FileOutputStream outputStream = new FileOutputStream(filepath);
        outputStream.write(bytes);
        outputStream.close();
        promise.resolve(null);
      } catch (Exception ex) {
        ex.printStackTrace();
        reject(promise, filepath, ex);
      }
}

To

@ReactMethod
public void writeFile(final String filepath, final String base64Content, final Promise promise) {
  new Thread(new Runnable() {
    public void run() {
      try {
        byte[] bytes = base64Content.getBytes();
        FileOutputStream outputStream = new FileOutputStream(filepath);
        outputStream.write(bytes);
        outputStream.close();

        promise.resolve(null);
      } catch (Exception ex) {
        ex.printStackTrace();
        reject(promise, filepath, ex);
      }
    }
  }).start();
}

In summary,

  1. Move the operation to a new thread
  2. Remove the base64 encoding and decoding operation for the string you want to save (This was the major cause)

All the best.

Discover and read more posts from Daniel Oduonye
get started