C#要点补充

1字符串与时间的互转

DateTime.TryParse将空字符串、为null或格式不正确,则转换为的DateTime所代表的值为:0001/1/1 0:00:00,此为DateTime.MinValue的值。

使用public static DateTime ParseExact(string s, string format, IFormatProvider provider);实例方法转换时间,可以指定转换的格式。其中format为输入字符s的格式。若指定的格式与输入字符格式不一样,会抛异常

例如:

//dateTime ="2017-11-18 17:25:53";会抛异常,这种类型对应格式为:yyyy-MM-dd HH:mm:ss

string dateTime = "20171118172553";

IFormatProvider yyyymmddFormat = new CultureInfo(String.Empty, false);

DateTime time = DateTime.ParseExact(dateTime, "yyyyMMddHHmmss", yyyymmddFormat);

2比较时间先后

使用DateTime的public int CompareTo(DateTime value);实例方法。

示例:

string dateTime = "2017-11-28 12:57:30";

            DateTime dt;

            DateTime.TryParse(dateTime, out dt);

            int cr = dt.CompareTo(DateTime.Now);

如果cr大于0,dt时间晚于(当前时间)DateTime.Now,即时间的整数值大于DateTime.Now的整数值。

如果cr等于0,dt时间等于(当前时间)DateTime.Now,即时间的整数值等于DateTime.Now的整数值。

如果cr小于0,dt时间早于(当前时间)DateTime.Now,即时间的整数值小于DateTime.Now的整数值。

3 StreamWriter

将文件所在的目录传给StreamWriter的构造函数,而不是传递文件的全路径,那么会抛出如下的异常,看上去似乎是对文件目录没有访问权限,其实是错将文件目录传递给了StreamWriter构造函数。

4将Sream中的数据写入文件

错误的做法一:

获取流的长度然后转型为int,容易造成数据截断,导致未能读取流的全部内容。

        //读取
        long length = 0;
            using (Stream fs = new FileStream("D:\\命令行安装MySQL.docx", FileMode.Open))
            {
                length = fs.Length;
            }
            byte[] bytes = new byte[length];

            using (Stream fs = new FileStream("D:\\命令行安装MySQL.docx", FileMode.Open))
            {
                int countIn = fs.Read(bytes, 0, (int)length);
            }
        //写入
            using (Stream fs = new FileStream("D:\\命令行安装MySQLnew.docx", FileMode.OpenOrCreate))
            {
                fs.Write(bytes, 0, (int)length);
            }

错误做法二:

貌似不会发生错误类型一那样的情况,但还是会出现数据截断的现象。调用FileStream的Read实例方法:Read(byte[] buffer, int offset, int count),offset这个参数的类型是int型,这里将numBytesRead 转型为int,一旦这个偏移量超过这个值,那么读取的数据有一部分就是重复的。

        /读取
         using (Stream fs = new FileStream("D:\\命令行安装MySQL.docx", FileMode.Open))
            {
                int c = 10000;
                long numBytesRead = 0;
                long numBytesToRead = fs.Length;
                while (numBytesToRead>0)
                {
                    if (fs.Length - numBytesRead <= c)
                    {
                        c = (int)(fs.Length - numBytesRead);
                    }
                    int n = fs.Read(bytes, (int)numBytesRead, c);
                    numBytesRead += n;
                    numBytesToRead -= n;
                }
            }
        //写入
            using (Stream fs = new FileStream("D:\\命令行安装MySQLnew.docx", FileMode.OpenOrCreate))
            {
                fs.Write(bytes, 0, (int)length);
            }

正确的做法一:

确保上述错误做法中的源数据长度不超过int32的最大值。此外也可使用下面的方法,但同样要保证源数据长度不超过int32的最大值:

        //读取
        using (Stream fs = new FileStream("D:\\命令行安装MySQL.docx", FileMode.Open))
            {                
                int c = 10000;
                long position = 0;
                while (true)
                {
                    position = fs.Seek(position, SeekOrigin.Begin);
                    if (position == fs.Length)
                    {
                        break;
                    }

                    if (position + c > fs.Length)
                    {
                        c = (int)(fs.Length - position);
                    }
                    int n = fs.Read(bytes, (int)position, c);
                    position += n;
                }
            }
         //写入
            using (Stream fs = new FileStream("D:\\命令行安装MySQLnew.docx", FileMode.OpenOrCreate))
            {
                fs.Write(bytes, 0, (int)length);
            }

正确的做法二:

使用CopyTo(Stream destination)

CopyTo(Stream destination, int bufferSize)

使用第一个方法默认缓冲区大小为4096,现在看下源码片段:

     public void CopyTo(Stream destination)
        {
            ......
 
            InternalCopyTo(destination, _DefaultCopyBufferSize);
        }

CopyTo方法中调用了InternalCopyTo方法,来看下InternalCopyTo方法的源码片段:

      private void InternalCopyTo(Stream destination, int bufferSize)
        {
            ......
            
            byte[] buffer = new byte[bufferSize];
            int read;
            while ((read = Read(buffer, 0, buffer.Length)) != 0)
                destination.Write(buffer, 0, read);
        }

InternalCopyTo方法内部调用了Read方法,下面来看一下Read方法源码片段:

然而在Stream这个类中并没有Read方法的具体实现,只有一个抽象方法:

public abstract int Read([In, Out] byte[] buffer, int offset, int count);

到这里已经可以看出CopyTo方法中的参数bufferSize的作用了,即设置内存缓冲区的大小,每次从流中读取长度为bufferSize的数据,放入缓冲区,然后写入目标流,重复这个过程直到所有的流都拷贝完成。那么在内存允许的范围内,bufferSize设置的越大效率越高。

        using (Stream fs = new FileStream("D:\\命令行安装MySQL.docx", FileMode.Open))
        {
             using(Stream fss = new FileStream("D:\\命令行安装MySQLnew.docx", FileMode.OpenOrCreate))
             {
                 fs.CopyTo(fss);
             }
        }

5文件读写效率与对象频繁开关的影响

写文件方式一:

      public static void W()
         {
             for (int i = 0; i < 1000;i++ )
             {
                 string s = "sdfrgyjefgyhjdsfdfgfghgew"+i;
                 using (StreamWriter sw = new StreamWriter(@"D:\g.txt", true))
                 {
                     sw.Write(s);
                 }
             }
         }

方式二:

      public static void WT()
         {
             using (StreamWriter sw = new StreamWriter(@"D:\gT.txt", true))
             {
                 for (int i = 0; i < 1000; i++)
                 {
                     string s = "sdfrgyjefgyhjdsfdfgfghgew" + i;
                     sw.Write(s);
                 }
             }
         }

分析:

方式一每写一次文件,开关一次StreamWriter对象,而方式二将所有的字符串都写入文件后才关闭StreamWriter实例。统计数据如下:

循环次数

方式一

方式二

100万

21861ms

260ms

1000

231ms

13ms

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

Enterprise Library深入解析与灵活应用(6):自己动手创建迷你版AOP框架

基于Enterprise Library PIAB的AOP框架已经在公司项目开发中得到广泛的使用,但是最近同事维护一个老的项目,使用到了Enterprise L...

1848
来自专栏陈树义

JVM系列第4讲:从源代码到机器码,发生了什么?

在上篇文章我们聊到,无论什么语言写的代码,其到最后都是通过机器码运行的,无一例外。那么对于 Java 语言来说,其从源代码到机器码,这中间到底发生了什么呢?这就...

162
来自专栏Java学习网

常见的 Java 错误及避免方法之第五集(每集10个错误后续持续发布)

当输入期间意外终止文件或流时,将抛出“EOFException”。 以下是抛出EOFException异常的一个示例,来自JavaBeat应用程序:

613
来自专栏智能大石头

XCode读取Excel数据(适用于任何数据库)

虽然是充血模型,虽然是强类型,XCode同样支持遍历任何数据库结构,并以强类型(相对于DataSet等字典访问)方式读取数据。 要遍历数据库结构是很容易的事情,...

1948
来自专栏技术博客

Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化

阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.h...

993
来自专栏JAVA同学会

JAVA 11初体验

  随着JAVA没半年发布一次新版本,前几天JAVA 11隆重登场。在JAVA 11中,增加了一些新的特性和api, 同时也删除了一些特性和api,还有一些性能...

821
来自专栏张善友的专栏

Protocol Buffers的应用

1. Protocol Buffers的介绍 Protocol buffers are Google’s language-neutral, platform-...

18010
来自专栏技术记录

JAVA-FTP批量大文件传输

FTP的具体使用      FTP是一种网络协议,用于进行不同服务器主机之间的文件传输,或者简单地说两台不同IP的机器之间的文件传输。在java中我们什么时候需...

5566
来自专栏PHP在线

9个必须掌握的实用PHP函数和功能

即使使用 PHP 多年,也会偶然发现一些未曾了解的函数和功能。其中有些是非常有用的,但没有得到充分利用。并不是所有人都会从头到尾一页一页地阅读手册和函数参考! ...

2808
来自专栏大内老A

ASP.NET Core中的依赖注入(3): 服务的注册与提供

在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个...

2207

扫码关注云+社区