Flutter 檔案讀寫---path_provider詳解

Jimi發表於2021-10-14

前言

在我們實際的應用開發過程中,常常會做一些本地持久化資料配置,在應用啟動時可以拿到配置去處理對應的業務邏輯。或者我們下載檔案、下載圖片等都需要通過IO流來實現。

在我們操作檔案的時候我們需要結合dart:io庫中的path_provider,因為每個系統下檔案路徑不同,如果自己去實現會很麻煩,那麼path_provider就此產生。

原始碼及視訊教程地址

github原始碼地址 視訊教程地址

path_provider介紹

path_provider是一個Flutter外掛,主要作用是提供一種以平臺無關一致的方式訪問裝置的檔案系統,比如應用臨時目錄、文件目錄等。而且path_provider支援AndroidiOSLinuxMacOSWindows

path_provider App目錄

app儲存目錄總共分為八種,我們來看一下他們的區別:

臨時目錄

臨時目錄的是系統可以隨時清空的快取資料夾

文件目錄

文件目錄用於儲存只能由該應用訪問的檔案,系統不會清除該目錄,只有在刪除應用時才會消失。

應用程式支援目錄

應用程式支援目錄用於不想向使用者公開的檔案,也就是你不想給使用者看到的檔案可放置在該目錄中,系統不會清除該目錄,只有在刪除應用時才會消失。

應用程式持久檔案目錄

該目錄主要儲存持久檔案的目錄,並且不會對使用者公開,常用於儲存資料庫檔案,比如sqlite.db等。

外部儲存目錄

主要用於獲取外部儲存目錄,如SD卡等,但iOS不支援外部儲存目錄,目前只有Android才支援。

外部儲存快取目錄

主要使用者獲取應用程式特定外部快取資料的目錄,比如從SD卡或者手機上有多個儲存目錄的,但iOS不支援外部儲存目錄,目前只有Android才支援。

外部儲存目錄(單獨分割槽)

可根據型別獲取外部儲存目錄,如SD卡、單獨分割槽等,和外部儲存目錄不同在於他是獲取一個目錄陣列。但iOS不支援外部儲存目錄,目前只有Android才支援。

桌面程式下載目錄

主要用於儲存下載檔案的目錄,只適用於LinuxMacOSWindowsAndroidiOS平臺無法使用。

path_provider方法和說明

方法屬性描述
getTemporaryDirectory()Future<Directory>臨時目錄
getApplicationSupportDirectory()Future<Directory>應用程式支援目錄
getLibraryDirectory()Future<Directory>應用程式持久檔案目錄
getApplicationDocumentsDirectory()Future<Directory>文件目錄
getExternalStorageDirectory()Future<Directory>外部儲存目錄
getExternalCacheDirectories()Future<List<Directory>?>外部儲存快取目錄
getExternalStorageDirectories()Future<List<Directory>?>外部儲存目錄(單獨分割槽)
getDownloadsDirectory()Future<Directory?>桌面程式下載目錄

path_provider基本使用

我們這裡舉一個簡單的例子,通過path_provider獲取磁碟中的路徑,把文字寫入到檔案中,具體步驟如下:

  • 新增依賴
  • 獲取本地目錄
  • 寫入資料到磁碟中
  • 讀取磁碟資料

第一步:新增依賴

environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  path_provider: ^2.0.5

第二步:獲取本地目錄

雖然獲取路徑總共有八種,但是在實際應用開發過程中,我們經常使用的有三種,我們分別來獲取這三種目錄的路徑,如下:

/// 獲取文件目錄檔案
Future<File> _getLocalDocumentFile() async {
  final dir = await getApplicationDocumentsDirectory();
  return File('${dir.path}/str.txt');
}

/// 獲取臨時目錄檔案
Future<File> _getLocalTemporaryFile() async {
  final dir = await getTemporaryDirectory();
  return File('${dir.path}/str.txt');
}

/// 獲取應用程式目錄檔案
Future<File> _getLocalSupportFile() async {
  final dir = await getApplicationSupportDirectory();
  return File('${dir.path}/str.txt');
}

第三步:寫入資料到磁碟中

我們這裡通過writeAsString()來將name值寫入到磁碟中,如果你需要同步寫入可呼叫writeAsStringSync(),或者想通過位元組流的方式寫入可以呼叫writeAsBytes()

String name = "Jimi";

/// 寫入資料
Future<void> writeString(String str) async {
  final file = await _getLocalDocumentFile();
  await file.writeAsString(name);

  final file1 = await _getLocalTemporaryFile();
  await file1.writeAsString(name);

  final file2 = await _getLocalSupportFile();
  await file2.writeAsString(name);
  print("寫入成功");
}

第四步:讀取磁碟資料

這裡加了一個try catch,防止在讀取檔案出現異常導致崩潰,我們分別讀取三個目錄裡面的檔案並對其增加相應的列印。

/// 讀取值
Future<void> readString() async {
  try {

    final file = await _getLocalDocumentFile();
    final result  = await file.readAsString();
    print("result-----$result");

    final file1 = await _getLocalTemporaryFile();
    final result1  = await file1.readAsString();
    print("result1-----$result1");

    final file2 = await _getLocalSupportFile();
    final result2  = await file2.readAsString();
    print("result2-----$result2");

  } catch (e) {
  }
}

完整示例程式碼

import 'dart:io';

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

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

class MyApp extends StatelessWidget {

  String name = "Jimi";

  /// 獲取文件目錄檔案
  Future<File> _getLocalDocumentFile() async {
    final dir = await getApplicationDocumentsDirectory();
    return File('${dir.path}/str.txt');
  }

  /// 獲取臨時目錄檔案
  Future<File> _getLocalTemporaryFile() async {
    final dir = await getTemporaryDirectory();
    return File('${dir.path}/str.txt');
  }

  /// 獲取應用程式目錄檔案
  Future<File> _getLocalSupportFile() async {
    final dir = await getApplicationSupportDirectory();
    return File('${dir.path}/str.txt');
  }

  /// 讀取值
  Future<void> readString() async {
    try {

      final file = await _getLocalDocumentFile();
      final result  = await file.readAsString();
      print("result-----$result");

      final file1 = await _getLocalTemporaryFile();
      final result1  = await file1.readAsString();
      print("result1-----$result1");

      final file2 = await _getLocalSupportFile();
      final result2  = await file2.readAsString();
      print("result2-----$result2");


    } catch (e) {
    }
  }

  /// 寫入資料
  Future<void> writeString(String str) async {
    final file = await _getLocalDocumentFile();
    await file.writeAsString(name);

    final file1 = await _getLocalTemporaryFile();
    await file1.writeAsString(name);

    final file2 = await _getLocalSupportFile();
    await file2.writeAsString(name);
    print("寫入成功");
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(title: Text("path_provider"),),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(name,
                style: TextStyle(
                    color: Colors.pink,
                    fontSize: 30
                ),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: (){
                  writeString(name);
                },
                child: Text("存入本地目錄"),
              ),
              ElevatedButton(
                onPressed: (){
                  readString();
                },
                child: Text("讀取值"),
              ),
            ],
          ),
        ),
      )
    );
  }
}

控制檯輸出

flutter: 寫入成功
flutter: result-----Jimi
flutter: result1-----Jimi
flutter: result2-----Jimi

總結

當我們需要持久化資料或下載檔案、圖片或儲存資料庫檔案我們將檔案寫入到磁碟中,那我們需要藉助dart:io以及path_provider,而path_provider主要作用是提供一種以平臺無關一致的方式訪問裝置的檔案系統,比如應用臨時目錄、文件目錄等。

相關文章