flutter zip压缩/解压缩,生成/读取csv文件

今天分享干货的都是文件操作相关

  • 如何读取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的文章。如果有疑问的话,请在下方留言~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容