Flutter笔记:目录与文件存储以及在Flutter中的使用(上)

Flutter笔记
目录与文件存储以及在Flutter中的使用(上)
文件系统基础知识与路径操作

作者李俊才 (jcLee95):https://blog.csdn.net/qq_28550263
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/134499297


【简介】本文探讨了Dart和Flutter中的文件系统操作和文件存储。内容覆盖了Dart的文件系统基础,文件路径处理,文件读写操作及其优化(上),以及在Flutter中的文件读写相关注意的事项(下)。

下一节:《 目录与文件存储以及在Flutter中的使用(下)


1. 概述

本文主要介绍了Dart和Flutter中的文件系统操作和文件存储。首先,我们将探讨Dart中的文件系统基础,包括文件、目录和链接的基本概念及其操作方法。然后,我们将学习如何在Dart中处理文件路径,以及如何进行文件的读写操作。接着,我们将讨论如何在Flutter中进行文件存储,包括如何使用path_provider库来获取应用的文件存储路径,以及如何读写特殊类型的文件。最后,我们将探讨文件读写的性能优化。希望通过本文,你能够对Dart和Flutter中的文件操作有一个全面的了解。

2. Dart文件系统基础

本小节将介绍文件的基本概念、操作方法以及错误处理和异常捕获。

2.1 文件(File)

本小节包括3个子小节,讲解文件的基本概念、操作方法以及错误处理和异常捕获。

2.1.1 文件的概念

文件是存储在磁盘上的数据的集合,可以包含任何类型的数据,如文本、图片、音频等。文件是计算机中用于数据存储的基本单位,它可以包含各种类型的数据,如程序代码、文本文档、图片、音频和视频等。

Dart 中,我们可以使用 dart:io 库中的 File 类来操作文件。File类提供了一系列的方法,如 readAsStringwriteAsStringreadAsByteswriteAsBytes 等,用于读取和写入文件。这些方法都是异步的,因此在使用它们时,我们需要使用await关键词来等待操作完成。

以下是一个简单的示例,演示如何使用 File 类来创建一个新文件,并向其中写入一些文本:

在这个示例中,我们首先导入了 dart:io 库,然后创建了一个File对象,表示一个名为’test.txt’的文件。然后,我们使用 writeAsString 方法向文件中写入了一些文本。由于 writeAsString 方法是异步的,我们需要使用 await 关键词来等待操作完成。

import 'dart:io';void main() async {var file = File('test.txt');await file.writeAsString('Hello, Dart!');
}

注意,由于我们在 main 函数中使用了 await 关键词,因此我们需要将 main 函数声明为异步函数,即在函数声明前添加 async 关键词。

2.1.2 文件的操作

Dart 中,我们可以使用 File 类的各种方法来操作文件,包括创建、读取、写入和删除等操作。

以下是一些常用的文件操作方法的示例:

  1. 创建文件:使用 create 方法可以创建一个新的文件。如果文件已经存在,create 方法不会有任何效果。如果你希望覆盖已经存在的文件,可以给 create 方法传入一个名为 recursive 的参数,将其设为 true
import 'dart:io';void main() async {var file = File('test.txt');await file.create();
}
  1. 读取文件:使用 readAsString 方法可以读取文件的内容,返回一个字符串。如果文件不存在,readAsString 方法会抛出一个异常。
import 'dart:io';void main() async {var file = File('test.txt');String contents = await file.readAsString();print(contents);
}
  1. 写入文件:使用 writeAsString 方法可以向文件中写入字符串。如果文件不存在,writeAsString 方法会创建一个新的文件。如果文件已经存在,writeAsString 方法会覆盖文件的内容。
import 'dart:io';void main() async {var file = File('test.txt');await file.writeAsString('Hello, Dart!');
}
  1. 删除文件:使用 delete 方法可以删除一个文件。如果文件不存在,delete 方法不会有任何效果。
import 'dart:io';void main() async {var file = File('test.txt');await file.delete();
}

在实际使用中,你可能还需要处理各种可能出现的错误和异常,例如文件不存在、没有权限等。这些内容将在后续小节中讲解。

2.1.3 错误处理和异常捕获

在进行文件操作时,可能会出现各种错误和异常,例如文件不存在、没有读写权限等。在 Dart 中,我们可以使用 try-catch 语句来捕获和处理这些错误和异常。

以下是一些常见的错误处理和异常捕获的示例:

  1. 文件不存在:当我们试图读取或删除一个不存在的文件时,Dart会抛出一个 FileSystemException 异常。我们可以捕获这个异常,然后进行相应的处理,例如创建一个新的文件或者给用户显示一个错误消息。
import 'dart:io';void main() async {var file = File('test.txt');try {String contents = await file.readAsString();print(contents);} catch (e) {print('Error: $e');}
}

在这个示例中,如果 ‘test.txt’ 文件不存在,readAsString方法会抛出一个 FileSystemException 异常,然后我们在catch语句中捕获这个异常,并打印一个错误消息。

  1. 没有读写权限:当我们试图读取或写入一个我们没有权限访问的文件时,Dart 也会抛出一个 FileSystemException 异常。我们可以捕获这个异常,然后进行相应的处理,例如请求用户提供权限或者给用户显示一个错误消息。
import 'dart:io';void main() async {var file = File('/root/test.txt');try {await file.writeAsString('Hello, Dart!');} catch (e) {print('Error: $e');}
}

在这个示例中,如果我们没有权限写入 ‘/root/test.txt’ 文件,writeAsString 方法会抛出一个 FileSystemException 异常,然后我们在 catch 语句中捕获这个异常,并打印一个错误消息。

在实际使用中,可能还需要处理其他类型的错误和异常,例如磁盘空间不足等。处理这些错误和异常的方法和上述示例类似,关键是要正确地识别错误类型,然后进行相应的处理。

2.2 目录(Directory)

本小节将介绍目录的基本概念及其在Dart中的操作方法。

2.2.1 目录的概念

目录是文件的容器,可以包含文件和其他目录。在文件系统中,目录用于组织文件,使得我们可以更方便地管理和访问文件。一个目录可以包含任意数量的文件和子目录。

Dart 中,我们可以使用dart:io库中的 Directory 类来操作目录。Directory 类提供了一系列的方法,如create、list、delete等,用于创建、列出和删除目录。这些方法都是异步的,因此在使用它们时,我们需要使用await关键词来等待操作完成。

以下是一个简单的示例,演示如何使用Directory类来创建一个新目录:

import 'dart:io';void main() async {var directory = Directory('test');await directory.create();
}

在这个示例中,我们首先导入了dart:io库,然后创建了一个 Directory 对象,表示一个名为 ‘test’ 的目录。然后,我们使用 create 方法创建了这个目录。由于 create 方法是异步的,我们需要使用 await 关键词来等待操作完成。

注意,由于我们在 main 函数中使用了 await 关键词,因此我们需要将 main 函数声明为异步函数,即在函数声明前添加 async 关键词。

2.2.2 目录的操作

Dart 中,我们可以使用 Directory 类的各种方法来操作目录,包括创建、列出内容和删除等操作。

以下是一些常用的目录操作方法的示例:

创建目录

使用 create 方法可以创建一个新的目录。如果目录已经存在,create 方法不会有任何效果。如果你希望创建的目录的父目录不存在,可以给 create 方法传入一个名为 recursive 的参数,将其设为 true

import 'dart:io';void main() async {var directory = Directory('test');await directory.create();
}
列出目录内容

使用list方法可以列出目录的内容,包括文件和子目录。list 方法返回一个 Stream 对象,我们可以使用 await for 语句来遍历这个 Stream

import 'dart:io';void main() async {var directory = Directory('test');await for (var entity in directory.list()) {print(entity.path);}
}

注:
await for 是一种特殊的循环结构,用于处理异步流。 await for 循环会订阅 提供的流,并等待流生成新的值。
每当流生成新的值,循环体就会使用这个值进行一次迭代。当流关闭时,循环就会结束。

删除目录

使用 delete 方法可以删除一个目录。如果目录不存在,delete 方法不会有任何效果。如果你希望删除的目录包含文件或子目录,可以给 delete 方法传入一个名为 recursive 的参数,将其设为true。

import 'dart:io';void main() async {var directory = Directory('test');await directory.delete();
}

在实际使用中,你可能还需要处理各种可能出现的错误和异常,例如目录不存在、没有权限等。这些内容将在后续的章节中讲解。

2.2.3 一个注意点:关于目录的字符串表示

如果你正在使用的是 Windows 系统,并且上面的代提示一些路径方面的错误,那么或许本小节可以帮助到你。

假设你有一个目录为 D:\SOFTWARES\postgresql(Windows系统上),现在你想输出该目录中所有的文件,如果直接使用这段字符串,那就是:

// 错误示例
import 'dart:io';void main() async {var directory = Directory('D:\SOFTWARES\postgresql');await for (var entity in directory.list()) {print(entity.path);}
}

这是一个错误的写法。因为在 Dart 中,字符串中的反斜杠 \ 是一个特殊字符,用于引入转义序列,因此你需要使用两个反斜杠 \\,那么就是:

var directory = Directory('D:\\SOFTWARES\\postgresql');

但是如果你觉得这样太麻烦了,不想再后动为你复制过来的 Windows 系统上的位置添加这么多的 \ 进行转移,那么就应该使用 原始字符串 (raw string)来避免处理转义字符。

原始字符串以 r 开头,如 r"Hello\nWorld"。在原始字符串中,\ 字符没有特殊含义,所以你可以直接使用 \ 而不是 \\。因此,下面的写法也是正确的:

var directory = Directory(r'D:\SOFTWARES\postgresql');

哦,似乎你知道 Python 等一些语言也是这样的。那就用起来吧。

2.3 链接(Link)

本小节将介绍链接的基本概念以及在Dart中如何操作链接。

2.3.1 链接的概念

链接是指向另一个文件或目录的引用。在文件系统中,链接可以使我们在不复制文件内容的情况下,从不同的位置访问同一个文件。这对于节省存储空间和提高数据管理的效率非常有用。链接可以分为两种类型:硬链接软链接(也被称为 符号链接)。

2.3.2 硬链接 和 软链接

在以前写的另外一篇文章中关于链接有更加详细的介绍,包括如何直接通过命令创建链接 《链接、包管理工具、polyrepo、monorepo以及Lerna 工具的使用》,地址为 https://jclee95.blog.csdn.net/article/details/129903902。感兴趣的读者可以参考。

硬链接和软链接是两种不同类型的链接,它们的主要区别在于指向文件的方式不同。

1. 硬链接

硬链接 是指向文件的物理位置的引用。换句话说,硬链接和它所指向的文件在文件系统中是等价的,它们共享同一块存储空间。这意味着,如果你删除了硬链接,它所指向的文件仍然存在;如果你修改了硬链接的内容,它所指向的文件的内容也会被修改。

2. 软链接

软链接(也称为 符号链接symlink)是指向另一个链接或文件的路径的引用。软链接和它所指向的文件在文件系统中是独立的,它们不共享存储空间。这意味着,如果你删除了软链接,它所指向的文件不会受到影响;如果你修改了软链接的内容,它所指向的文件的内容不会被修改。

在大多数情况下,我们都会使用软链接,因为它更加灵活和方便。然而,在某些情况下,硬链接可能会更有用。例如,如果你希望在不增加存储空间的情况下,从不同的位置访问同一个文件,你可以使用硬链接。

在下一节中,我们将讨论如何在 Dart 中操作链接。

2.3.3 链接的操作

Dart 中,我们可以使用Link类的各种方法来操作链接,如 createdelete 等。

创建链接

使用 create 方法可以创建一个新的链接。如果链接已经存在,create方法会覆盖已经存在的链接。

import 'dart:io';void main() async {var link = Link('link');await link.create('test.txt');
}

在这个示例中,我们创建了一个新的链接,该链接指向名为 ‘test.txt’ 的文件。

获取链接的目标

使用 target 方法可以获取链接的目标。

import 'dart:io';void main() async {var link = Link('link');String target = await link.target();print(target);
}

在这个示例中,我们获取了链接的目标,并将其打印出来。

更新链接的目标

使用update方法可以更新链接的目标。

import 'dart:io';void main() async {var link = Link('link');await link.update('new_target.txt');
}

在这个示例中,我们更新了链接的目标,将其指向名为 ‘new_target.txt’ 的文件。

删除链接

使用 delete 方法可以删除一个链接。如果链接不存在,delete 方法不会有任何效果。

import 'dart:io';void main() async {var link = Link('link');await link.delete();
}

在这个示例中,我们删除了链接。

3. Dart文件路径操作

3.1 路径的概念

路径是文件或目录在文件系统中的位置。它是一个字符串,由一系列的名称组成,这些名称代表从文件系统的根目录到文件或目录的路径。在路径中,名称之间通常由特殊的字符(如斜杠/或反斜杠\)分隔。

例如,路径 /home/user/documents/report.txt 表示在 home 目录下的 user 目录下的 documents 目录下的 report.txt 文件。

Dart 中,我们可以使用字符串来表示路径。例如,我们可以创建一个表示文件路径的字符串,然后使用这个字符串来创建一个 File 对象:

import 'dart:io';void main() {var path = '/home/user/documents/report.txt';var file = File(path);
}

在这个示例中,我们首先创建了一个表示文件路径的字符串,然后使用这个字符串来创建了一个File对象。

【注意】不同的操作系统可能使用不同的字符来分隔路径中的名称。
例如,UnixLinux 系统使用斜杠/,而 Windows 系统使用反斜杠\
为了编写可移植的代码,我们应该尽可能避免直接在代码中使用这些特殊字符,而是使用 Dart 提供的路径操作函数,如join。这些函数可以正确地处理不同操作系统的路径分隔符。

3.3 路径的操作

Dart 中,我们可以使用 path 库中的各种函数来操作路径。这个库提供了一系列的函数,用于连接路径、获取路径的基名、分割路径等。

3.3.1 连接路径(join)

join 函数可以连接两个或多个路径。它会自动处理路径中的分隔符,使得你的代码可以在不同的操作系统上正确运行。

import 'package:path/path.dart' as path;void main() {var p = path.join('/home/user', 'documents', 'report.txt');print(p);  // Outputs: /home/user/documents/report.txt
}

3.3.2 获取路径的基名(basename)

basename 函数可以获取路径的基名,即路径的最后一部分。

import 'package:path/path.dart' as path;void main() {var name = path.basename('/home/user/documents/report.txt');print(name);  // Outputs: report.txt
}

3.3.3 分割路径(split)

split函数可以分割路径,将路径分解为它的各个部分。

import 'package:path/path.dart' as path;void main() {var parts = path.split('/home/user/documents/report.txt');print(parts);  // Outputs: ['/', 'home', 'user', 'documents', 'report.txt']
}

3.3.4 获取路径的目录名(dirname)

dirname 函数可以获取路径的目录名,即除去最后一部分的路径。

import 'package:path/path.dart' as path;void main() {var dir = path.dirname('/home/user/documents/report.txt');print(dir);  // Outputs: /home/user/documents
}

3.3.5 获取路径的扩展名(extension)

extension函数可以获取路径的扩展名,即最后一部分中的点(.)之后的部分。

import 'package:path/path.dart' as path;void main() {var ext = path.extension('/home/user/documents/report.txt');print(ext);  // Outputs: .txt
}

3.3.6 判断路径是否为绝对路径(isAbsolute)

isAbsolute 函数可以判断路径是否为绝对路径。绝对路径是从文件系统的根目录开始的路径,而相对路径是从当前目录开始的路径。

import 'package:path/path.dart' as path;void main() {var isAbs = path.isAbsolute('/home/user/documents/report.txt');print(isAbs);  // Outputs: true
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/150865.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Navicat DML 操作

在表格种插入 列信息 -- 修改数据 update 表名 set 列名 值1, 列名值2,[where 条件]; -- 注意:如果update语句没有加where 表里对应行的全部信息都会被改; -- 删除数据 delecte from 表名 [where 条件]; 未删除前: 执行删除后为: DQL - 条…

全志XR806基于http的无线ota功能实验

XR806不仅硬件功能多,XR806也提供了功能极其丰富的SDK,几天体验下来非常容易上手。常见的功能几乎都有相应的cmd或demo实现,HAL也做得非常全面,非常适合快速开发。这一点超级好评!本文章要实现的无线OTA也基于该SDK。 …

【已解决】移动号码在移动网上营业厅更换为8元保号套餐

有很多人的副卡基本是为了接收银行卡短信,平时基本不打电话和用流量,每个月固定消费在18-30左右,很浪费。今天发现在网上营业厅就可以修改8元保号套餐,分享给大家。 保号套餐 有以下两种: 解决办法: 1、…

1688API接口接入|阿里1688-B类电商基础链路专业化体验升级

新挑战,新契机! 当下整个互联网的竞争环境的变化为我们带来新的机遇和挑战。1688作为连接中小生产商、贸易商和零售商的源头货源首选平台,持续不断地为B类买家提供更专业的服务和更优质的源头厂货供给,打造核心竞争力。 面对新的…

客户端性能优化实践

背景 双十一大促时,客户客服那边反馈商品信息加载卡顿,在不断有订单咨询时,甚至出现了商品信息一直处于加载状态的情况,显然,在这种高峰期接待客户时,是没法进行正常的接待工作的。 起初,页面一…

程序员请放下你的技术情节,与你的同伴一起进步关心业务

如果说掌握一门赖以生计的技术是技术人员要学会的第一课的话, 那么我觉得技术人员要真正学会的第二课,不是技术,而是业务、交流与协作,学会关心其他工作伙伴的工作情况和进展。 为什么这么说呢? 因为技术人员太容易陷…

计算机视觉与机器学习D1

计算机视觉简介 技术背景 了解人工智能方向、热点 目前人工智能的技术方向有: 1、计算机视觉——计算机视觉(CV)是指机器感知环境的能力;这一技术类别中的经典任务有图像形成、图像处理、图像提取和图像的三维推理。物体检测和人脸识别是其比较成功…

apache 基线安全加固操作

本文档适用于Apache服务器。本规范明确了Apache服务器安全配置方面的基本要求。 账号管理、认证授权 ELK-Apache-01-01-01 编号 ELK-Apache-01-01-01 名称 以特定用户运行服务 实施目的 以特定用户运行服务,不要使用系统管理员账号启动APACHE 问题影响 越权使用造成非…

Kotlin--1.基础语法

目录 一.概念 二.基本语法 1.入门案例 2.变量声明 3.数据类型 4.字符串 (1)访问字符串 (2)字符串长度 (3)字符串函数 (4)比较字符串 (5)在字符串中查找字符串 (6)字符串模板 5.if-else 6.when 7.数组 8.范围 三.函数 1.实例 2.多个参数 3.返回值 一.概念 Kot…

客服中心的客户关系管理核心功能

根据国外的调查,拥有客服中心的运营机构,可以保持85%左右的客户忠诚度,而接受过专业培训的客户中心可以将客户忠诚度提高到99%。客服中心作为客户关系管理的前沿,通过提供服务、实时沟通、搜集与分析客户信息、预测客户需求来提升…

数据结构与算法-生成树与最小生成树

生成树与最小生成树 🎈1.生成树与最小生成树🔭1.1生成树与最小生成树的概念🔭1.2最小生成树的生成准则🔭1.3两种最小生成树算法🏆1.3.1Kruskal算法🏆1.3.2Prim算法 🎈2.有向无环图及其应用&…

【如何学习Python自动化测试】—— 时间等待

3 、 时间等待 在做自动化测试时,难免会碰到一些问题,比如你在脚本中操作某个对象时, 页面还没有加载出来,你的操作语句已经被执行,从而导致脚本执行失败,针对这样的问题 webdriver 提供了等待操作&#xf…

virtuoso 后仿 ADE L error

ADE后仿时出现error ERROR (SFE-23): "input.scs" 299: The instance _57_D32_noxref is referencing an undefined model or subcircuit, parasitic_nwd. Either include the file containing the definition of parasitic_nwd, or define parasitic_nwd before run…

Java MVC亚马逊网站的仿制JSP+JavaBean+Servlet+DB

系统总体要求 1. 网站中必须包含用户登录,查看产品列表,增加产品信息,修改产品信息,和查看产品详细信息的功能;对于列表页面,要求要实现分页功能,产品数目不少于20条,每页8条记录 2…

Redis学习笔记15:基于spring data redis及lua脚本发送到redis服务器多久过期

在Redis服务器中,通过SCRIPT LOAD命令加载的脚本会被缓存,并且会一直保存在缓存中,直到服务器重启或者使用SCRIPT FLUSH名利手动清空缓存。 一个对springboot redis框架进行重写,支持lettuce、jedis、连接池、同时连接多个集群、多…

Frida 安装使用

Frida 使用 1:安装 查看安装版本 frida --version 16.0.2(这是我自己安装的版本,目前最新是16.1.17) 安装 pip install frida pip install frida-tools2:frida-server https://github.com/frida/frida/releases 下…

iTerm2+oh-my-zsh搭个Mac电脑上好用好看终端

根据苹果网站上介绍,bash是 macOS Mojave 及更早版本中的默认Shell,从 macOS Catalina 开始,zsh(Z shell) 是所有新建用户帐户的默认Shell。 1. 安装Oh my zsh sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzs…

Java学习笔记43——函数式接口

函数式接口 函数式接口函数式接口概述函数式接口作为方法的参数函数式接口作为方法的返回值 常用的函数式接口Supplier接口Comsumer接口Predicate接口Function接口 函数式接口 函数式接口概述 有且仅有一个抽象方法的接口 是lambda表达式的前提 需要注意的是 默认方法不是抽…

选择java商城开发商需要注意哪些方面?

Java商城开发是一项庞大而复杂的任务,选择一家合适的开发商至关重要。那么,我们在选择Java商城开发商时,需要注意哪些方面呢? 1、专业经验 选择具有丰富经验的开发商是至关重要的。开发商应该拥有多年的Java开发经验,…