美文网首页
flutter zip压缩/解压缩,生成/读取csv文件

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

作者: 微风_10a5 | 来源:发表于2021-07-27 18:30 被阅读0次

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

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

    相关文章

      网友评论

          本文标题:flutter zip压缩/解压缩,生成/读取csv文件

          本文链接:https://www.haomeiwen.com/subject/otvomltx.html