AxeSlide软件项目梳理   canvas绘图系列知识点整理

自动保存的基本思路

1)软件每次打开都会创建一个保存画布元素信息的文件,文件名是在打开软件时生成的唯一字符串。可同时打开多个窗口,所以保存文件路径下work/context文件夹里可能会有多个文件。

2)每隔2分钟就更新一次context.json文件

3)软件窗口正常关闭时将该窗口对应的context.json文件自动删除,如果仅打开了这一个窗口,将work下其他资源文件(插入的图片等)也删除掉。

软件窗口如果是非正常关闭(电脑断电,电脑死机,软件崩溃等),context.json文件和work下的资源文件都不会被删除

4)当软件再次被打开时,如果无其他窗口打开并且work/context目录下面有context.json文件存在,这时候软件会提醒有文件需要恢复保存。

保存context.json文件

针对过程2)每间隔2分钟context.json文件被保存一次,借助游戏主循环《软件项目技术点(1)——游戏主循环机制》,我们在循环主函数run()里添加如下代码,判断是否需要进行一次保存。

1 //自动保存context
2 if (!that.isGoto && editor.canvas.extendIntervalId < 0) {
3     var autoSaveSetting = index.autoSaveContext;
4     if (that.commonElements.count() >= 1 && curTime - autoSaveSetting.lastSaveTime > 60 * 1000 * <number>autoSaveSetting.saveTime) {
5         autoSaveSetting.saveContext();
6     }
7 }

如何将画布对象信息写入一个.json文件?

我们先给大家认识一下我们代码里利用到的这三个fs函数

(1)打开文件

fs.open(filename, flags, [mode], callback);
 1 // fs.open(filename, flags, [mode], callback);
 2
 3 /**
 4  * filename, 必选参数,文件名
 5  * flags, 操作标识,如"r",读方式打开,'r' 写方式打开
 6  * [mode],权限,如777,表示任何用户读写可执行
 7  * callback 打开文件后回调函数,参数默认第一个err,
 8     第二个fd为一个整数,表示打开文件返回的文件描述符,window中又称文件句柄
 9  */
10
11 fs.open(__dirname + '/test.txt', 'r', '0666', function (err, fd) {
12   console.log(fd);
13 });

(2)写文件,将缓冲区内数据写入使用fs.open打开的文件

fs.write(fd, buffer, offset, length, position, callback);
 1 //fs.write(fd, buffer, offset, length, position, callback);
 2
 3 /**
 4  * fd, 使用fs.open打开成功后返回的文件描述符
 5  * buffer, 一个Buffer对象,v8引擎分配的一段内存
 6  * offset, 整数,从缓存区中读取时的初始位置,以字节为单位
 7  * length, 整数,从缓存区中读取数据的字节数
 8  * position, 整数,写入文件初始位置;
 9  * callback(err, written, buffer), 写入操作执行完成后回调函数,written实际写入字节数,buffer被读取的缓存区对象
10  */
11
12 fs.open(__dirname + '/test.txt', 'a', function (err, fd) {
13   if(err) {
14     console.error(err);
15     return;
16   } else {
17     var buffer = new Buffer('写入文件数据内容');
18     //写入'入文件'三个字
19     fs.write(fd, buffer, 3, 9, 12, function (err, written, buffer) {
20       if(err) {
21         console.log('写入文件失败');
22         console.error(err);
23         return;
24       } else {
25         console.log(buffer.toString());
26         //写入'数据内'三个字
27         fs.write(fd, buffer, 12, 9, null, function (err, written, buffer) {
28           console.log(buffer.toString());
29         })
30       }
31     });
32   }
33 });

(3)刷新缓存区;

fs.fsync(fd, [callback])
 1 // 使用fs.write写入文件时,操作系统是将数据读到内存,再把数据写入到文件中,当数据读完时并不代表数据已经写完,因为有一部分还可能在内在缓冲区内。
 2 // 因此可以使用fs.fsync方法将内存中数据写入文件;--刷新内存缓冲区;
 3
 4 //fs.fsync(fd, [callback])
 5 /**
 6  * fd, 使用fs.open打开成功后返回的文件描述符
 7  * [callback(err, written, buffer)], 写入操作执行完成后回调函数,written实际写入字节数,buffer被读取的缓存区对象
 8  */
 9
10 fs.open(__dirname + '/test.txt', 'a', function (err, fd) {
11   if(err)
12     throw err;
13   var buffer = new Buffer('我爱nodejs编程');
14   fs.write(fd, buffer, 0, 9, 0, function (err, written, buffer) {
15     console.log(written.toString());
16     fs.write(fd, buffer, 9, buffer.length - 9, null, function (err, written) {
17       console.log(written.toString());
18       fs.fsync(fd);
19       fs.close(fd);
20     })
21   });
22 });

注意:每个fd都要调用fs.close(fd)关闭流对象,否则会出错。

我们使用上面介绍的三个fs的api函数完成将画布对象信息写入context.json文件的代码如下:

 1 //保存context文件
 2  saveContext() {
 3      var that = this;
 4      try {
 5          var dtoCore = editor.getDtoCore(true, false);
 6          var dtoCoreObj = JSON.decycle(dtoCore, true);
 7          var context = JSON.stringify(dtoCoreObj);
 8          Common.FileSytem.fsExt.open(Common.FileSytem.contextDir + this.saveContextPath + ".tmp", "w", function (err, fd) {
 9              if (err) {
10                  Common.Logger.setErrLog(Common.LogCode.saveContext, "文件:AutoSaveContext,saveContext方法出错:" + err.message);
11                  Common.FileSytem.fsExt.closeSync(fd);
12              } else {
13                  Common.FileSytem.fsExt.write(fd, context, function (err) {
14                      if (err) {
15                          Common.Logger.setErrLog(Common.LogCode.saveContext, "文件:AutoSaveContext,saveContext方法出错:" + err.message);
16                          Common.FileSytem.fsExt.closeSync(fd);
17                      } else {
18                          Common.FileSytem.fsExt.fsync(fd, function (err) {
19                              if (err) {
20                                  Common.Logger.setErrLog(Common.LogCode.saveContext, "文件:AutoSaveContext,saveContext方法出错:" + err.message);
21                                  Common.FileSytem.fsExt.closeSync(fd);
22                              } else {
23                                  Common.FileSytem.fsExt.closeSync(fd);
24                                  Common.FileSytem.fsExt.rename(Common.FileSytem.contextDir + that.saveContextPath + ".tmp", Common.FileSytem.contextDir + that.saveContextPath, function (err) {
25                                      if (err) {
26                                          Common.Logger.setErrLog(Common.LogCode.saveContext, "文件:AutoSaveContext,saveContext方法出错:" + err.message);
27                                      }
28                                  });
29                              }
30                          })
31                      }
32                  })
33              }
34          });
35      } catch (err) {
36          Common.Logger.setErrLog(Common.LogCode.saveContext, "文件:AutoSaveContext,saveContext方法出错:" + err.message);
37      }
38
39      this.lastSaveTime = Date.now();//执行本次保存的具体时间点
40  }

注意:跟保存作品一样,为避免一个已存在context文件再次保存时失败将已存在的正确文件覆盖掉,我们新建文件context.json.tmp,文件写入成功后再重命名为context.json文件。

检查是否有需要修复文件

在关闭软件窗口时需要判断是否有需要修复文件,以此得出是否要删除资源

在软件打开时也需要判断是否有需要修复文件,以此控制是否需要弹出恢复文件窗口

 1 //检查是否有需要修复的文件
 2 isNeedToRestore(callback: Function = null) {
 3     var that = this;
 4     var fileList = Common.FileSytem.readDirSync(Common.FileSytem.contextDir);//如果context文件夹下没有文件时,说明没有需要修复的文件再进行清除
 5     fileList.forEach(function (name, i) {
 6         if (name.indexOf(".tmp") == -1) {//临时文件.tmp不包含在内
 7             that.needRestoreNames.push(name);
 8         }
 9     })
10     if (that.needRestoreNames.length >= 1) {
11         var allWindows = chrome.app.window.getAll();//获取打开软件窗口的个数
12         if (that.needRestoreNames.length >= 1 && allWindows.length == 1) {//如果context.json有多个,且只打开一个软件窗口情况
13             return true;
14         } else {
15             return false;
16         }
17
18     } else {
19         return false;
20     }
21 }

恢复文件

跟保存文件的过程是一样的《软件项目技术点(19)——文件的保存和打开(解压缩)》

fs用法参考资料:

http://www.jianshu.com/p/5683c8a93511

转载于:https://www.cnblogs.com/fangsmile/p/6283560.html

软件项目技术点(21)——自动保存和恢复相关推荐

  1. 软件项目技术路线图_创建基本的项目路线图

    软件项目技术路线图 Continuing from my previous article, at this checkpoint, I have two things with me: 上一篇文章的 ...

  2. 软件项目技术路线图_为您的项目创建路线图

    软件项目技术路线图 Scrum has a tool for roadmap and release planning as well. We use two different mechanisms ...

  3. 软件项目技术点(19)——文件的保存和打开(解压缩)

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 保存文件 保存内容有哪些? 我们需要保存的内容信息 1)context.json 存储画布状态信息和所有元素的配置信息(这个文件在过程 ...

  4. 软件项目技术点(7)——在canvas上绘制自定义图形

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 图形种类 目前我们软件可以绘制出来的形状有如下这几种,作为开发者我们一直想支持用户可以拖拽的类似word里面图形库,但目前还没有找到比 ...

  5. 软件项目技术点(20)——导出视频

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 导出的视频和播放器自动播放效果时一样的,这样用户就可以传到视频网站分享出去,或者mp4文件发送分享给朋友. 导出视频过程 我们导出视频 ...

  6. 软件项目技术点(1)——d3.interpolateZoom-在两个点之间平滑地缩放平移

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 软件参考d3的知识点 我们在软件中主要用到d3.js的核心函数d3.interpolateZoom - 在两个点之间平滑地缩放平移.请 ...

  7. 软件项目技术点(2)——Canvas之获取Canvas当前坐标系矩阵

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 前言 在我的另一篇博文 Canvas坐标系转换 中,我们知道了所有的平移缩放旋转操作都会影响到画布坐标系.那在我们对画布进行了一系列操 ...

  8. 软件项目技术点(9)——如何将gif动态图拆分绘制

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 背景介绍 我们的软件支持插入gif图片,并且展示在软件里是动态的,例如插入下面这张gif图. 在软件里显示的同样是这样的动态效果: 那 ...

  9. 软件项目技术点(1)——Tween算法及缓动效果

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 Tween算法及缓动效果 软件里在切换步序时需要有过渡动画效果,从当前位置的画面缓动到目标位置的画面.动画效果可重新查看文章系列第一篇 ...

最新文章

  1. zend studio 10破解/汉化
  2. mask rcnn算法原理图_基于MASK RCNN算法实现瑕疵图像识别(训练模型及应用)
  3. Fiddler本机调试的方法
  4. VTK:隐式函数之ImplicitSphere
  5. 进腾讯实习要交钱?腾讯2021年开除70名员工,拉黑13家公司
  6. 专科计算机专业大学,计算机专业大学排名 专科生学计算机专业好吗
  7. shell中shift作用
  8. s8050三极管经典电路_电子电路系统的基本概念有哪些?
  9. 返回表对象的方法之一--bulk collect into
  10. linux 中软件安装的三种方法
  11. 内网神器cobaltstrike使用教程
  12. 系泊系统的设计界_如何回馈设计界
  13. 题目【物联网控制技术第五章】【幅频特性】【相频特性】【波特图】【奈奎斯特图】
  14. Java ques: Exception in thread “main“ java.lang.ClassNotFoundException
  15. 命令提示符中的一些基本命令
  16. 使用LINUX云服务器搭建web、小程序服务器MySql+Java+Tomcat
  17. 人人都能看懂的Spring底层原理,看完绝对不会懵逼
  18. 为什么很多企业都在使用短信群发?原来是有3大好处!
  19. 抖音服务器升级暂时不能修改简介,抖音简介修改内容暂不可用,抖音简介哪些内容不能用...
  20. 生肖迷宫之如何辨别福娃衰娃

热门文章

  1. [C] zintrin.h: 智能引入intrinsic函数 V1.01版。改进对Mac OS X的支持,增加INTRIN_WORDSIZE宏...
  2. 黄聪:Python+NLTK自然语言处理学习(三):计算机自动学习机制
  3. 通过iTextSharp为PDF添加带有超链接的Bookmark
  4. 让协同工作更加轻松——Office 2007面面观之(8)
  5. Xamarin iOS编写第一个应用程序创建工程
  6. html5基础知识文档,HTML5基础知识(1)
  7. 分布式锁的应用场景_分布式缓存技术Redis:高级应用(主从、事务与锁、持久化)...
  8. Excel ,三步 快速实现应用一个公式到一列或一行中
  9. 爱立信和威瑞森电信使用VR流式车来测试5G
  10. 米哈游蔚来领投“人造太阳”项目!首轮融资4亿,北大物理系校友初创企业:走高温超导路线...