IO 输入输出

.Net标准库中,System.IO命名空间下包含了和输入/输出操作相关的工具类,包括文件系统操作、文件流、网络流等,这里我们简单介绍其中比较常用的内容。至于网络流相关的内容将在网络编程章节详细介绍。

Stream 流

所谓的Stream流,其实是一种对IO设备进行读写的抽象概念。我们读写的设备可以是磁盘、主存、网卡等,这些设备通常由硬件驱动程序来操作,而.Net为我们进一步封装了一层,将IO设备的读写操作暴露为统一接口,方便我们使用。C#中,所有的流都继承自Stream基类。

流有三个基本操作:

  1. Read 读操作:用于从流中读取数据,对于字节流一般都是读入一个字节数组
  2. Write 写操作:用于向流写入数据,对于字节流一般都是传入一个包含要写数据的字节数组
  3. Seek 设置读写位置:无论读写流都会自动改变一个Position属性,每读写一个字节都会让其增加1,我们也可以手动调用Seek方法设置这个属性实现随机读写

FileStream 文件流

FileStream流用于读写文件系统中的文件,下面代码中,我们从一个文本文件中以字节流方式进行了读取,并打印了其中的内容。

// 开启文件流
FileStream fileStream = File.Open(@"E:\1.txt", FileMode.Open);
// 开辟1024字节的数组
byte[] buffer = new byte[1024];
// 从文件流中读入1024字节数据
fileStream.Read(buffer, 0, buffer.Length);
// 关闭文件流
fileStream.Close();

// 输出读取的内容
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
string str = encoding.GetString(buffer);
Console.WriteLine(str);

上面代码的实现比较简单,只是尝试读取的文件的前1024个字节,如果是一个较大的文件,你可能需要编写一个循环来读取其中的内容。

向文件流写入数据也十分简单,下面是一个例子。

// 开启文件流
FileStream fileStream = File.Open(@"E:/2.txt", FileMode.OpenOrCreate);
// 写入数据
string str = "你好,C#!";
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
byte[] strBytes = encoding.GetBytes(str);
fileStream.Write(strBytes, 0, strBytes.Length);
// 关闭流
fileStream.Close();

代码中,我们将字符串以UTF-8编码转化为了字节数组,并写入字节流。

MemoryStream 内存流

我们进行文件和网络IO操作时,一些临时数据可以存储在内存中,以便进一步处理,MemoryStream用于以流的方式读写一块内存区域。下面例子代码简单演示了其用法。

string str = "你好,C#!";
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
byte[] strBytes = encoding.GetBytes(str);

// 创建内存流
MemoryStream memoryStream = new MemoryStream(new byte[1024]);
// 向内存流写入数据
memoryStream.Write(strBytes, 0, strBytes.Length);
// 将流的读写位置重置
memoryStream.Seek(0, SeekOrigin.Begin);
// 从内存流读取数据
byte[] buf = new byte[1024];
memoryStream.Read(buf, 0, buf.Length);

Console.WriteLine(encoding.GetString(buf));

代码中我们对于同一个内存流,县写入了一部分数据,然后重置了其位置,最后又将数据重新读取了出来。

BufferedStream 缓冲流

BufferedStream需要和FileStream等基础的流类型配合使用,缓冲流使用了内存缓冲区进行块读写,相比直接使用FileStream等能够提高流读写的性能。注意这里所说的缓冲区和上面读写流使用的byte[] buf不是一个层次的概念,缓冲流中的缓冲区是.Net中更为底层的块读写实现。

// 创建缓冲流
FileStream fileStream = File.Open(@"E:\1.txt", FileMode.Open);
BufferedStream bufferedStream = new BufferedStream(fileStream);

// 读取数据
byte[] buf = new byte[1024];
bufferedStream.Read(buf, 0, buf.Length);

// 关闭流
bufferedStream.Close();
fileStream.Close();

System.Text.Encoding encoding = System.Text.Encoding.UTF8;
string str = encoding.GetString(buf);
Console.WriteLine(str);

默认情况下缓冲流使用的缓冲区为4KB,当然我们也可以手动指定其值,读写大文件时,我们可以将其调大。

NetworkStream 网络流

NetworkStream用于从网络套接字(Socket)中读写数据,有关这部分内容将在网络编程章节详细介绍。

字符流

如果读写文本文件,上面使用字节流的方式其实很不方便,我们需要以字节数组形式读取,然后将其转换为对应编码的字符串。对于文本文件.Net提供了StreamReaderStreamWriter,支持以文件行或字符数组的方式进行读取,使用字符流读写文本文件就方便很多了。

下面例子代码演示了如何使用StreamReaderStreamWriter读写文本文件。

// 创建字符读取流
StreamReader streamReader = new StreamReader(@"E:\1.txt");
// 从字符流中读取一行
string s = streamReader.ReadLine();
Console.WriteLine(s);
// 关闭流
streamReader.Close();

// 创建字符写入流
StreamWriter streamWriter = new StreamWriter(@"E:\1.txt");
// 向流中写入数据(覆盖写入)
streamWriter.WriteLine("ha ha ha ~");
// 关闭流
streamWriter.Close();

文件系统操作

我们知道文件系统是操作系统的重要组成部分,文件系统提供了一系列接口用于文件和文件夹的增删改查操作,.Net也对文件系统的操作进行了便利的封装。

文件(File)和目录(Directory)

.NetFileDirectory是两个比较重要的工具类,它们被声明为静态类,其中包含了操作文件和目录的许多实用方法,包括移动、复制和删除文件(文件夹)等;此外,FileInfoDirectoryInfo则是对于文件系统中文件和目录的抽象,这两个类则需要基于真正的文件和文件夹创建实例来使用。这两组API提供的功能其实有些重合,我们实际开发中需要根据具体使用场景具体选择。

// 创建文件
File.Create(@"E:\3.txt");

// 判断文件是否存在
bool exists = File.Exists(@"E:\3.txt");
Console.WriteLine(exists);

// 删除文件
File.Delete(@"E:\2.txt");

// 移动文件
File.Move(@"E:\1.txt", @"E:\2.txt");

// 拷贝文件
File.Copy(@"E:\2.txt", @"E:\1.txt");

// 读取文件所有内容
byte[] buf = File.ReadAllBytes(@"E:\2.txt");
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
string str = encoding.GetString(buf);
Console.WriteLine(str);

上面代码实现了对一些文件的操作,至于Directory其实也是类似的,这里就不多介绍了。

Path 路径操作

Path是一个静态类,提供了对文件系统路径的解析、拼接等一系列操作。对于文件路径,相比我们自己手动操作字符串,使用Path工具类要更加靠谱。

string pathStr = @"E:\1.txt";

// 获取文件名
string filename = Path.GetFileName(pathStr);
// 获取文件名(不带扩展名)
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(pathStr);
// 获取文件的路径名
string directoryName = Path.GetDirectoryName(pathStr);
// 组合路径和文件名为完整的路径
string combinedPath = Path.Combine(@"E:\学习资料", "1.txt");
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap