今天分享干货的都是文件操作相关
- 如何读取flutter assets文件夹下的csv文件(加载本地csv文件,并展示出来)
- 如何把大量数据,保存到csv文件中,且把csv文件放到缓存目录中
- 如何去缓存目录中读取csv文件,并且展示在界面上
- 如何把csv文件进行压缩(.zip),且把zip文件放到缓存目录中
- 如何解压缩zip文件,且把解压后的csv文件读取出来,展示在界面上
首先我们会用到以下4个第三方库,各自的作用后面都有注释
csv: ^5.0.0 //操作csv文件相关
path_provider: ^2.0.2 //文件路径相关
archive: ^3.1.2 //压缩,解压缩相关
permission_handler: ^8.1.4+1 //申请权限相关
项目配置如下
config.png
本地sales.csv文件下数据也比较简单,主要用来测试的,如下图
csv.png
读取本地csv文件
//读取csv文件(从Assets资源文件夹读取csv文件)
loadCSVFormAssets() async {
final myData = await rootBundle.loadString("assets/sales.csv");
List<List<dynamic>> csvTable = CsvToListConverter().convert(myData);
data = csvTable;
print("loadCSVFileTest读取的数据data = $data");
setState(() {});
}
执行后的结果如下,同本地csv文件(如上图),内容相同。
localCsv.png
界面效果如下
androidLoacal.png
.
生成csv文件,放到缓存目录中
createCSVFile() async {
List rootAttendanceList = [
["name", "age"],
["zz", 28],
["wu", 27]
];
List<List<dynamic>> rows = [];
for (int i = 0; i < rootAttendanceList.length; i++) {
List<dynamic> row = [];
row.add(rootAttendanceList[i][0]);
row.add(rootAttendanceList[i][1]);
rows.add(row);
}
print("rows =======$rows");
Directory documentsDir = (await getApplicationDocumentsDirectory());
// 创建ble文件夹
Directory desDir = await Directory('${documentsDir.path}/ble').create();
print("desDir=${desDir.path}");
String file = "${desDir.path}";
File f = new File(file + "/myReport.csv");
// 生成csv文件,csv文件路径:缓存目录下的 ble文件夹下
String csv = const ListToCsvConverter().convert(rows);
f.writeAsString(csv);
print("生成csv文件路径=${f.path}");
}
结果如下,可以看到缓存目录中已经生成了myReport.csv文件
create.png
压缩csv文件,生成zip文件,zip文件也是在缓存目录中,代码如下
// 压缩csv文件成zip文件
_zipFiles() async {
Directory documentsDir = (await getApplicationDocumentsDirectory());
Directory desDir = await Directory('${documentsDir.path}/ble').create();
String desPath = desDir.path;
var encoder = ZipFileEncoder();
encoder.zipDirectory(Directory(desDir.path),
filename: desDir.path + ".zip");
print("""生成zip文件路径=$desPath.zip""");
}
运行后结果如下
zip.png
因为解压缩后会自动生成ble文件夹及底下文件,为了验证是真的能解压缩,为了避免干扰,我们先把现在已经有的ble文件夹及子文件全部删除。,如下图
noBLeDirectory.png解压缩zip文件
// 解压缩zip文件,释放出csv文件
_unZipFiles() async {
Directory documentsDir = (await getApplicationDocumentsDirectory());
Directory desDir = Directory('${documentsDir.path}/ble');
String zipFilePath = desDir.path + ".zip";
print("压缩文件路径zipFilePath = $zipFilePath");
// 从磁盘读取Zip文件。
List<int> bytes = File(zipFilePath).readAsBytesSync();
// 解码Zip文件
Archive archive = ZipDecoder().decodeBytes(bytes);
// 将Zip存档的内容解压缩到磁盘。
for (ArchiveFile file in archive) {
if (file.isFile) {
List<int> tempData = file.content;
File f = File(desDir.path + "/" + file.name)
..createSync(recursive: true)
..writeAsBytesSync(tempData);
print("解压后的文件路径 = ${f.path}");
Future.delayed(Duration(seconds: 2), () {
//读取csv文件(从缓存目录中读取csv文件)
loadCSVFile(f);
});
} else {
Directory(desDir.path + "/" + file.name)..create(recursive: true);
}
}
print("解压成功");
}
运行结果如下,注意看下图右边又生成了ble文件夹及csv文件:
unzip.png
解压缩出来后,我们要读取csv文件里面的内容,并展示出来;读取出来的数据如上图所示
//读取csv文件(从缓存目录中读取csv文件)
loadCSVFile(File file) async {
// String myData = await rootBundle.loadString(file.path);
String myData = await file.readAsString();
print("myData=$myData");
List<List<dynamic>> csvTable = CsvToListConverter().convert(myData);
data = csvTable;
print("读取的数据data = $data");
setState(() {});
}
读取完数据后,界面展示效果如下:
loadCsv.png
最后奉上完整代码
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
import 'package:csv/csv.dart';
import 'package:path_provider/path_provider.dart';
import 'package:archive/archive.dart';
import 'package:archive/archive_io.dart';
import 'package:permission_handler/permission_handler.dart';
class TableLayout extends StatefulWidget {
@override
_TableLayoutState createState() => _TableLayoutState();
}
class _TableLayoutState extends State<TableLayout> {
List<List<dynamic>> data = [];
@override
void initState() {
// TODO: implement initState
super.initState();
_requestPermission();
// 加载本地csv文件并展示出来
loadCSVFormAssets();
}
_requestPermission() async {
if (await Permission.contacts.request().isGranted) {
// Either the permission was already granted before or the user just granted it.
}
// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
Permission.storage,
].request();
print(statuses[Permission.location]);
print(statuses[Permission.storage]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.refresh),
onPressed: () {
// 生成csv文件
createCSVFile();
}),
appBar: AppBar(
title: Text("Table Layout and CSV"),
actions: [
IconButton(
onPressed: () {
// 压缩csv文件成zip文件
_zipFiles();
},
icon: Icon(Icons.compare)),
IconButton(
onPressed: () {
// 解压缩zip文件,释放出csv文件
_unZipFiles();
},
icon: Icon(Icons.insert_comment)),
],
),
body: SingleChildScrollView(
child: Table(
// columnWidths: {
// 0: FixedColumnWidth(100.0),
// 1: FixedColumnWidth(100.0),
// },
border: TableBorder.all(width: 1.0),
children: data.map((item) {
return TableRow(
children: item.map((row) {
return Container(
color:
row.toString().contains("NA") ? Colors.red : Colors.green,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
row.toString(),
style: TextStyle(fontSize: 20.0, color: Colors.white),
),
),
);
}).toList());
}).toList(),
),
),
);
}
//读取csv文件(从Assets资源文件夹读取csv文件)
loadCSVFormAssets() async {
final myData = await rootBundle.loadString("assets/sales.csv");
List<List<dynamic>> csvTable = CsvToListConverter().convert(myData);
data = csvTable;
print("loadCSVFileTest读取的数据data = $data");
setState(() {});
}
createCSVFile() async {
List rootAttendanceList = [
["name", "age"],
["zz", 28],
["wu", 27]
];
List<List<dynamic>> rows = [];
for (int i = 0; i < rootAttendanceList.length; i++) {
List<dynamic> row = [];
row.add(rootAttendanceList[i][0]);
row.add(rootAttendanceList[i][1]);
rows.add(row);
}
print("rows =======$rows");
Directory documentsDir = (await getApplicationDocumentsDirectory());
// 创建ble文件夹
Directory desDir = await Directory('${documentsDir.path}/ble').create();
print("desDir=${desDir.path}");
String file = "${desDir.path}";
File f = new File(file + "/myReport.csv");
// 生成csv文件,csv文件路径:缓存目录下的 ble文件夹下
String csv = const ListToCsvConverter().convert(rows);
f.writeAsString(csv);
print("生成csv文件路径=${f.path}");
}
//读取csv文件(从缓存目录中读取csv文件)
loadCSVFile(File file) async {
// String myData = await rootBundle.loadString(file.path);
String myData = await file.readAsString();
print("myData=$myData");
List<List<dynamic>> csvTable = CsvToListConverter().convert(myData);
data = csvTable;
print("读取的数据data = $data");
setState(() {});
}
// 压缩csv文件成zip文件
_zipFiles() async {
Directory documentsDir = (await getApplicationDocumentsDirectory());
Directory desDir = await Directory('${documentsDir.path}/ble').create();
String desPath = desDir.path;
var encoder = ZipFileEncoder();
encoder.zipDirectory(Directory(desDir.path),
filename: desDir.path + ".zip");
print("""生成zip文件路径=$desPath.zip""");
}
// 解压缩zip文件,释放出csv文件
_unZipFiles() async {
Directory documentsDir = (await getApplicationDocumentsDirectory());
Directory desDir = Directory('${documentsDir.path}/ble');
String zipFilePath = desDir.path + ".zip";
print("压缩文件路径zipFilePath = $zipFilePath");
// 从磁盘读取Zip文件。
List<int> bytes = File(zipFilePath).readAsBytesSync();
// 解码Zip文件
Archive archive = ZipDecoder().decodeBytes(bytes);
// 将Zip存档的内容解压缩到磁盘。
for (ArchiveFile file in archive) {
if (file.isFile) {
List<int> tempData = file.content;
File f = File(desDir.path + "/" + file.name)
..createSync(recursive: true)
..writeAsBytesSync(tempData);
print("解压后的文件路径 = ${f.path}");
Future.delayed(Duration(seconds: 2), () {
//读取csv文件(从缓存目录中读取csv文件)
loadCSVFile(f);
});
} else {
Directory(desDir.path + "/" + file.name)..create(recursive: true);
}
}
print("解压成功");
}
// 删除文件夹及其下所有文件
_deleteDirectory(Directory directory) {
directory.delete(recursive: true);
}
}
补充
1.此demo,苹果 ,安卓都能正常使用的,
2.生成的csv文件,用电脑端的Excel软件是可以正常打开的,
3.zip文件用电脑端的解压缩软件也是可以正常解压的,
4.可以生成多个csv文件,然后将多个csv文件一起压缩到zip文件中,读出来的时候也是有多个csv文件
5.安卓需要申请文件读写相关权限,具体如下
permission.png
结尾
小伙伴们,为了实现上面功能,本人也是花费了不费时间,踩过不少的坑,如果小伴们,觉得有点用的话,或者已经看到这里面来的请点个赞吧~~ 后续分享更多有关flutter的文章。如果有疑问的话,请在下方留言~
网友评论