目录

介绍

例子

结论


在审查和重构现实世界的代码库时,我注意到byte[] API是如何被滥用的。这就是为什么在本文中我要分享一些关于为什么不应该在代码中逃避Stream API的想法的原因。

介绍

在处理文件时,通常有两个API同时操作byte[]和Stream,因此人们经常选择byte[]对应的API ,因为它需要较少的仪式或直观地更清晰。

您可能认为这个结论牵强,但我决定在审查和重构一些实际生产代码后写下它。因此,您可能会发现在您的代码库中忽略了这个简单的技巧,就像我在之前的文章中提到的其他一些简单的事情一样。

例子

让我们看一个像计算文件哈希一样简单的例子。尽管它很简单,但有些人认为唯一的方法是将整个文件读入内存。

有经验的读者可能已经预见到这种方法的问题。让我们看看对900MB文件做一些基准测试,看看问题是如何表现出来的,以及我们如何规避它。

基线将是从byte[]源计算哈希的天真解决方案:

public static Guid ComputeHash(byte[] data)
{using HashAlgorithm algorithm = MD5.Create();byte[] bytes = algorithm.ComputeHash(data);return new Guid(bytes);
}

因此,按照文章标题的建议,我们将添加另一个方法,该方法将接受Stream将其转换为byte数组并计算哈希。

public async static Task<Guid> ComputeHash(Stream stream, CancellationToken token)
{var contents = await ConvertToBytes(stream, token);return ComputeHash(contents);
}private static async Task<byte[]> ConvertToBytes(Stream stream, CancellationToken token)
{using var ms = new MemoryStream();await stream.CopyToAsync(ms, token);return ms.ToArray();
}

然而,从byte[]计算哈希并不是唯一的选择。还有一个接受Stream 的重载。让我们使用它。

public static Guid ComputeStream(Stream stream)
{using HashAlgorithm algorithm = MD5.Create();byte[] bytes = algorithm.ComputeHash(stream);stream.Seek(0, SeekOrigin.Begin);return new Guid(bytes);
}

结果很有说服力:

那么这里发生了什么?虽然我们试图盲目地遵循文章中的建议,但并没有帮助。这些图中的关键要点是使用Stream允许我们以块的形式处理文件,而不是天真地将它们加载到内存中。虽然您可能不会在小文件上注意到这一点,但是一旦您必须处理大文件,立即将它们加载到内存中就会变得非常昂贵。

大多数与.NET一起使用byte[]的方法已经展示了Stream对应方法,因此使用它应该没有问题。当您提供自己的API时,您应该考虑提供一种以强大的逐批方式运行Stream的方法。

让我们使用以下代码检查两个stream是否相等来作为另一个示例:

private const int bufferSize = 2048;public static bool IsEqual(this Stream stream, Stream otherStream)
{if (stream is null) return false;if (otherStream is null) return false;if (stream.Length != otherStream.Length) return false;if (stream == otherStream) return true;byte[] buffer = new byte[bufferSize];byte[] otherBuffer = new byte[bufferSize];while (stream.Read(buffer, 0, buffer.Length) > 0){otherStream.Read(otherBuffer, 0, otherBuffer.Length);if (!otherBuffer.SequenceEqual(buffer)){stream.Seek(0, SeekOrigin.Begin);otherStream.Seek(0, SeekOrigin.Begin);return false;}}stream.Seek(0, SeekOrigin.Begin);otherStream.Seek(0, SeekOrigin.Begin);return true;
}

在这里,我们没有将两个潜在的大文件加载到内存中,而是使用2KB的块来比较它们。一旦块不同,我们就退出。

结论

Stream API允许逐批处理,这使我们能够减少大文件的内存消耗。虽然乍一看,Stream API似乎需要更多的仪式,但它绝对是一个人工具箱中的有用工具。

https://www.codeproject.com/Tips/5308853/Prefer-using-Stream-to-byte

更喜欢使用Stream到byte[]相关推荐

  1. 纸上原型设计 VS 桌面原型工具设计,你更喜欢谁?

    2019独角兽企业重金招聘Python工程师标准>>> 纸上原型设计,作为传统的原型设计方式,简单快速,成本低廉,为大部分设计师所喜爱.而桌面原型工具设计,作为伴随电脑科技发展而出现 ...

  2. AI一分钟 | 刚爆Python将进入高考,AI就已强势进入公务员国考试卷;报告称1/4男性更喜欢跟机器人谈恋爱,真的吗?

    一分钟AI 人工智能进入国考试卷 上百万人参加2018年度国考笔试,我们距离AI还有多远? 发改委正在牵头制定智能汽车创新发展战略,2级水平以上的自动驾驶在2020年要达到10%左右 未来你会跟机器人 ...

  3. 南京、苏州、杭州、上海你更喜欢哪座城市?

    南京.苏州.杭州.上海你更喜欢哪座城市? 这个问题笔者来回答,实在是很合适.笔者在这四个城市里工作过,以出差做SAP咨询项目的方式,在这些城市里至少生活过半年.在这些城市生活期间笔者游历了这些城市的各 ...

  4. C# Stream 和 byte[] 之间的转换

    /// <summary> /// 将 Stream 转成 byte[] /// </summary> public byte[] StreamToBytes(Stream s ...

  5. 我为什么更喜欢 Mac OS X

    我为什么更喜欢 Mac OS X 自从苹果的iPhone和iPad在市场上取得傲人的成绩之后,国内的用户对于苹果的MacBook笔记本以及iMac机器的热情也越来越高.但是很多人是买了Apple的电脑 ...

  6. Stream 与 byte[] 互转

    public byte[] StreamToBytes(Stream stream){byte[] bytes = new byte[stream.Length];stream.Read(bytes, ...

  7. (转)javascript 杂谈之哪种写法你更喜欢?

    原文地址:http://www.cnblogs.com/baochuan/archive/2012/04/30/2473771.html 思维导图 介绍 老是在写js,你平时是怎么写你的js呢?更喜欢 ...

  8. 现在使用控件, 更喜欢继承(覆盖控件已有的函数,很奇怪的一种使用方式)...

    以前写代码, 总是把主单元弄得满满当当; 现在更喜欢把控件比较独立的功能写成一个单元, 改写属性.重载方法...哪怕只有一点点和默认不同, 也喜欢独立出来. 刚刚用到 TListBox, 需要能拖动元 ...

  9. Stream 和Byte[] 之间的转换

    代码  1 //Stream 和Byte[]之间的转换  2 byte[] arr=new byte[stream.Length];//设定arr长度  3   4 stream.Read(arr,0 ...

最新文章

  1. for...in和 for...of
  2. JQUERY打造隐藏在左侧的弹性弹出菜单
  3. sharepoint 2010 如何使用sharepoint多媒体视频播放media webpart功能
  4. C++ STL库的总结以及实现原理
  5. jQuery EasyUI API 中文文档 - 日期框(DateBox)
  6. vs2008调试c#网页时出现“加载配置文件时出错: 未能映射路径'/' 错误 .
  7. PC远程调试移动设备
  8. 为提高研发和测试质量而规范Scrum项目需求描述
  9. Linux中Shell数组的笔记
  10. 【测绘程序设计】高斯克吕格投影:带号及中央经度计算神器V1.0(附源程序)
  11. 第二届大数据世界论坛 聚焦行业需求
  12. 自定义列_如何对Pandas DataFrame进行自定义排序
  13. idhttp.post方式 调用datasnap rest 远程方法(转咏南兄)
  14. [Android]Eclipse连不上模拟器的问题[emulator-5554 disconnected](转)
  15. 积分路径上有奇点的积分_【Euler积分】Ch 2. Gamma函数的定义
  16. 定制你自己的CRF模型以及JAVA实现的Word2Vec模型和一些java版NLP的工具
  17. 概率论与数理统计图解
  18. Tensorflow2梯度带tape.Gradient的用法_(全面,深入)
  19. [机器学习] Ubuntu 软件源更新(校园网)以及问题总结
  20. GBIT51233-2016装配式木结构建筑技术标准

热门文章

  1. 命令 结构_只需一个命令!从你的U盘里读出更多内容
  2. 单结晶体管的导电特性_适用于印刷电子的导电墨水可在纸和PET薄膜上印刷薄膜晶体管...
  3. wegame饥荒一直连接中_谁是老牛?谁是嫩草?WeGame与老牌网游的故事 | 游戏茶馆...
  4. activemq后台管理 看topic消息_17 个方面,综合对比 Kafka、RabbitMQ、RocketMQ、ActiveMQ 四个分布式消息队列...
  5. 支持专业设计师的高端样机素材网
  6. 摄影平铺海报psd模板|简单搭建层次场景海报
  7. UI设计中配色专辑素材|做图配色,一键搞定
  8. 对python的意思_python的意思
  9. python 新式类和旧式类_python新式类和旧式类区别
  10. Ubuntu16.04 配置VNC