Flutter: How to Read and Write Text Files

Updated: April 22, 2023 By: A Goodman One comment

This article is about reading and writing text files in Flutter.

Introduction

Text files (which have .txt extension) are widely used to store information persistently, from numerical data to long text. Today, we will walk through 2 examples of Flutter applications that work with this file type.

The first example is quick and simple. It only loads content from a text in the assets folder (or another folder in the root project) using rootBundle (from services.dart) then outputs the result onto the screen. This is useful when you only need to read data and not write data.

The second example is a little bit more complex. It not only read but also write something entered by the user into a text file. You will learn how to use File asynchronous methods including readAsString and writeAsString.

Example 1: Loading content

Preview

This example contains a text widget and a floating button. When this button is pressed, the function _loadData will be triggered and load content from the file.

Add the text file to your project

Create a new text file named data.txt in the assets folder (create one if it doesn’t exist yet) at the root of your project the add some dummy content to it, like this:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In at lacus et mi blandit iaculis sed eget elit. Nulla facilisi. Sed pulvinar erat vel odio pretium, id malesuada tortor sollicitudin.

Don’t forget to register the assets folder in your pubspec.yaml file:

flutter:
  assets:
    - assets/

The full code

Add the following to your main.dart:

// kindacode.com
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'dart:async';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String? _data;

  // This function is triggered when the user presses the floating button
  Future<void> _loadData() async {
    final loadedData = await rootBundle.loadString('assets/data.txt');
    setState(() {
      _data = loadedData;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Kindacode.com'),
      ),
      body: Center(
          child: SizedBox(
              width: 300,
              child: Text(_data ?? 'Nothing to show',
                  style: const TextStyle(fontSize: 24)))),
      floatingActionButton: FloatingActionButton(
          onPressed: _loadData, child: const Icon(Icons.add)),
    );
  }
}

Example 2: Reading and Writing

Getting the file path

For security reasons, Android and iOS do not allow us to read and write anywhere on the hard drive. We need to save our text files to the Documents directory, where the application can only access its own files. These files will only be removed when the app is deleted.

The Documents directory is NSDocumentDirectory on iOS and AppData on Android. To get the full path of this directory, we use the path_provider package (this one is an official package from Flutter).

Install the package by performing the command below:

flutter pub add path_provider

Then run the following command:

flutter pub get

And find the path as shown below:

import 'package:path_provider/path_provider.dart';

/* .... */

Future<String> get _getDirPath async {
  final dir = await getApplicationDocumentsDirectory();
  return dir.path;
}

Example Preview

This example app has a TextFiled that lets the user enter his/her name to write to a text file. It also contains a Text widget that displays the name read from that file.

The full code and explanations

In this example, we don’t need to manually create and add a text file to the project. It will be created automatically when we do writing data for the first time.

Here’s the code in our main.dart:

// KindaCode.com
// main.dart
import 'dart:convert';

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // This will be displayed on the screen
  String? _content;

  // Find the Documents path
  Future<String> _getDirPath() async {
    final dir = await getApplicationDocumentsDirectory();
    return dir.path;
  }

  // This function is triggered when the "Read" button is pressed
  Future<void> _readData() async {
    final dirPath = await _getDirPath();
    final myFile = File('$dirPath/data.txt');
    final data = await myFile.readAsString(encoding: utf8);
    setState(() {
      _content = data;
    });
  }

  // TextField controller
  final _textController = TextEditingController();
  // This function is triggered when the "Write" buttion is pressed
  Future<void> _writeData() async {
    final dirPath = await _getDirPath();

    final myFile = File('$dirPath/data.txt');
    // If data.txt doesn't exist, it will be created automatically

    await myFile.writeAsString(_textController.text);
    _textController.clear();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Kindacode.com'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [
            TextField(
              controller: _textController,
              decoration: const InputDecoration(labelText: 'Enter your name'),
            ),
            ElevatedButton(
              onPressed: _writeData,
              child: const Text('Save to file'),
            ),
            const SizedBox(
              height: 150,
            ),
            Text(_content ?? 'Press the button to load your name',
                style: const TextStyle(fontSize: 24, color: Colors.pink)),
            ElevatedButton(
              onPressed: _readData,
              child: const Text('Read my name from the file'),
            )
          ],
        ),
      ),
    );
  }
}

Conclusion

Through this article, you built 2 simple applications and learned the essentials about reading and writing text files. If you would like to use JSON files, CSV files, Hive database, or SQLite with Flutter, take a look at the following articles:

You can also check out our Flutter topic page or Dart topic page for the latest tutorials and examples.

Subscribe
Notify of
guest
1 Comment
Inline Feedbacks
View all comments
Mike
Mike
3 years ago

I’d like to read from and write to an OTG USB drive using the “serial_usb 0.2.4” package.

Related Articles