本文内容
- 流 Stream 涉及的一些基本操作
- 用于文件 I/O 的类
- 通用 I/O Stream 类
- 演示
- 如何向文本文件写入字符串
- 如何从文本文件读取字符串
- 如何读取数据文件
- 如何向字符串写入字符
- 如何从字符串读取字符
抽象基类 Stream 支持读写字节。Stream 集成了异步支持。它默认的实现对它们相应的异步方法定义了同步读写,反之亦然。
所有关于流(Stream)的类都是从 Stream 类继承的。Stream 类和其子类提供了数据源和存储的通用视图,使得程序可以独立于操作系统和底层设备的细节。
流 Stream 涉及的一些基本操作
1. 流可以读取。读取是把一个流中的数据传输到一个数据结构,如一个字节数组。
2. 流可以写入。写入是把一个数据结构中的数据传输到一个流。
3. 流支持定位(seek)。定位是查询和修改流中当前的位置。
根据底层数据源或存储,流可能只支持这些功能。例如,NetworkStreams 不支持定位(seek),这是显而易见的。Stream及其子类的CanRead、CanWrite、和 CanSeek 属性确定各种流支持的操作。
用于文件 I/O 的类
1. Directory 类提供创建、移动、遍历目录和子目录的静态方法。DirectoryInfo 类提供实例方法。
2. DirectoryInfo 提供创建、移动、遍历目录及其子目录的实例方法。Directory 类提供静态方法。
3. DriveInfo 类提供访问驱动器信息的实例方法。
4. File 类提供创建、复制、删除、移动、打开文件的静态方法,并且帮助创建一个 FileStream 对象。FileInfo 类提供实例方法。
5. FileInfo 类提供提供创建、复制、删除、移动、打开文件的实例方法,并帮助创建一个 FileStream 对象。File 类提供静态方法。
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 都是密封类,你可以创建这些类的实例,但它们不能被继承。
1. BinaryReader 和 BinaryWriter 类从流读写编码的字符串和基础数据类型。
2. StreamReader 类通过 Encoding 把字符转换成字节,从流中读取字符串。StreamReader 有一个构造函数,尝试确定一个给定流的正确 Encoding。这是基于一个特定编码序言,例如一个字节顺序标记。
3. StreamWriter 类通过 Encoding 把字符转换成字节,像流中写入字符。
4. StringReader 类从字符串读取字符。StringReader 允许你用相同的 API 来对待字符串,因此,你的输出可以是一个任意编码的流,或是一个字符串。
5. StringWriter 类把字符写入到字符串。StringWriter 允许你用相同的 API 来对待字符串,因此,你的输出可以是一个任意编码的流,或是一个字符串。
6. TextReader 类是抽象类,StreamReader 和 StringReader 继承该类。抽象的 Stream 类的实现是为了字节的输入和输出设计的,而 TextReader 的实现是为 Unicode 字符输出设计的。
7. 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();
}
}