Expoexpo-file-systemStorageReact Native

Reading and Writing Files in Expo (expo-file-system Guide)

Save, read, and delete files on device with expo-file-system's new File and Paths API. Learn to cache JSON, persist user data, list directories, and choose document vs cache storage. SDK 54+ examples.

DeveloperMill2 min read

When AsyncStorage isn't enough — you're caching API responses, saving generated files, or handling downloads — you need the file system. expo-file-system gives you direct access to device storage, and SDK 54 introduced a new synchronous File / Paths API that reads like ordinary file code. This guide covers writing, reading, deleting, JSON caching, and directories.

Install

npx expo install expo-file-system

Write and read a text file

The new API models files as objects you create, write, and read:

import { File, Paths } from "expo-file-system"

const file = new File(Paths.document, "notes.txt")

file.create()
file.write("Hello from Expo!")

console.log(file.textSync()) // "Hello from Expo!"

Use file.textSync() for a quick synchronous read, or await file.text() when you'd rather not block.

Document vs cache storage

Choose the right base path:

  • Paths.document — persistent user data (survives restarts, gets backed up).
  • Paths.cache — disposable data the OS may purge when storage is low.
const persistent = new File(Paths.document, "profile.json")
const temporary = new File(Paths.cache, "thumb.jpg")

Cache JSON offline

A tiny offline cache without a database — write stringified JSON, read it back parsed:

import { File, Paths } from "expo-file-system"

const cache = new File(Paths.document, "articles.json")

export function saveArticles(articles: unknown) {
  if (!cache.exists) cache.create()
  cache.write(JSON.stringify(articles))
}

export function loadArticles() {
  if (!cache.exists) return null
  return JSON.parse(cache.textSync())
}

Check, delete, and inspect files

const file = new File(Paths.document, "notes.txt")

console.log(file.exists) // boolean
console.log(file.size)   // bytes

file.delete() // remove it

Work with directories

Create folders and list their contents with the Directory class:

import { Directory, Paths } from "expo-file-system"

const dir = new Directory(Paths.document, "downloads")
if (!dir.exists) dir.create()

for (const entry of dir.list()) {
  console.log(entry.name) // files and subdirectories
}

Gotchas

  • Call create() before write() on a new file, or guard with if (!file.exists).
  • Don't hardcode paths — always build from Paths.document / Paths.cache, since the sandbox location differs per install and platform.
  • For tiny key/value data (flags, IDs), AsyncStorage is simpler; for secrets, use expo-secure-store.

Next steps

Storing lots of structured, queryable data? Move up to expo-sqlite. Saving files users picked or captured? See the expo-image-picker guide. Full list: top 10 Expo SDK modules.

Frequently asked questions

How do I read and write a file in Expo?

Use the new File API from expo-file-system: `const file = new File(Paths.document, 'name.txt')`, then `file.create()` and `file.write('...')` to save, and `file.textSync()` (or `await file.text()`) to read it back.

What's the difference between the document and cache directories?

Files in `Paths.document` persist until your app deletes them and are backed up — use it for user data. Files in `Paths.cache` can be cleared by the OS when storage runs low — use it for regenerable data like downloaded thumbnails.

How do I store JSON data with expo-file-system?

Write with `file.write(JSON.stringify(data))` and read with `JSON.parse(file.textSync())`. This is a simple way to cache API responses offline without a database.

Build it faster with a template

Production-ready Expo React Native templates with the patterns from this post already wired up.

Browse templates