程序意外推出,文件流存储

顫_栗 2015-01-24 04:58:37
由于是程序员初学者,写出来的程序,用户误操作会引发相对比较多的意外退出。

那么问题来了,由于文件流没有及时关闭,那么之前存储的数据就会丢失。

我想知道大家是怎么应付这种情况的?

我现在暂时用的解决办法是:
1.尽量catch到每一个异常,但肯定还是会存在捕获不到的异常,而且我目前比较浮躁,暂时比较烦去处理这些细节问题。
2.不断的开启和关闭数据流,每存一部分数据就关闭,然后再开启。这样可能会大大影响效率?底层基础比较弱,我也没有仔细去测试。
...全文
108 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
winnowc 2015-01-25
  • 打赏
  • 举报
回复
还少说了个finally。除非被强行结束,否则finally中的代码都会执行(其实也存在例外)。所以也可以把Flush的逻辑写到finally里。
winnowc 2015-01-25
  • 打赏
  • 举报
回复
频繁Flush当然会影响些性能,不过只要在能够接受的范围内就可以,像StreamWriter类也有AutoFlush属性自动Flush。也可以自己设置FileStream的buffer的大小,它默认是4KB。(这个Flush也不能确保写到磁盘,不过一般场合就够了) 一般情况,用户的非法操作导致的异常是在UI线程。如果是winform可以使用Application.ThreadException截获所有UI上的异常。类似的wpf上有Dispatcher.UnhandledException。这种UI线程上的截获一般更"靠近"异常发生的地方,所以先通过这些来统一处理。这样子程序可能还能恢复成可用的状态。 然后,可以使用AppDomain的UnhandledException事件,统一对没有截获的异常做处理。但是这个时候已经无法阻止程序退出了。当然如果是被任务管理器强制结束,那这些事件都没有。 最理想的方式是把UI和接收数据写文件的进程彻底隔离。使用一个新的进程来接收数据和写文件,UI只是和这个进程进行进程间交互。那么UI的异常只要不给工作进程发错误的指令就没有关系。这样也利于一组人维护底层,另一组人维护UI,甚至做多版本UI,比如迅雷就是这么做的。
顫_栗 2015-01-25
  • 打赏
  • 举报
回复
引用 11 楼 github_22161131 的回复:
频繁Flush当然会影响些性能,不过只要在能够接受的范围内就可以,像StreamWriter类也有AutoFlush属性自动Flush。也可以自己设置FileStream的buffer的大小,它默认是4KB。(这个Flush也不能确保写到磁盘,不过一般场合就够了) 一般情况,用户的非法操作导致的异常是在UI线程。如果是winform可以使用Application.ThreadException截获所有UI上的异常。类似的wpf上有Dispatcher.UnhandledException。这种UI线程上的截获一般更"靠近"异常发生的地方,所以先通过这些来统一处理。这样子程序可能还能恢复成可用的状态。 然后,可以使用AppDomain的UnhandledException事件,统一对没有截获的异常做处理。但是这个时候已经无法阻止程序退出了。当然如果是被任务管理器强制结束,那这些事件都没有。 最理想的方式是把UI和接收数据写文件的进程彻底隔离。使用一个新的进程来接收数据和写文件,UI只是和这个进程进行进程间交互。那么UI的异常只要不给工作进程发错误的指令就没有关系。这样也利于一组人维护底层,另一组人维护UI,甚至做多版本UI,比如迅雷就是这么做的。
正准备睡觉,看到您的回答,感觉您的回答是我最想要的东西,谢谢!当然其他人的回答也让我受益良多,结贴睡觉~~~
SPFarmer 2015-01-24
  • 打赏
  • 举报
回复
引用 7 楼 u010412702 的回复:
[quote=引用 3 楼 sp1234 的回复:] [quote=引用 楼主 u010412702 的回复:] 2.不断的开启和关闭数据流,每存一部分数据就关闭,然后再开启。这样可能会大大影响效率?底层基础比较弱,我也没有仔细去测试。
成员不怕不怎会搜索和抄袭代码,怕的就是根本没有一个正确的开发工程师基本文化素养。如果你纠结于“效率”胜过在意正确性,如果你因为“我确实浮躁因而没有耐心去仔细测试”的借口而写try...catch,其实有经验的技术经理一眼就能看出你是“人品有问题”,这就很容易在将来不断重复造成程序有问题。[/quote] 你理解错了。。。而且从你的语气明显表现出对新手的不满,一个小技术问题都能牵涉到人品,如果我想草草了事就不会在这来询问意见了。 我说的效率是重复不断的flush,会影响效率,比如下位机传数据太频繁的话肯定会受到影响。 我周围没有人写过这种东西,所以希望通过网络询问他人的办法,或许能获得更多的思路。虽然您可能会觉得这些东西太简单,就不应该来发问,应该自己好好学习基础,我是在不断学习,但我不认为我在这发问有什么不对,我也并不是完全寄托网络的懒人。[/quote] 其实sp1234 的回复里,还是很有技术含量的,从另一个层面教你怎么写程序。忠言逆耳吧。
SPFarmer 2015-01-24
  • 打赏
  • 举报
回复
引用
而接收方之后再写完到磁盘里,
而接收方只有在写完到磁盘里
SPFarmer 2015-01-24
  • 打赏
  • 举报
回复
引用 6 楼 u010412702 的回复:
[quote=引用 4 楼 SPFarm 的回复:] 文件流有一个flush方法。每次你写完了就flush一次,那么内存里的内容就被写到磁盘上了。即使程序意外退出了,之前的内容已经在磁盘上了,所以不会丢失。
下位机来了数据就存,但是下位机传数据基本是不间断的,期间如果用户非法操作或者强制结束程序,那么保存的数据就会丢失,我现在改成每来一个数据写完就flush一次。总感觉这样做不好,所以想了解下大家类似问题是怎么做的。[/quote] 你这里提到了两个导致异常的情况: (1)用户非法操作。 这个应该是写程序的时候去避免,不要让用户的操作影响你的后台逻辑。因此要防止用户“误”操作。实际上用户是没有误操作的,你写的程序,用户想怎么点就怎么点,你要做的就是对用户的每次操作做合法性检查。这个做好的话,这个问题就无存在了。 (2)强制结束程序。 这个谁都没有办法。 如果你觉得每次都flush影响效率的话,那么可以这么做: 写一个buffer类。这个类可以存储64K的byte。每次你接到数据,不要直接写到文件里,而是写到buffer里。然后buffer来控制什么时候去往内存上写。 这个会降低往磁盘写的频率,但是还是存在一样的问题,程序被强制结束了,buffer里的数据就丢失了。 因此,对于强制退出的问题,就不能从及时往磁盘写的角度考虑了。而是要考虑重连,断线续传等。 一个简单的断点续传的原理,就是只有发送方接到接收方返回的消息,才继续发下一个数据包。而接收方之后再写完到磁盘里,才给发送方返回消息。这样就不会有数据丢失了。
顫_栗 2015-01-24
  • 打赏
  • 举报
回复
引用 3 楼 sp1234 的回复:
[quote=引用 楼主 u010412702 的回复:] 2.不断的开启和关闭数据流,每存一部分数据就关闭,然后再开启。这样可能会大大影响效率?底层基础比较弱,我也没有仔细去测试。
成员不怕不怎会搜索和抄袭代码,怕的就是根本没有一个正确的开发工程师基本文化素养。如果你纠结于“效率”胜过在意正确性,如果你因为“我确实浮躁因而没有耐心去仔细测试”的借口而写try...catch,其实有经验的技术经理一眼就能看出你是“人品有问题”,这就很容易在将来不断重复造成程序有问题。[/quote] 你理解错了。。。而且从你的语气明显表现出对新手的不满,一个小技术问题都能牵涉到人品,如果我想草草了事就不会在这来询问意见了。 我说的效率是重复不断的flush,会影响效率,比如下位机传数据太频繁的话肯定会受到影响。 我周围没有人写过这种东西,所以希望通过网络询问他人的办法,或许能获得更多的思路。虽然您可能会觉得这些东西太简单,就不应该来发问,应该自己好好学习基础,我是在不断学习,但我不认为我在这发问有什么不对,我也并不是完全寄托网络的懒人。
顫_栗 2015-01-24
  • 打赏
  • 举报
回复
引用 4 楼 SPFarm 的回复:
文件流有一个flush方法。每次你写完了就flush一次,那么内存里的内容就被写到磁盘上了。即使程序意外退出了,之前的内容已经在磁盘上了,所以不会丢失。
下位机来了数据就存,但是下位机传数据基本是不间断的,期间如果用户非法操作或者强制结束程序,那么保存的数据就会丢失,我现在改成每来一个数据写完就flush一次。总感觉这样做不好,所以想了解下大家类似问题是怎么做的。
SPFarmer 2015-01-24
  • 打赏
  • 举报
回复
另外,你的流是一直开着的吗?比较好的做法是,真正需要往磁盘写的时候再开启流,在写完之前不要有任何其他的操作,一直到写完。 看你的需求,好像是流一直开着,用户可以随时操作?最好不要这样。
SPFarmer 2015-01-24
  • 打赏
  • 举报
回复
文件流有一个flush方法。每次你写完了就flush一次,那么内存里的内容就被写到磁盘上了。即使程序意外退出了,之前的内容已经在磁盘上了,所以不会丢失。
  • 打赏
  • 举报
回复
引用 楼主 u010412702 的回复:
2.不断的开启和关闭数据流,每存一部分数据就关闭,然后再开启。这样可能会大大影响效率?底层基础比较弱,我也没有仔细去测试。
成员不怕不怎会搜索和抄袭代码,怕的就是根本没有一个正确的开发工程师基本文化素养。如果你纠结于“效率”胜过在意正确性,如果你因为“我确实浮躁因而没有耐心去仔细测试”的借口而写try...catch,其实有经验的技术经理一眼就能看出你是“人品有问题”,这就很容易在将来不断重复造成程序有问题。
  • 打赏
  • 举报
回复
你不可能给每一行都写上try...catch吧?即使你写了,你除了再次多余地抛出异常或者给用户一个“出错了”这样的提示,你能“解决”什么问题吗? try...catch不能解决任何问题。所以把这个说成是解决了问题,是自欺欺人和欺瞒上级检查的做法(假设上级根本不深入测试是否数据混乱)。如果你某条语句try...catch之后还继续执行下一条语句,那么你的程序将在滚雪球一般的多么巨大的错误数据下继续处理和保存完全错误的数据啊?! 真正的做法,是一个程序只有在表现层——最外层——统一地捕获异常,然后给用户提示。而在内部各层并不try...catch。 并且,只有在Release版本中才会启用这个(只有几行代码的)表现层异常处理程序。在Debug版本中绝不启用它。 在Debug版本,也就是开发和测试阶段所使用的程序版本,它的目的就是尽可能早地重复发现你发现的这种Bug。这个阶段发现Bug是“万幸”,发现了这类问题那么后边的工作就不用做了,就应该先把这个Bug消灭掉,才敢于进行接下来的开发工作。因此如果说“不断的开启和关闭数据流,每存一部分数据就关闭,然后再开启”这能让Bug(在Debug,也就是不靠表现层给用户一个伪装的“友好提示”时)被消灭掉,谁还扯什么“大大影响效率”的淡呢?谁不想弄一个“又不影响效率又没有Bug的程序呢”?如果连正确性都没有了,纠结“效率”不就多余了嘛! 只有极个别的(但是属于正常业务流程)情况下,由于.net类库没有封装好异常隔离机制,我们才需要写try...catch。比如你的代码中有整数运算
a = b /c;
这样的语句,那么你就必须写
if(c!=0)
这样的判断语句,走正常业务流程设计,而不应该写什么try...catch。 所以上述两个Debug原则(不要写try...catch、要保证程序稳定运行)都需要遵守。
bdmh 2015-01-24
  • 打赏
  • 举报
回复
你写数据时,加一个catch就行了,catch中提交

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧