Speed Up React Native File System (RNFS) on Android
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,
- Move the operation to a new thread
- Remove the base64 encoding and decoding operation for the string you want to save (This was the major cause)
All the best.