etw系统provider事件较多_【Flutter 实战】文件系统目录

老孟导读:Flutter 中获取文件路径,我们都知道使用 path_provider,但对其目录对含义不是很清楚,此文介绍 Android、iOS 系统的文件目录,不同场景下建议使用的目录。
不同的平台对应的文件系统是不同的,比如文件路径,因此 Flutter 中获取文件路径需要原生支持,原生端通过 MethodChannel 传递文件路径到 Flutter,如果没有特殊的需求,推荐大家使用 Google 官方维护的插件 path_provider。
pub 地址:https://pub.flutter-io.cn/packages/path_provider
Github 地址:https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider
添加依赖
在项目的 pubspec.yaml
文件中添加依赖:
dependencies:path_provider: ^1.6.14
执行命令:
flutter pub get
文件路径
path_provider(版本:1.6.14)提供了8个方法获取不同的文件路径,目前 Flutter(Flutter 1.20.1 • channel stable )只发布了正式版本的 Android 和 iOS,因此下面仅介绍 Android 和 iOS 平台的文件路径。
getTemporaryDirectory
临时目录,适用于下载的缓存文件,此目录随时可以清除,此目录为应用程序私有目录,其他应用程序无法访问此目录。
Android 上对应
getCacheDir
。iOS上对应
NSCachesDirectory
。getApplicationSupportDirectory
应用程序可以在其中放置应用程序支持文件的目录的路径。
将此文件用于您不想向用户公开的文件。 您的应用不应将此目录用于存放用户数据文件。
在iOS上,对应
NSApplicationSupportDirectory
,如果此目录不存在,则会自动创建。 在Android上,对应getFilesDir
。getLibraryDirectory
应用程序可以在其中存储持久性文件,备份文件以及对用户不可见的文件的目录路径,例如storage.sqlite.db。
在Android上,此函数抛出[UnsupportedError]异常,没有等效项路径存在。
getApplicationDocumentsDirectory
应用程序可能在其中放置用户生成的数据或应用程序无法重新创建的数据的目录路径。
在iOS上,对应
NSDocumentDirectory
API。 如果数据不是用户生成的,考虑使用[getApplicationSupportDirectory]。在Android上,对应
getDataDirectory
API。 如果要让用户看到数据,请考虑改用[getExternalStorageDirectory]。getExternalStorageDirectory
应用程序可以访问顶级存储的目录的路径。由于此功能仅在Android上可用,因此应在发出此函数调用之前确定当前操作系统。
在iOS上,此功能会引发[UnsupportedError]异常,因为无法在应用程序的沙箱外部访问。
在Android上,对应
getExternalFilesDir(null)
。getExternalCacheDirectories
存储特定于应用程序的外部缓存数据的目录的路径。 这些路径通常位于外部存储(如单独的分区或SD卡)上。 电话可能具有多个可用的存储目录。 由于此功能仅在Android上可用,因此应在发出此函数调用之前确定当前操作系统。 在iOS上,此功能会抛出UnsupportedError,因为这是不可能的在应用程序的沙箱外部访问。
在Android上,对应
Context.getExternalCacheDirs()
或API Level 低于19的Context.getExternalCacheDir()
。getExternalStorageDirectories
可以存储应用程序特定数据的目录的路径。 这些路径通常位于外部存储(如单独的分区或SD卡)上。 由于此功能仅在Android上可用,因此应在发出此函数调用之前确定当前操作系统。 在iOS上,此功能会抛出UnsupportedError,因为这是不可能的在应用程序的沙箱外部访问。 在Android上,对应
Context.getExternalFilesDirs(String type)
或API Level 低于19的Context.getExternalFilesDir(String type)
。getDownloadsDirectory
存储下载文件的目录的路径,这通常仅与台式机操作系统有关。 在Android和iOS上,此函数将引发[UnsupportedError]异常。
如果没有 Android 或者 iOS开发经验,看完上面的说明应该是一脸懵逼的,这么多路径到底用哪个?有什么区别?下面从 Android 和 iOS 平台的角度介绍其文件路径,最后给出路径使用的建议以及使用过程中需要注意的事项。
Android 文件存储
Android 文件存储分为内部存储和外部存储。
内部存储
用于保存应用的私有文件,其他应用无法访问这些数据,创建的文件在此应用的包名目录下,没有 root 权限 的手机无法在手机的 文件管理 应用中看到此目录,不过可以通过 Android Studio 工具查看,路径为:data/data/包名:

看下包名下具体的目录结构:

- cache 目录:对应 getTemporaryDirectory 方法,用于缓存文件,此目录随时可能被系统清除。
- files 目录:对应 getApplicationSupportDirectory 方法。
- code_cache:此目录存储 Flutter 相关代码和资源。
- flutter_engine/skia:Flutter 渲染引擎。
- flutter_guidePVWGWK/flutter_guide/build/flutter_assets:Flutter 资源文件。
- shared_prefs: SharePreferences 的默认路径。
- app_flutter:对应 getApplicationDocumentsDirectory方法。
- app_flutter/dbName:使用 sqlite 的默认路径,sqlite 也可以指定位置。
SharePreferences 和 sqlite 是两种保存数据的第三方插件。
内部存储的特点:
- 安全性,其他应用无法访问这些数据。
- 当应用卸载的时候,这些数据也会被删除,避免垃圾文件。
- 不需要申请额外权限。
- 存储的空间有限,此目录数据随时可能被系统清除,也可以通过 设置 中的 清除数据 可以清除此目录数据。
- 国内特色,不同手机厂商对此目录做了不同的限制,比如总体大小限制、单个应用程序所占空间大小限制、清除数据策略不同等。
外部存储
外部存储可以通过手机的 文件管理 应用查看,

这里面有一个特殊的目录:Android/data/包名:

看到这个目录是不是觉得和内部存储目录非常相似,一个包名代表一个应用程序:

- cache:缓存目录,对应 getExternalCacheDirectories 方法。
- files:对应 getExternalStorageDirectories 方法。
此目录的特点:
- 当应用卸载的时候,这些数据也会被删除,避免垃圾文件。
- 不需要申请额外权限。
- 空间大且不会被系统清除,通过 设置 中的 清除数据 可以清除此目录数据。
- 用户可以直接对文件进行删除、导入操作。
外部存储除了 Android/data/ 目录,还有和此目录同级的目录,特点:
- 所有应用程序均可访问。
- 用户可以直接对文件进行删除、导入操作。
- 需要申请读写权限。
Android 官方对此目录的管理越来越严格, Android 11 系统已经开始强制执行分区存储,详情见:https://developer.android.com/preview/privacy/storage?hl=zh-cn
上面说了这么多,总结如下:
- SharePreferences 和 sqlite 数据建议存放在内部存储,插件已经帮我们完成了,无需手动处理。
- 严格保密的数据,比如用户数据,建议存放在内部存储,对应 getApplicationSupportDirectory 方法。
- 其余所有的数据建议存放 Android/data/包名/ ,对应 getExternalCacheDirectories 和 getExternalStorageDirectories 方法。
iOS 文件存储
iOS 文件存储相比 Android 要简单的多,因为 iOS 对用户隐私保护非常严格,每个 iOS 应用程序都有一个单独的文件系统,而且只能在对应的文件系统中进行操作,此区域被称为沙盒。
每个应用沙盒含有3个文件夹:Documents, Library 和 tmp:

- Documents:应用程序数据文件写入到这个目录下。这个目录用于存储用户数据。保存应用程序的重要数据文件和用户数据文件等。iTunes 同步时会备份该目录,对应 getApplicationDocumentsDirectory 方法。
- Library:对应 getLibraryDirectory 方法。
- Caches:保存应用程序使用时产生的支持文件、缓存文件、日志文件等,比如下载的音乐,视频,SDWebImage缓存等。对应 getTemporaryDirectory 方法。
- Preferences:包含应用程序的偏好设置文件,iCloud会备份设置信息。
- Application Support:对应 getApplicationSupportDirectory 方法。
- tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能,按照官方说法每三天清理一次缓存数据。
path_provider 使用
import 'dart:io';import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';///
/// desc:
///class PathProviderDemo extends StatefulWidget {@override_PathProviderDemoState createState() => _PathProviderDemoState();
}class _PathProviderDemoState extends State<PathProviderDemo> {Future<Directory> _tempDirectory;Future<Directory> _appSupportDirectory;Future<Directory> _appLibraryDirectory;Future<Directory> _appDocumentsDirectory;Future<Directory> _externalStorageDirectory;Future<List<Directory>> _externalStorageDirectories;Future<List<Directory>> _externalCacheDirectories;Future<Directory> _downloadDirectory;@overridevoid initState() {super.initState();setState(() {_tempDirectory = getTemporaryDirectory();_appSupportDirectory = getApplicationSupportDirectory();_appLibraryDirectory = getLibraryDirectory();_appDocumentsDirectory = getApplicationDocumentsDirectory();_externalStorageDirectory = getExternalStorageDirectory();_externalCacheDirectories = getExternalCacheDirectories();_externalStorageDirectories = getExternalStorageDirectories();_downloadDirectory = getDownloadsDirectory();});}Widget _buildDirectory(BuildContext context, AsyncSnapshot<Directory> snapshot) {Text text = const Text('');if (snapshot.connectionState == ConnectionState.done) {if (snapshot.hasError) {text = Text('Error: ${snapshot.error}');} else if (snapshot.hasData) {text = Text('path: ${snapshot.data.path}');} else {text = const Text('path unavailable');}}return Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: text);}Widget _buildDirectories(BuildContext context, AsyncSnapshot<List<Directory>> snapshot) {Text text = const Text('');if (snapshot.connectionState == ConnectionState.done) {if (snapshot.hasError) {text = Text('Error: ${snapshot.error}');} else if (snapshot.hasData) {final String combined =snapshot.data.map((Directory d) => d.path).join(', ');text = Text('paths: $combined');} else {text = const Text('path unavailable');}}return Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: text);}Widget _buildItem(String title, Future<Directory> future) {return Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Padding(padding: const EdgeInsets.symmetric(horizontal: 16),child: Text(title),),FutureBuilder<Directory>(future: future, builder: _buildDirectory),],);}Widget _buildItem1(String title, Future<List<Directory>> future) {return Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Padding(padding: const EdgeInsets.symmetric(horizontal: 16),child: Text(title),),FutureBuilder<List<Directory>>(future: future,builder: _buildDirectories),],);}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(),body: Center(child: ListView(itemExtent: 120,children: <Widget>[_buildItem('getTemporaryDirectory', _tempDirectory),_buildItem('getApplicationSupportDirectory', _appSupportDirectory),_buildItem('getLibraryDirectory', _appLibraryDirectory),_buildItem('getApplicationDocumentsDirectory', _appDocumentsDirectory),_buildItem('getExternalStorageDirectory', _externalStorageDirectory),_buildItem('getDownloadsDirectory', _downloadDirectory),_buildItem1('getExternalStorageDirectories',_externalStorageDirectories),_buildItem1('getExternalCacheDirectories',_externalCacheDirectories),],),),);}
}
Android 系统各个路径:

iOS 系统各个路径:

交流
交流
老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com
欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】
相关文章:

BZOJ4491: 我也不知道题目名字是什么
【传送门:BZOJ4491】 简要题意: 给出一个长度为n的序列,m个操作,每个操作输入x,y,求出第x个数到第y个数的最长子串,保证这个最长子串是不上升或不下降子串 题解: 线段树 因为不上升或…

区块链挖矿的钱从哪来 区块链挖矿怎么挣钱
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 进入2018年以来,区块链在资本市场的风口上依然热度不减,已成为当下最热的投资领域。而普通投资者想通过区块链投资赚钱最简单…

Linux-TCP/IP TIME_WAIT状态原理
TIME_WAIT状态原理----------------------------通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态。客户端主动关闭连接时,会发送最后一个ack后,然后会进入TIME_WAIT状态,再停留2个MSL时间(后有MSL的解释)…

python如何实现找图_利用OpenCV和Python实现查找图片差异
使用OpenCV和Python查找图片差异 flyfish 方法1 均方误差的算法(Mean Squared Error , MSE)下面的一些表达与《TensorFlow - 协方差矩阵》式子表达式一样的拟合 误差平方和( sum of squared errors) residual sum of squares (RSS…

区块链还能赚钱吗 区块链挖矿赚钱吗
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 区块链有多火,连我母上都知道这个词,身边很多人也都向笔者咨询这个东西。 其实他们真实的想法是,想知道这东西到…

pythonfor循环遍历list_为什么for循环可以遍历list:Python中迭代器与生成器
1 引言 只要你学了Python语言,就不会不知道for循环,也肯定用for循环来遍历一个列表(list),那为什么for循环可以遍历list,而不能遍历int类型对象呢?怎么让一个自定义的对象可遍历? 这篇博客中&am…

Linux下查看和添加环境变量
转自:http://blog.sina.com.cn/s/blog_688077cf01013qrk.html $PATH:决定了shell将到哪些目录中寻找命令或程序,PATH的值是一系列目录,当您运行一个程序时,Linux在这些目录下进行搜寻编译链接。 编辑你的 PATH 声明&am…

iis7下站点日志默认位置
iis7下站点日志默认位置 原文:iis7下站点日志默认位置iis7下站点日志默认位置在iis6时,通过iis管理器的日志配置可以找到站点日志存储的位置。但是在iis7下,iis管理器下的日志配置只能找到iis日志配置的主目录,但到底在哪个子目录,…

go语言有哪些优势
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 1、学习曲线容易 Go语言语法简单,包含了类C语法。因为Go语言容易学习,所以一个普通的大学生花几个星期就能写出来可以上手的…

重定向后,如何通过浏览器返回定向之前的页面?
js实现页面跳转重定向的几种方式 第一种: 代码如下: <script language"javascript"type"text/javascript">window.location.href"http://shanghepinpai.com";</script> 第二种: 代码如下: <script languag…

金蝶中间件部署报栈溢出_京东618压测时自研中间件暴露出的问题,压测级别数十万/秒...
618大促演练进行了全链路压测,在此之前刚好我的热key探测框架也已经上线灰度一周了,小范围上线了几千台服务器,每秒大概接收几千个key探测,每天大概几亿左右,因为量很小,所以框架表现稳定。借着这次压测&am…

利用box-shadow绘图
上篇博客提到过,box-shadow属性的本质是对形状的复制,那么如果我设置一个1*1px的i标签,利用box-shadow可以叠加的特性,给每一个1*1px的阴影赋上颜色,那么最后不就是一幅图片了么。 html代码很简单: <!do…

为什么要使用Go语言?Go语言的优势在哪里?
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 Go语言之所有越来越受到开发者的欢迎,我认为与其超高的实用价值密不可分。要知道Go语言是为了解决现实问题而设计的,而不是为…

BI之SSAS完整实战教程3 -- 创建第一个多维数据集
上一篇我们已经完成了数据源的准备工作,现在我们就开始动手,创建第一个多维数据集(Cube)。 文章提纲 使用多维数据集向导创建多维数据集 总结Cube设计器简介 维度细化 总结 一、使用向导创建多维数据集 在Analysis Services中,可以通过3种…

python opencv local_threshold_Python-OpenCV中的cv2.threshold
主要记录Python-OpenCV中的cv2,threshold()方法;官方文档 cv2.threshold() def threshold(src, thresh, maxval, type, dstNone): """ 设置固定级别的阈值应用于多通道矩阵 例如,将灰度图像变换二值图像,或去除指定级别的噪声…

java中decimalFormat格式化数值
介绍 我们经常要对数字进行格式化,比如取小数点后两位小数,或者加个百分比符号等,Java提供了DecimalFormat这个类0 和 # 的区别 "#"可以理解为在正常的数字显示中,如果前缀与后缀出现不必要的多余的0,则将其…

GO语言有哪些优势?怎样入门?
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 1、学习曲线 它包含了类C语法、GC内置和工程工具。这一点非常重要,因为Go语言容易学习,所以一个普通的大学生花一个星期就能…

POJ-2955 Brackets
题目大意: 给你一个只由(、)、[、]组成的字符串,问你这个字符串的子串能够匹配的最长长度是多少。 能够匹配的意思是这样的: 1.如果s是个空串,那么它是匹配的。 2.如果子串是(s)或者[s],那么它也是匹配的,其…

CentOS7.4-btrfs管理及使用
btrfs, B-tree File System, GPL开源文件系统, 支持CoW即读时写入. 核心特性: 多物理卷支持;btrfs可由多个底层磁盘组成支持RAID mkfs.btrfs 命令的man文档支持: raid0, raid1, raid5, raid6,raid10, single or dup联机"添加, 移除, 修改" CoW写时复制更新机制 对文件…

取消对 null 指针“l”的引用。_C++中的引用
当变量声明为引用时,它将成为现有变量的替代名称。通过在声明中添加“&”,可以将变量声明为引用。#include using namespace std; int main() { int x 10; // ref is a reference to x. int& ref x; // Value of x is no…

你没听说过的Go语言惊人优点
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 在这篇文章中,我将讨论为什么你需要尝试一下 Go 语言,以及应该从哪里学起。 Go 语言是可能是最近几年里你经常听人说起的编…

JS document
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head><body><div id"one">今天下雨</div><table border"1" cellspacing"0" cellpadding"…

python 流写入文件_python文件流操作
博主在学习python时对文件进行操作时经常踩一下坑。所以专门梳理了一下。有问题麻烦指出哈。 python对于文件的操作我们一般是用open()。我们根据python的源码可以看出。我们必须要传的参是file即打开文件的URL。同时open方法默认是是r的打开方式即只读。…

使用 Python 从零开始开发区块链应用程序
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 “区块链”是什么? 区块链是一种存储数字数据的方式。数据可以是任何内容。对于比特币,它是事务(在帐户之间转移…

Mybatis学习记录-使用问题总结之一DISTINCT
问题1:手动修改的查询语句,放入到项目中后显示结果和实际查询结果不一致 由于实际情况中用的了分页功能,导致最终的语句在查询完成后,添加了分页项,即如下代码。 ROW_NUMBER() OVER ( ORDER BY COLUMNS) PAGE_ROW_NUMB…

python xlrd读取excel所有数据_python读取excel进行遍历/xlrd模块操作
我就废话不多说了,大家还是直接看代码吧~ #!/usr/bin/env python # -*- coding: utf-8 -*- import csv import xlrd import xlwt def handler_excel(filenamer/Users/zongyang.yu/horizon/ops_platform/assets/upload/1.xlsl): # 打开文件 workbook xlrd.open_work…

【NOIP2015提高组Day1】 神奇的幻方
【问题描述】 幻方是一种很神奇的 N*N矩阵:它由数字1,2,3, … … ,N*N 构成,且每行、每列及两条对角线上的数字之和都相同。 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间。 之后,按如下…

40行python开发一个区块链
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 尽管有人认为区块链目前还是个不成熟的解决方案,但它无疑称得上是计算机发展历史上的一个奇迹。但是,到底区块链是什么呢?…

网络实验的背景流
在最近做的网络实验中,发现背景流必须要先于实验流开始,并且要长于实验流的时间,这样才能看出实验流的规律。如果背景流后发于实验流,就会变成竞争模式,实验流就会被抢占或者挤压。转载于:https://www.cnblogs.com/fen…

python捕获异常后处理_python异常捕获处理
一、异常处理 在程序运行过程中,总会遇到各种各样的错误。程序一旦出错就停止运行了,此时就需要捕捉异常,通过捕捉到的异常,我们再去做对应的处理 写一个函数,实现除法运算 def calc(a,b): return a/b print(calc(5,1)…