Flutter笔记:目录与文件存储以及在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文件读写

本节将介绍 字节流 和 字符流 的基本概念、操作方法以及性能优化。

1.1 字节流(Byte Stream)

字节流是一种低级的输入输出流,它以字节为单位进行读写操作。字节流通常用于处理二进制数据,如图片、音频和视频等。

在Dart中,我们可以使用File类的openRead和openWrite方法来创建字节流。

以下是一些使用字节流进行文件读写的示例:

1.1.1 以字节流读取文件

使用 openRead 方法可以创建一个字节流,用于读取文件的内容。openRead 方法返回一个 Stream<List<int>> 对象,我们可以使用 Stream 的各种方法来处理字节流。

  /// 为此文件的内容创建一个新的独立 [Stream]。////// 如果 [start] 存在,将从字节偏移量 [start] 读取文件。否则从开始(索引0)。////// 如果 [end] 存在,只读取到字节索引 [end] 的字节。否则,直到文件结束。////// 为确保系统资源被释放,必须读取流到完成,或者取消对流的订阅。////// 如果 [File] 是一个 [命名管道](https://en.wikipedia.org/wiki/Named_pipe)/// 那么返回的 [Stream] 将等待管道的写入端关闭后才会发出 "done" 信号。如果在打开时管道没有连接的写入器,/// 那么 [Stream.listen] 将等待写入器打开管道。Stream<List<int>> openRead([int? start, int? end]);

例如:

import 'dart:io';void main() async {var file = File('test.txt');Stream<List<int>> inputStream = file.openRead();await for (var data in inputStream) {// 处理数据...}
}

在这个示例中,我们首先创建了一个字节流,然后使用await for循环来处理字节流中的数据。

1.1.2 以字节流写入文件

使用 openWrite 方法可以创建一个字节流,用于向文件中写入数据。openWrite 方法返回一个 IOSink 对象,我们可以使用IOSinkaddwrite 方法来写入数据。

// abstract interface class IOSink/// 将字节 [data] 添加到目标消费者,忽略 [encoding]。////// [encoding] 不适用于此方法,[data] 列表直接作为流事件传递给目标消费者。////// 当使用 [addStream] 添加流时,不应调用此方法。////// 此操作是非阻塞的。查看 [flush] 或 [done] 以获取此调用生成的任何错误。////// 传递给 `add` 后,不应修改数据列表,因为目标消费者接收列表的原始状态还是修改后的状态未定义。////// [data] 中的单个值如果不在 0 .. 255 的范围内,将被截断到其低8位,就像通过 [int.toUnsigned] 那样,然后再使用。void add(List<int> data);/// 通过调用 [Object.toString] 将 [object] 转换为字符串,并将结果的编码 [add] 到目标消费者。////// 此操作是非阻塞的。查看 [flush] 或 [done] 以获取此调用生成的任何错误。void write(Object? object);

例如:

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

在这个示例中,我们首先创建了一个字节流,然后使用 write 方法向字节流中写入数据。最后,我们使用 close 方法关闭字节流。

1.2 字符流(Character Stream)

1.2.1 以字节流读取文件

字符流是一种高级的输入输出流,它以字符为单位进行读写操作。字符流通常用于处理文本数据。

Dart 中,我们可以使用 File 类的 readAsStringwriteAsString 方法来进行字符流的读写操作。

  /// 使用给定的 [Encoding] 读取整个文件内容作为字符串。////// 返回一个 `Future<String>`,当文件内容被读取后,该Future将完成并返回字符串。Future<String> readAsString({Encoding encoding = utf8});

例如:

import 'dart:io';void main() async {var file = File('test.txt');String contents = await file.readAsString();print(contents);
}

在这个示例中,我们使用 readAsString 方法读取了文件的内容,并将其打印出来。

1.2.2 以字节流写入文件

使用 writeAsString 方法可以向文件中写入字符串。如果文件不存在,writeAsString 方法会创建一个新的文件。如果文件已经存在,writeAsString 方法会覆盖文件的内容。

  /// 将字节列表写入文件。////// 打开文件,将字节列表写入文件,然后关闭文件。返回一个 `Future<File>`,当整个操作完成后,该Future将完成并返回此 [File] 对象。////// 默认情况下,[writeAsBytes] 会创建文件并进行写入,如果文件已存在,将会截断文件。如果要将字节追加到现有文件,可以将 [FileMode.append] 作为可选的mode参数传入。////// 如果参数 [flush] 设置为 `true`,在返回的Future完成之前,写入的数据将被刷新到文件系统。Future<File> writeAsBytes(List<int> bytes,{FileMode mode = FileMode.write, bool flush = false});

例如:

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

在这个示例中,我们使用 writeAsString 方法向文件中写入了一些文本。

1.3 使用流优化文件读写

在读取或写入大文件时,我们通常使用流来处理数据。流可以让我们以块的形式处理数据,而不是一次性加载整个文件到内存中。这样可以显著减少内存使用,并提高程序的响应性。

以下是一个使用流读取大文件的示例:

import 'dart:io';
import 'dart:convert';void main() {var file = File('large_file.txt');var inputStream = file.openRead();inputStream.transform(utf8.decoder)  // 将字节解码为UTF-8.transform(LineSplitter())  // 将流转换为单独的行.listen((String line) {  // 处理结果print('从流中获得 ${line.length} 个字符');}, onDone: () {print('文件现已关闭');}, onError: (e) {print(e.toString());});
}

在这个示例中,我们首先打开了一个文件的读取流,然后使用 transform 方法将字节流转换为字符串流,再将字符串流转换为行流。最后,我们使用 listen 方法处理每一行数据。

2. 文件权限

在进行文件操作时,我们需要考虑到平台权限问题。不同的操作系统和设备可能有不同的权限要求。以下是一些可能需要处理的权限问题:

2.1 不同移动平台上的权限

以往,在 Android 平台上,我们需要在 AndroidManifest.xml 文件中声明我们需要的权限。

  • READ_EXTERNAL_STORAGE:这个权限允许应用读取设备上的外部存储空间。
  • WRITE_EXTERNAL_STORAGE:这个权限允许应用写入设备上的外部存储空间。

但是从Android 6.0(API级别23)开始,用户可以在运行时授予或撤销某些权限。
即使你在 AndroidManifest.xml 文件中声明了这些权限,你仍然需要在运行时检查这些权限是否已经被授予,并在需要时请求用户授予这些权限。

而在iOS平台上,我们需要在Info.plist文件中声明我们需要的权限。以下是一些可能需要的权限:

  • NSFileProtectionCompleteUntilFirstUserAuthentication:这个权限允许应用在设备解锁后访问文件。

2.2 使用 permission_handler 请求权限

为了方便的获取相应的用户授权,在进行文件操作前,我们需要检查并请求必要的运行时权限,这可以使用 permission_handler 库来完成。我们可以使用来处理运行时权限。

2.2.1 安装和配置 permission_handler

首先,我们需要在项目中安装 permission_handler 库。在 pubspec.yaml 文件中添加以下依赖:

dependencies:flutter:sdk: flutterpermission_handler: ^11.0.1

然后,运行 flutter pub get 命令来获取库。

2.2.2 请求存储权限

以下是一个请求权限的示例:

import 'package:permission_handler/permission_handler.dart';void main() async {var status = await Permission.storage.status;if (!status.isGranted) {status = await Permission.storage.request();}if (status.isGranted) {// 你可以开始文件操作} else {// 不能启动文件操作}
}

在这个示例中,我们首先检查存储权限的状态。如果权限没有被授予,我们请求用户授予权限。如果权限被授予,我们可以开始文件操作。否则,我们不能开始文件操作。

2.3 处理权限拒绝

如果用户拒绝了我们的权限请求,我们需要处理这种情况。我们可以显示一个解释为什么我们需要这个权限的对话框,或者引导用户到系统设置中开启权限。例如:

import 'package:permission_handler/permission_handler.dart';void handler_storage_permission() async {var status = await Permission.storage.status;if (!status.isGranted) {status = await Permission.storage.request();}if (status.isGranted) {// 你可以开始文件操作// ...} else if (status.isPermanentlyDenied) {// 用户选择永久拒绝权限// 你可以在这里打开应用设置// ...openAppSettings();} else {// 用户选择拒绝权限// 你可以在这里显示一个对话框// ...}
}

在这个示例中,如果用户永久地拒绝了权限,我们可以打开应用设置。如果用户只是拒绝了权限,我们可以显示一个对话框。

3. Flutter 文件存储

本节讲解如何在Flutter中进行文件存储,包括如何使用path_provider库来获取应用的文件存储路径,如何使用File类的方法来进行文件的读写操作,以及如何读写特殊类型的文件。

3.1 path_provider 库及其用法

path_provider 是一个Flutter插件,用于查找iOS和Android上的常用位置的路径。这个库可以帮助我们找到存储应用数据的正确位置。

3.1.1 安装 path_provider

首先,我们需要在项目中安装path_provider库。在pubspec.yaml文件中添加以下依赖:

dependencies:flutter:sdk: flutterpath_provider: ^2.1.1

3.1.2 获取临时目录

我们可以使用getTemporaryDirectory方法来获取临时目录的路径。临时目录是一个可以用来存储临时数据的目录。系统可能会随时清理这个目录,因此不应将重要数据保存在这里。

import 'package:path_provider/path_provider.dart';Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;print(tempPath);

3.1.3 取应用程序目录

我们可以使用getApplicationDocumentsDirectory方法来获取应用程序目录的路径。应用程序目录是一个可以用来存储应用需要持久化的数据的目录。系统不会清理这个目录,因此可以安全地将重要数据保存在这里。

import 'package:path_provider/path_provider.dart';Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;print(appDocPath);

3.1.4 获取外部存储中为应用程序创建的目录

我们可以使用 getExternalStorageDirectory 方法来获取外部存储中为应用程序创建的目录的路径。这个目录通常用来存储可以由用户在其他应用中访问的文件,如图片、音乐等。

import 'package:path_provider/path_provider.dart';Directory externalStorageDir = await getExternalStorageDirectory();
String externalStoragePath = externalStorageDir.path;print(externalStoragePath);

注意,由于Android 10的隐私更改,此方法不再可用。作为替代,你可以查看MediaStore。

3.1.5 获取应用程序缓存目录

我们可以使用getCacheDirectory方法来获取应用程序缓存目录的路径。这个目录用来存储临时缓存数据。

import 'package:path_provider/path_provider.dart';Directory cacheDir = await getCacheDirectory();
String cachePath = cacheDir.path;print(cachePath);

3.1.6 获取应用程序可以放置应用库文件的目录

我们可以使用getApplicationSupportDirectory方法来获取应用程序可以放置应用库文件的目录的路径。这个目录用来存储应用的支持文件,这些文件只有应用本身可以访问。

import 'package:path_provider/path_provider.dart';Directory supportDir = await getApplicationSupportDirectory();
String supportPath = supportDir.path;print(supportPath);

3.2 文件的读写操作

在Flutter中,我们可以使用File类的方法来进行文件的读写操作,与在Dart中的操作方式相同。因此你需要 导入 ‘dart:io’:

import 'dart:io';

具体操作这里不再赘述。

3.3 读写特殊类型的文件示例

在Flutter中,我们可以使用File类来读写各种类型的文件,包括图片、音频等特殊类型的文件。然而,由于这些特殊类型的文件通常是二进制格式的,因此我们需要使用readAsBytes和writeAsBytes方法来读写这些文件。

3.3.1 图片文件

  1. 读取图片文件

我们可以使用 readAsBytes 方法来读取图片文件,然后使用 Image.memory 构造函数来创建一个图片控件。

import 'dart:io';
import 'package:flutter/material.dart';void main() async {var file = File('path_to_your_image_file');var bytes = await file.readAsBytes();var image = Image.memory(bytes);runApp(MaterialApp(home: Scaffold(body: Center(child: image),),));
}
  1. 写入图片文件

我们可以使用writeAsBytes方法来写入图片文件。首先,我们需要获取图片的字节数据,然后将这些字节数据写入文件。

import 'dart:io';
import 'package:flutter/services.dart';void main() async {var bytes = await rootBundle.load('assets/image.png');var file = File('path_to_your_image_file');await file.writeAsBytes(bytes.buffer.asUint8List());
}

3.3.2 音频文件

  1. 读取音频文件

读取音频文件的方法与读取图片文件类似,我们可以使用 readAsBytes 方法来读取音频文件。然而,由于Flutter的核心库并不支持音频播放,因此我们需要使用一个第三方库,如audioplayers,来播放音频。

import 'dart:io';
import 'package:audioplayers/audioplayers.dart';void main() async {var file = File('path_to_your_audio_file');var bytes = await file.readAsBytes();var player = AudioPlayer();await player.playBytes(bytes);
}
  1. 写入音频文件

写入音频文件的方法与写入图片文件类似,我们可以使用writeAsBytes方法来写入音频文件。

import 'dart:io';
import 'package:flutter/services.dart';void main() async {var bytes = await rootBundle.load('assets/audio.mp3');var file = File('path_to_your_audio_file');await file.writeAsBytes(bytes.buffer.asUint8List());
}

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

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

相关文章

-bash: jps: command not found

背景 服务器的jdk通过yum 安装的&#xff0c;要用jps查询pid&#xff0c;提示找不到命令 yum install -y java-1.8.0-openjdk.x86_64 一、jps命令无法找到 [devhgh-tob-hsbc-dev-003 ~]$ jps -bash: jps: command not found 二、检查基础Java环境 [devhgh-tob-hsbc-dev-003 ~]…

计算机是如何工作的(简单介绍)

目录 一、冯诺依曼体系 二、CPU基本流程工作 逻辑⻔ 电⼦开关——机械继电器(Mechanical Relay) ⻔电路(Gate Circuit) 算术逻辑单元 ALU&#xff08;Arithmetic & Logic Unit&#xff09; 算术单元(ArithmeticUnit) 逻辑单元(Logic Unit) ALU 符号 寄存器(Regis…

KVM Cloud云平台

项目介绍 KVM Cloud 是一款基于Java实现的轻量级私有云平台&#xff0c;旨在帮助中小企业快速实现计算、存储、网络等资源的管理&#xff0c;让企业拥有自己的云平台&#xff0c;包括但不限于如下功能: 1、基于KVM的VM基础功能(创建、启动、停止、重装、webVNC等功能) 2、使用…

xftp连接wsl2

在WSL中默认是没有安装OpenSSH&#xff0c;需要自己安装。 安装 sudo apt update sudo apt install openssh-server检查是否安装成功 ssh -V配置ssh sudo vim /etc/ssh/ssh_config设置端口 Port 22启动ssh服务 sudo service ssh startxftp连接 主机地址&#xff1a;127.…

从零开始写一个APM监控程序(一)协议

APM&#xff08;Application Performance Monitoring&#xff09;是一种用于监控和管理应用程序性能的解决方案。它通过收集、分析和报告应用程序的性能数据&#xff0c;帮助开发人员和系统管理员更好地了解应用程序的运行状况&#xff0c;识别潜在的性能问题&#xff0c;并进行…

卷积神经网络(CNN)衣服图像分类的实现

文章目录 前期工作1. 设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;我的环境&#xff1a; 2. 导入数据3.归一化4.调整图片格式5. 可视化 二、构建CNN网络模型三、编译模型四、训练模型五、预测六、模型评估 前期工作 1. 设置GPU&#xff08;如果使用的是CPU可以…

Office文件在线预览大全-Word文档在线预览的实现方法-OFD文档在线预览-WPS文件在线预览

Office文件在线预览大全-Word文档在线预览的实现方法-OFD文档在线预览-WPS文件在线预览 Office文件在线预览指的是文件在浏览器中可以直接预览查看&#xff0c;不需要安装任何插件就可以实现文档的在线预览功能、打印功能、文件转PDF功能、文件转OFD功能、文档内容提取功能、自…

JVM——运行时数据区(程序计数器+栈)

目录 1.程序计数器2.栈Java虚拟机栈 - 栈帧的组成1.Java虚拟机栈-局部变量表3.Java虚拟机栈-操作数栈3.Java虚拟机栈-帧数据 3.Java虚拟机栈-栈内存溢出4.本地方法栈 ⚫ Java虚拟机在运行Java程序过程中管理的内存区域&#xff0c;称之为运行时数据区。 ⚫ 《Java虚拟机规范》中…

Unity减少发布打包文件的体积(二)——设置WebGL发布时每张图片的压缩方式

一个项目在发布成WebGL后&#xff0c;其体积至关重要&#xff0c;体积太大&#xff0c;用户加载会经历一个漫长的等待…轻则骂娘&#xff0c;重则用脚把电脑踢烂(扣质保金)… 那么如何减少发布后的体积呢&#xff0c;本文从图片的压缩开始入手。 前传回顾&#xff1a; Unity减…

Linux mmap 的作用是什么?

文章目录 1.简介2.相关函数3.mmap和常规文件操作的区别4.作用参考文献 1.简介 mmap&#xff08;memory map&#xff09;即内存映射&#xff0c;用于将一个文件或设备映射到进程的地址空间。 2.相关函数 创建映射函数&#xff1a; #include <sys/mman.h>void *mmap(v…

Upwork 新手使用指南——如何快速在Upwork上接单

Upwork 这个自由职业平台不知道大家听说过没&#xff0c;在 Upwork&#xff0c;如果你是自由职业者&#xff0c;你可以接单&#xff1b;如果你是客户&#xff0c;你可以找人干活。但对于新手来说&#xff0c;怎么使用 Upwork 并且用好 Upwork 是一大难题。因此今天给大家分享 U…

你好,我叫Python,欢迎你认识派森。(来自关于Python语言的全方位自我介绍。

文章目录 自我简介一、Python的发展历程二、Python的特色1.语言特色2.语法特色 三、Python2与Python3的比较1.print 函数2.Unicode3.除法运算4.异常5.八进制字面量表示6.不等运算符7.python 3.0严格使用tab键进行缩进 四、Python适用开发场景及成果1.应用领域2.Python开发出的应…

20231120_python练习_天气网爬取城市近七天温度情况

先根据城市名找到对应编码&#xff0c;然后获取近七天天气情况 淄博 101120301 [‘20日&#xff08;今天&#xff09;’] [‘晴’] <class ‘list’> [‘7℃’] [‘\n’, ‘<3级’, ‘\n’] 淄博 101120301 [‘21日&#xff08;明天&#xff09;’] [‘晴转阴’] <…

python科研绘图:P-P图与Q-Q图

目录 什么是P-P图与Q-Q图 分位数 百分位数 Q-Q图步骤与原理 Shapiro-Wilk检验 绘制Q-Q图 绘制P-P图 什么是P-P图与Q-Q图 P-P图和Q-Q图都是用于检验样本的概率分布是否服从某种理论分布。 P-P图的原理是检验实际累积概率分布与理论累积概率分布是否吻合。若吻合&#xf…

srs webrtc推拉流环境搭建(公网)

本地环境搭建 官方代码https://github.com/ossrs/srs 拉取代码&#xff1a; git clone https://github.com/ossrs/srs.gitcd ./configure make ./objs/srs -c conf/https.rtc.confsrs在公网上&#xff0c;由于srs是lite-ice端&#xff0c;导致他不会主动到srs获取自己的公网i…

MySQL的执行器是怎么工作的

作为优化器后的真正执行语句的层&#xff0c;执行器有三种方式和存储引擎&#xff08;一般是innoDB&#xff09;交互 主键索引查询 查询的条件用到了主键&#xff0c;这个是全表唯一的&#xff0c;优化器会选择const类型来查询&#xff0c;然后while循环去根据主键索引的B树结…

nn.KLDivLoss,nn.CrossEntropyLoss,nn.MSELoss,Focal_Loss

KL loss&#xff1a;https://blog.csdn.net/qq_50001789/article/details/128974654 https://pytorch.org/docs/stable/nn.html 1. nn.L1Loss 1.1 公式 L1Loss: 计算预测 x和 目标y之间的平均绝对值误差MAE, 即L1损失&#xff1a; l o s s 1 n ∑ i 1 , . . . n ∣ x i…

Java 设计模式——桥接模式

目录 1.概述2.结构3.实现3.1.实现化类3.2.具体实现化类3.3.抽象化类3.4.扩展抽象化类3.5.测试 4.优缺点5.使用场景 1.概述 &#xff08;1&#xff09;现在有一个需求&#xff0c;需要创建不同的图形&#xff0c;并且每个图形都有可能会有不同的颜色。我们可以利用继承的方式来…

数据结构与算法之美学习笔记:22 | 哈希算法(下):哈希算法在分布式系统中有哪些应用?

目录 前言应用五&#xff1a;负载均衡应用六&#xff1a;数据分片应用七&#xff1a;分布式存储解答开篇 & 内容小结 前言 本节课程思维导图 今天&#xff0c;我们再来看剩余三种应用&#xff1a;负载均衡、数据分片、分布式存储。你可能已经发现&#xff0c;这三个应用都…

详解Java设计模式之职责链模式

原文&#xff1a;详解Java设计模式之职责链模式_java_脚本之家 责任链模式是一种行为设计模式&#xff0c;使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系&#xff0c;文中通过代码示例给大家介绍的非常详细,需要的朋友可以参考下 − 目…