.NET C# I/O 操作

本文内容

  • 流 Stream 和基本操作
  • 用于 I/O 的类
  • 通用 I/O Stream 类
  • I/O 与安全
  • 演示
  • 如何向文本文件写入字符串
  • 如何从文本文件读取字符串
  • 如何读取数据文件
  • 如何向字符串写入字符
  • 如何从字符串读取字符
  • 参考资料
  • 修改记录

2008 年毕业时,在解决问题时,第一反映是—— baidu 或 google 一下,身边的很多人都是这么说的。当然也有人说,微软 MSDN 是个好东西,虽然我当时也知道这点,但对于一个没有多少项目经验的人来说,使用 MSDN 的确有些困难。因为你不知道如何在 MSDN 中找到解决问题的办法,换句话说,MSDN 不可能直接告诉你,你的问题如何解决。

但 MSDN 对于一个求知欲强、善于思考、提升编程能力的人来说,是不可或缺的。网上的东西永远只是事物的一个侧面,而 MSDN 却是知识的一个体系。我希望你能明白我的意思:这就好像“信息”和“知识”的区别。“信息”只有经过你自己汇总、比较、反思,无数次的假设和无数次的否定,才能成为“知识”——自己的东西。

凡事都有第一次,我最初使用 MSDN 也是迫于无奈。一是有意识地去使用 MSDN,再就是因为涉密,客户那不允许上网。在这样的情况下,我开始使用 MSDN。通过它的链接,你可以学习到相关的所有问题,加深对知识的理解。

下面就要开始我的问题——.NET I/O 操作。

System.IO 命名空间下,有四种类型的逻辑组:

  • 获取文件和目录的相关信息,执行与文件和目录相关的基本操作;
  • 在路径名上执行基本字符串的操作;
  • 在数据流和文件上进行读写操作;
  • 当给定的目录树上文件和文件夹发生动态变化时,获取相关通知。

本文主要说明前三个。

抽象基类 Stream 支持读写字节。Stream 集成了异步支持。它默认的实现对相应的异步方法定义了同步读写,反之亦然。

所有关于流(Stream)的类都是从 Stream 类继承的。Stream 类和其子类提供了数据源和存储的通用视图,独立于操作系统和底层设备的细节。

流 Stream 和基本操作


.NET System.IO 提供了对两种截然不同类型的数据——流和文件。文件是在磁盘上持久保存的、有序的并且已命名的字节集合。流代表从数据存储区中读取的或要写入数据存储区的字节块;流可以是基于多种存储媒体的。所以,流是文件的超集。

Stream 类支持三种基本操作:

  • 1. 读,是将数据从流中读取到数据结构中保存,如一个字节数组。
  • 2. 写,是将数据结构中的数据写入流中。
  • 3. 搜索。包括查询和修改流中当前的位置。

根据底层数据源或存储,流可能只支持上面这些功能。例如,NetworkStreams 不支持定位(seek),这是显而易见的。Stream 及其子类的 CanReadCanWrite、和 CanSeek 属性确定各种流支持的操作。

 

用于 I/O 的类


  • 1. Directory 全局静态类,提供创建目录、复制目录、移动目录和枚举目录中的文件子目录的静态方法。DirectoryInfo 类提供相应的实例方法。
  • 2. DirectoryInfo 类,Directory 类提供的是静态方法,而 DirectoryInfo 类提供的实例方法。
  • 3. File 全局静态类,提供创建文件、复制文件、删除文件、移动文件、打开文件的静态方法,并且帮助创建一个 FileStream 对象。FileInfo 类提供实例方法。
  • 4. FileInfo 类,File 类提供的是静态方法,而 FileInfo 类提供的是实例方法。但他们的内部实现和编程接口上是有区别的。
  • 5. DriveInfo 类,提供访问驱动器信息的实例方法。
  • 6. FileStream 类,通过Seek方法支持随机访问文件。默认情况下,FileStream 异步打开文件,但也支持同步操作。File 包含静态方法,而 FileInfo 则包含实例方法。
  • 7. FileSystemInfo 是抽象类,FileInfo 和DirectoryInfo 类继承该类。
  • 8. Path 类,提供的方法和属性,用于以跨平台的方式处理目录字符串。
  • 9. DeflateStream 类,提供的方法和属性,使用 Deflate 算法压缩和解压流。
  • 10. GZipStream 类,也是压缩和解压流。默认情况下,这个类和 DeflateStream 一样,但是可以扩展使用其他压缩格式。
  • 11. SerialPort 类,提供的方法和属性,用于控制一个串口文件资源。

File、FileInfo、DriveInfo、Path、Directory 和 DirectoryInfo 都是密封类,你可以创建这些类的实例,但它们不能被继承。

  • 12. BinaryReaderBinaryWriter 类,从流读写编码的字符串和基础数据类型。
  • 13. StreamReader 类,通过 Encoding 把字符转换成字节,从流中读取字符串。StreamReader 有一个构造函数,尝试确定一个给定流的正确 Encoding。这是基于一个特定编码序言,例如一个字节顺序标记。
  • 14. StreamWriter 类,通过 Encoding 把字符转换成字节,像流中写入字符。
  • 15. StringReader 类,从字符串读取字符。StringReader 允许你用相同的 API 来对待字符串,因此,你的输出可以是一个任意编码的流,或是一个字符串。
  • 16. StringWriter 类,把字符写入到字符串。StringWriter  允许你用相同的 API 来对待字符串,因此,你的输出可以是一个任意编码的流,或是一个字符串。
  • 17. TextReader 类是抽象类,StreamReader 和 StringReader 继承该类。抽象的 Stream 类的实现是为了字节的输入和输出设计的,而 TextReader 的实现是为 Unicode 字符输出设计的。
  • 18. TextWriter 类是抽象类,StreamWriter 和 StringWriter 继承该类。抽象的 Stream 类的实现是为了字节的输入和输出设计的,而 TextWriter 的实现是为 Unicode 字符输入设计的。

 

通用 I/O Stream 类


1. BufferedStream 类,将一个缓冲区添加到另一个流中,比如网络流 NetworkStream。(FileStream 已经进行了内部缓冲,MemoryStream 不需要缓冲)BufferedStream 可以有很多类型的流组成,以提高读写性能。缓冲区是内存中的一个块字节用于缓存数据,从而减少了操作系统的调用次数。

2. CryptoStream 类,将数据流链接到加密转换的流。尽管它继承了 Stream,但是并不在 System.IO 命名空间,而是在 System.Security.Cryptography 里。

3. MemoryStream 类,是一个非缓冲的流,它封装的数据在内存中可以直接访问。这个流没有后备存储,作为一个临时缓冲很有用。

4. NetworkStream 类,是一个网络连接的流。尽管它继承了 Stream 类,但是它并不在 System.IO 命名空间,而是在 System.Net.Sockets 里。

 

I/O 与安全


当使用 System.IO 命名空间中的类时,允许的访问必须满足操作系统的安全需要,如访问控制列表(ACL)。这个需求除了任何 FileIOPermission 需要的。

备注:ACL 可以由程序管理。For more information, see How to: Add or Remove Access Control List Entries and ACL Technology Overview.

注意:Internet 和 intranet 默认的安全策略不允许访问文件。因此,如果你编写需要通过网络下载的代码,就不能使用正规的非隔离存储(nonisolated storage )I/O 类,而应该使用隔离存储(Isolated Storage)。

当打开一个文件或是网络流,安全检查只有在流构造时才会进行。因此,当向不太受信任的代码或是应用程序域提交这些流是,应该谨慎。

以上就是基本文件 I/O 操作的相关类,看过之后,你多半还是有些迷糊,但你至少已经知道文件 I/O 涉及了哪些方面,如读、写、字节数组、字符串、文件,还有访问控制列表,这些“关键字”就是信息,之后就要靠你自己把这些信息,形成一个体系——文件 I/O。MSDN 给出了几个完整的例子,比如,如何读写二进制文件;如何读写文本文件;如何读写字符串等等,我觉得不错。

 

演示


如何向文本文件写入字符串

例一,演示如何向一个已经存在的文件添加文本;例二,演示如何创建一个新的文件,并向它写入一个字符串。WriteAllText 方法也提供类似的功能。

例一

using System;
using System.IO;
class Test 
{
    public static void Main() 
    {
        using (StreamWriter sw = new StreamWriter("TestFile.txt")) 
        {
            sw.Write("This is the ");
            sw.WriteLine("header for the file.");
            sw.WriteLine("-------------------");
            sw.Write("The date is: ");
            sw.WriteLine(DateTime.Now);
        }
    }
}

例二

using System;
using System.IO;
public class TextToFile 
{
    private const string FILE_NAME = "MyFile.txt";
    public static void Main(String[] args) 
    {
        if (File.Exists(FILE_NAME)) 
        {
            Console.WriteLine("{0} already exists.", FILE_NAME);
            return;
        }
        using (StreamWriter sw = File.CreateText(FILE_NAME))
        {
            sw.WriteLine ("This is my file.");
            sw.WriteLine ("I can write ints {0} or floats {1}, and so on.", 1, 4.2);
            sw.Close();
        }
    }
}

如何从文本文件读取字符串

第二个例子添加了检测文件结束。通过 ReadAll() 和 ReadAllText() 方法能实现同样的功能。

例一

using System;
using System.IO;
class Test 
{
    public static void Main() 
    {
        try 
        {
            using (StreamReader sr = new StreamReader("TestFile.txt")) 
            {
                String line;
                while ((line = sr.ReadLine()) != null) 
                {
                    Console.WriteLine(line);
                }
            }
        }
        catch (Exception e) 
        {
            Console.WriteLine("The file could not be read:");
            Console.WriteLine(e.Message);
        }
    }
}

例二

using System;
using System.IO;
public class TextFromFile 
{
    private const string FILE_NAME = "MyFile.txt";
    public static void Main(String[] args) 
    {
        if (!File.Exists(FILE_NAME)) 
        {
            Console.WriteLine("{0} does not exist.", FILE_NAME);
            return;
        }
        using (StreamReader sr = File.OpenText(FILE_NAME))
        {
            String input;
            while ((input=sr.ReadLine())!=null) 
            {
                Console.WriteLine(input);
            }
            Console.WriteLine ("The end of the stream has been reached.");
            sr.Close();
        }
    }
}

如何读取数据文件

BinaryReader 和 BinaryWriter 类用来读写数据,而不是字符串。下面的例子演示读写数据。

using System;
using System.IO;
class MyStream 
{
    private const string FILE_NAME = "Test.data";
    public static void Main(String[] args) 
    {
        if (File.Exists(FILE_NAME)) 
        {
            Console.WriteLine("{0} already exists!", FILE_NAME);
            return;
        }
        FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew);
        BinaryWriter w = new BinaryWriter(fs);
        for (int i = 0; i < 11; i++) 
        {
            w.Write( (int) i);
        }
        w.Close();
        fs.Close();
        fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
        BinaryReader r = new BinaryReader(fs);
        for (int i = 0; i < 11; i++) 
        {
            Console.WriteLine(r.ReadInt32());
        }
        r.Close();
        fs.Close();
    }
}

说明:如果 Test.data 文件在当前目录已经存在,会抛出 IOException 异常。

如何向字符串写入字符

下面的例子演示用 StringWriter 类向一个字符串写入字符数组中的字符。

using System;
using System.IO;
using System.Text;
public class CharsToStr
{
    public static void Main(String[] args)
    {
        StringBuilder sb = new StringBuilder("Some number of characters");
        char[] b = {' ','t','o',' ','w','r','i','t','e',' ','t','o','.'};
        StringWriter sw = new StringWriter(sb);
        sw.Write(b, 0, 3);
        Console.WriteLine(sb);
        sw.Close();
    }
}

如何从字符串读取字符

下面的例子演示用StringRead类从字符串读取字符。

using System;
using System.IO;
public class CharsFromStr
{
    public static void Main(String[] args)
    {
        String str = "Some number of characters";
        char[] b = new char[24];
        StringReader sr = new StringReader(str);
        sr.Read(b, 0, 13);
        Console.WriteLine(b);
        sr.Close();
    }
}

 

 

参考资料


  • System.IO 命名空间
  • MSDN 文件和流 I/O
  • MSDN 文件 I/O(C#与Java)
  • MSDN 异步文件 I/O
  • VS 2012 使用 Async 和 Await 的 异步编程

 

修改记录


  • 2015-1-17 [add]

转载于:https://www.cnblogs.com/liuning8023/archive/2011/08/28/2156546.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/422795.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言进阶深度学习记录】二十七 C语言中字符串的相等比较

文章目录1 字符串的相等比较1.1 代码分析1 字符串的相等比较 如果有字符串s1 “Hello”; s2 “Hello” ; 在我们看来s1与s2相等。但是如果使用 “” 来判断是不准确的。因为在代码中s1与s2是是不同的字符串&#xff0c;它们位于不同的内存空间&#xff08;当然&#xff0c;…

3天搞定的小型B/S内部管理类软件定制开发项目【软件开发实战10步骤详解】

2010-10-07 21:39 by 通用权限组件源码, 16580 visits, 收藏, 编辑 十一休假&#xff0c;杭州西湖边逛了一圈只能用人山人海来形容&#xff0c;浙大紫金港校区也逛了一圈风景如画&#xff0c;建设得真不错很棒&#xff0c;假期就去了这2个地方&#xff0c;然后在家里陪老婆、看…

【C语言进阶深度学习记录】二十八 数组指针与指针数组的分析

数组指针与指针数是非常重要的概念。面试中也是经常会被问到的 文章目录1 数组的类型1.1 定义数组的类型2 数组指针2.1 数组类型和数组指针的代码分析3 指针数组3.1 指针数组代码案例分析4 总结1 数组的类型 C语言中的数组有自己特定的类型。比如 int a[5]&#xff1b; 数组a…

(运维日志)在win7安装Oracle并部署Oracle数据库

部署环境说明&#xff1a; 操 作 系 统&#xff1a;window 7 Oracle 管理应用: pl sql 1 选择支持win7的Oracle版本,下载 目前完全支持win7 操作的oracle 版本为11.2 g 补充说明:Oracle 10g版本发布时间为2003年 Oracle 11g 版本发布时间为2007年 这两个版本在win7操作系统中安…

【C语言进阶深度学习记录】二十九 main函数与命令行参数

文章目录1 main函数的返回值2 main函数的参数2.1 main函数的参数的代码案例分析3 main函数不一定是程序中第一个执行的函数4 总结1 main函数的返回值 main函数是操作系统调用的函数操作系统总是将main函数的返回值作为程序的退出状态main函数的返回值正常来说是0&#xff0c;如…

【C语言进阶深度学习记录】三十 二维数组与二维指针

文章目录1 二维指针&#xff08;指向指针的指针&#xff09;2 二维数组3 二维数组的类型3.2 如何动态申请二维数组4 总结1 二维指针&#xff08;指向指针的指针&#xff09; 指针的本质是变量指针的指针是保存指针变量的地址。如下面的代码&#xff1a; 为什么需要指向指针的存…

Windows Phone 7 开发积累_04

关于产生错误 “The as operator must be used with a reference type or nullable type (System.DateTime is a non-nullable value type) ” 今天写数据转换器&#xff0c;需要将按照时间值显示不同的时间格式字符串。 结果在Convert里发现这么写报错。 public object Conve…

【C语言进阶深度学习记录】三十一 数组作为函数参数时退化为指针

之前的学习数组的文章中&#xff0c;已经知道一维数组作为函数参数的时候&#xff0c;最终会被编译器编译为指针。今天来看看二维数组的情形 文章目录1 为什么C语言中的数组作为函数参数会退化为指针&#xff1f;2 二维数组作为函数参数如何退化2.1 代码案例分析&#xff08;传…

使用HTMLParser模块解析HTML页面

HTMLParser是python用来解析html和xhtml文件格式的模块。它可以分析出html里面的标签、数据等等&#xff0c;是一种处理html的简便途径。HTMLParser采用的是一种事件驱动的模式&#xff0c;当HTMLParser找到一个特定的标记时&#xff0c;它会去调用一个用户定义的函数&#xff…

前端学习(294):rem小实例

altz转换为rem <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible"…

【C语言进阶深度学习记录】三十二 函数指针与使用函数指针实现回调函数

回调函数是非常重要的概念 文章目录1 函数的类型2 函数指针2.1 函数指针的使用2.2 使用函数指针实现回调函数3 总结1 函数的类型 跟以前学数组的时候是一样的&#xff0c;C语言中的数组是有自己的类型的。函数也是有自己的类型的。 函数的类型由返回值、参数的类型、参数的个…

tabs标签切换

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/xhtml"><head> <title>用户信息</title>…

【C语言进阶深度学习记录】三十三 C语言中动态内存分配

如何在程序运行的时候动态给程序分配内存&#xff1f; 文章目录1 动态内存分配的意义1.1 C语言中如何动态申请内存空间1.2 malloc和free的用法1.3 calloc与realloc1.31 calloc和realloc的代码案例分析2 总结1 动态内存分配的意义 在C语言中&#xff0c;一切操作都是基于内存的…

[Cocoa]深入浅出Cocoa之Core Data(2)- 手动编写代码

深入浅出Cocoa之Core Data&#xff08;2&#xff09;- 手动编写代码 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议前面详细讲解了 Core Data 的框架以及设计的类&#xff0c;下面我们来讲解一个完全手动编写代码使用这些类的示…

java并发实战

推荐一个Java并发编程实战的学习专栏。此专栏为极客时间收费专栏。 学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群 &#xff1a; 962535112 对于一个 Java 程序员而言&#xff0c; 能否熟练掌握并发编程是判断他优秀与否的…

a critical review of preetham skylight model 笔记

也是为了试用下Xmind。 上图是我用Xmind作的某篇文章的笔记。 感想&#xff1a; 1. 之以一直觉得这种东西没多大用处&#xff0c;回想起来大概是因为那时没有太多应用场景。 2. 如果留心&#xff0c;可以把许多事情做得更漂亮、更容易&#xff0c;这也是工具的用途。 贴一下软件…

【C语言进阶深度学习记录】三十四 C语言实现内存泄漏检测模块

上一篇文章学习了malloc系列的三个函数的使用。众所周知malloc的使用很容易导致内存泄漏。本文的目的就是使用C语言来实现内存泄漏检测模块&#xff0c;来帮忙自动检测我们写的程序中是否出现内存泄露。 文章目录1 内存泄露检测模块的实现原理1.1 各个函数模块的设计1.2 模块整…

用cookie实现叶卡的记忆功能

之前在写叶卡切换的时候总需要把js代码写到html标签里面。 后来接触了闭包后知到一点点怎么通过闭包实现该功能。 之后又想通过cookie来记忆叶卡的当前位置。 代码如下&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/…

重学前端----前端知识系统学习推荐专栏

推荐一个前端知识学习专栏。此专栏为极客时间收费专栏。 学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 文章目录1 概述2 专栏内容2.1 模块一&#xff0c;JavaScript2.2 模块二&#xff0c;HTML 和 …

【C语言进阶深度学习记录】三十五 程序中的堆、栈以及静态存储区(数据区)

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 在我之前学习底层的知识的时候&#xff0c;也写过相关的内容。可以对比的学习&#xff1a;【软件开发底层知识修炼】二十 深入理解可执行程序的结构&a…