文件和注册表
对于文件系统操作,相关的类几乎都在System.IO名称空间中,而注册表操作由System.Win32名称空间中的类处理。注意,在修改文件或注册表项时,安全性显得更为重要。
.NET基类也包含System.Runtime.Serialization名称空间中的许多类和接口,他们都与串行化有关。串行化是把一些数据转换为字节流并存储在某个地方的过程。
1、管理文件系统
System.MarshalByRefObject----------这是.NET类中用于远程操作的基对象类,它允许在应用程序域之间编组数据。这个列表中的其他项都在System.IO名称空间中。
FileSystemInfo-----------这是表示任何文件系统对象的基类
FileInfo---------------这些类表示文件系统上的文件
DirectoryInfo和Directory--------------这些类表示文件系统上的文件夹
Path-------------这个类包含的静态成员可以用于处理路径名
DriveInfo-------------他的属性和方法提供了指定驱动器的信息
在Windows上,包含文件并用于组织文件系统的对象称为文件夹,例如,在路径D:\MyDrivers\software.txt中,software.txt是一个文件,MyDrivers是一个文件夹,文件夹是一个Windows专用的术语:在其他操作系统上,用术语“目录”代替文件夹,Microsoft为了使.NET具有平台无关性,对应的.NET基类都称为Directory和 DirectoryInfo。因为它有可能与LDAP目录混淆,而且本书与Windows有关。
1.1、表示文件和文件夹的.NET类
注意,上面的列表有两个用于表示文件夹的类,和两个用于表示文件的类。使用哪个类主要依赖于访问该文件夹或文件的次数:
Directory类和File类只能包含静态方法,不能被实例化。只有调用一个成员方法,提供合适文件系统对象的路径,就可以使用这些类。如果只对文件夹或文件执行一个操作,使用这些类就很有效,因为这样可以省去实例化.NET类的系统开销。
DirectoryInfo类和FileInfo类实现与Directory类和File类大致相同的公共方法,并拥有一些公共属性和构造函数,但它们都是有状态的,并且这些类的成员都不是静态的。需要实例化这些类,之后把每个实例化与特定的文件夹或文件关联起来。如果使用同一个对象执行多个操作,使用这些类就比较有效。这是因为在构造时它们将读取合适文件系统对象的身份验证和其他信息,无论对每个对象调用了多少方法,都不需要再次读取这些信息。比较而言,在调用每个方法时,相应的无状态类需要再次检查文件或文件夹的详细内容。
FileInfo myFile = new FileInfo(@"D:\text.txt");
myFile.CopyTo(@"D:\test.txt"); 等同于 File.Copy(@"D:\text.txt", @"D:\test.txt");
第一段代码执行的时间稍微长点,因为需要实例化一个FileInfo对象MyFile,但myFlie可以对同一个文件夹执行进一步的操作。第二个不需要实例化来复制文件。
读写文件内容:
读:File.ReadAllText(path,Encoding.UTF8); 写:File.WriteAllText(path, contents);
1.2、流
流的概念存在很长时间了,流是一个用于传输数据的对象,数据可以向两个方向传输:
a、如果数据从外部源传输到程序中,这就是读取流。
b、如果数据从程序传输到外部源中,这就是写入流。
外部源常常是一个文件,但也不完全都是文件,它还可能是:
c、使用一些网络协议读写网络上的数据,其目的是选择数据,或从另一个计算机上发送数据。
e、读写到命名管道上。
f、把数据读写到一个内存区域上。
使用一个独立的对象来传输数据,比使用FileInfo或DirectoryInfo类更好,因为把传输数据的概念与特定数据源分离开来,可以更容易交换数据源。流对象本身包含许多通用代码,可以在外部数据源和代码中的变量之间移动数据,把这些代码与特定数据源的概念分离开来,就更容易实现不同环境下代码的重用。例如,StringReader和StringWrite类,StreamReader和StreamWrite,都是同一继承树的一部分,这些类几乎一定在后台共享许多代码。
对于文件的读写,最常用的类如下:
a、FileStream(文件流)------这个类主要用于在二进制文件中读写二进制数据-------也可以使用它读写任何文件。
b、StreamReader(流读取器)和StreamWrite(流写入器)---------这两个类专门用于读写文本文件。
1.3、缓存的流
从性能原因上看,在读写文件时,输出结果会被缓存。如果程序要求读取文件流中下面的两个字节,该流会把请求传递给Windows,则Windows不会连接文件系统,再定位文件,并从磁盘中读取文件,仅读取2个字节。而是在一次读取过程中,检索文件中的一大块,把该块保存在一个内存区域,即缓冲区上,以后对流中数据的请求就会从该缓冲区中读取,直到读取完该缓冲区为止。此时,Windows会从文件中再获取另一个数据块。
写入文件的方式与此相同。对于文件,操作系统会自动完成读写操作,但需要编写一个流类,从其他没有缓存的设备中读取数据。如果是这样,就应从BufferStream派生一个类,它实现一个缓冲区(BufferStream并不用于应用程序频繁切换读数据和写数据的情形)。
1.4使用FileStream类读写二进制文件
FileStream实例用于读写文件中的数据,要构造FileStream实例,需要以下4种信息:
a、要访问的文件。
b、表示如何打开文件的模式。例如,新建一个文件或打开一个现有的文件。如果打开一个现有的文件,写入操作是覆盖文件原来的内容,还是追加到文件的末尾?
c、表示访问文件的方式------------是只读,只写,还是读写?
e、共享访问-----------表示是否独占访问文件。如果允许其他流同时访问文件,则这些流是只读,只写,还是读写文件?
第一条信息通常用一个包含文件的完整路径字符串来表示,其余3条信息分别由3个.NET枚举FileMode、FileAccess和FileShare来表示。
FileMode-------------Append、Create、CreateNew、Open、OpenOrCreate和Truncate
FileAccess-----------Read、ReadWrite和Write
FileShare-------------Delete、Inheritable、None、Read、ReadWrite和Write
FileStream fs = new FileStream(@"F:\项目资料\语法学习训练\20181220\create.txt",FileMode.Create);
FileStream fs1 = new FileStream(@"F:\项目资料\语法学习训练\20181220\read.txt",FileMode.Create,FileAccess.Write);
FileStream fs2 = new FileStream(@"F:\项目资料\语法学习训练\20181220\read.txt", FileMode.Create, FileAccess.Write,FileShare.None);
FileInfo.OpenRead()方法提供的流只能读取现有文件,而FileInfo.OpenWrite()方法可以进行读写访问,FileInfo.Open()方法允许显式地指定模式、访问方式和文件共享参数。当然,使用完一个流后就应该关闭它:fs.Close();关闭流就会释放关联的资源,允许其他应用程序为同一个文件设置流。这个操作也会刷新缓冲区。在打开和关闭流之间,可以读写其中的数据。FlieStream类实现了许多方法以进行这样的读写。
ReadByte()是读取数据的最简单的方式,它从流中读取一个字节,把结果转换为一个0~255之间的整数。如果到达该流的末尾,它就返回-1: int NextByte=fs.ReadByte();
如果要一次读取多个字节,就可以调用Read()方法,它可以把特定数量的字节读入一个数组中。Read()方法返回实际读取的字节数---如果这个值是0,就表示到达了流的末尾,下面的示例读入一个字节数据ByteArray: int nByteRead=fs.Read(ByteArray,0,nByte); Read方法的第二个参数是一个偏移量,使用它可以要求Read操作的数据从数组的某个元素开始填充,而不是从第一个元素开始。第3个参数是要读入的数组的字节数。如果要给文件写入数据,就可以使用两个并行方法WriteByte和Write。WriteByte方法把一个字节写入流中: byte NextByte=100; fs.WriteByte(NextByte);而Write方法写入一个字节数组。例如,如果用一些值初始化前面的ByteArray数组,就可以使用下面的代码输出数组的前nByte个字节: fs.Write(ByteArray,0,nByte); 与Read()方法一样,第二个参数可以从数组的某个元素开始写入,而不是从第一个元素开始。WriteByte()方法和Write()方法都没有返回值。
private void DisplayFile()
{
int nCols = 16;
FileStream inStream = new FileStream(chosenFile, FileMode.Open,
FileAccess.Read);
long nBytesToRead = inStream.Length;
if (nBytesToRead > 65536/4)
nBytesToRead = 65536/4;
int nLines = (int) (nBytesToRead/nCols) + 1;
string[] lines = new string[nLines];
int nBytesRead = 0;
for (int i = 0; i < nLines; i++)
{
StringBuilder nextLine = new StringBuilder();
nextLine.Capacity = 4*nCols;
for (int j = 0; j < nCols; j++)
{
int nextByte = inStream.ReadByte();
nBytesRead++;
if (nextByte < 0 || nBytesRead > 65536)
break;
char nextChar = (char) nextByte;
if (nextChar < 16)
nextLine.Append(" x0" + string.Format("{0,1:X}",
(int) nextChar));
else if
(char.IsLetterOrDigit(nextChar) ||
char.IsPunctuation(nextChar))
nextLine.Append(" " + nextChar + " ");
else
nextLine.Append(" x" + string.Format("{0,2:X}",
(int) nextChar));
}
lines[i] = nextLine.ToString();
}
inStream.Close();
textBoxContents.Lines = lines;
}
1.5、读写文本文件
StreamReader类:StreamReader实例用于读取文本文件。用某些方式构造StreamReader实例要比构造FileStream实例更简单,因为使用StreamReader时,不需要FileStream的一些选项。特别是模式和访问类型与StreamReader类不相关,因为StreamReader只能执行读取操作。除此之外,没有指定共享许可的直接选项,但StreamReader有两个新选项:
a、需要指定不同的编码方法所执行的不同操作。可以构造一个StreamReader检查文件开头的字节码标记,确定编码方法,或者告诉StreamReader假定该文件使用某种指定的编码方法。
b、不提供要读取的文件名,而为另一个流提供一个引用。
最后一个选项需要解释一下,它说明把读写数据的模型建立在流概念上的另一个优点。因为StreamReader工作在相对较高的级别上,如果有另一个流在读取其他源中的数据,就要使用StreamReader提供的工具来处理这个流,就好像这个流包含文本,所以此时StreamReader类非常有用。可以把这个流的输出传递给StreamReader,这样StreamReader就可以用于读取和处理任何数据源(不仅仅是文件)中的数据。
StreamReader tr = new StreamReader(@"F:\项目资料\语法学习训练\20181220\read.txt");
StreamReader tr = new StreamReader(@"F:\项目资料\语法学习训练\20181220\read.txt",Encoding.UTF8); //Unicode ASCII UTF32 UTF7 UTF8 BigEndianUnicode
FileStream fs2 = new FileStream(@"F:\项目资料\语法学习训练\20181220\read.txt", FileMode.Create, FileAccess.Write, FileShare.None);
StreamReader tr = new StreamReader(fs2);//关联到文件流上
tr.Close(); //关闭
string nextLine=sr.ReadLine();//一次读取一行
string restOfStream=sr.ReadToEnd();//提取文件中的所有剩余内容
int nextChar=sr.Read();//读取一个字符
int nChars=100; char[] charArray=new char[nChars]; int nCharRead=sr.Read(charArray,0,nChars); //把给定个数的字符读到数组中
StreamWrite类:只能写入文件,构造方法如下:
StreamWriter sw = new StreamWriter(@"F:\项目资料\语法学习训练\20181220\write.txt");
StreamWriter sw = new StreamWriter(@"F:\项目资料\语法学习训练\20181220\write.txt",true,Encoding.ASCII);//可以指定相应的编码方法,第二个参数表示文件是否应以追加方式打开
sw.Write("you want to ");//写入字符串
sw.Write(charArray,startAtLocation,50)//输出字符数组的一部分
private readonly OpenFileDialog chooseOpenFileDialog = new OpenFileDialog();
private string chosenFile;
public Form1()
{
InitializeComponent();
menuFileOpen.Click += OnFileOpen;
chooseOpenFileDialog.FileOk += OnOpenFileDialogOK;
menuFileSave.Click += OnFileSave;
}
private void OnFileOpen(object Sender, EventArgs e)
{
chooseOpenFileDialog.ShowDialog();
}
private void OnFileSave(object Sender, EventArgs e)
{
SaveFile();
}
private void OnOpenFileDialogOK(object Sender, CancelEventArgs e)
{
chosenFile = chooseOpenFileDialog.FileName;
Text = Path.GetFileName(chosenFile);
DisplayFile();
}
private void SaveFile()
{
StreamWriter sw = new StreamWriter(chosenFile, false,
Encoding.Unicode);
foreach (string line in textBoxContents.Lines)
sw.WriteLine(line);
sw.Close();
}
private void DisplayFile()
{
StringCollection linesCollection = ReadFileIntoStringCollection();
string[] linesArray = new string[linesCollection.Count];
linesCollection.CopyTo(linesArray, 0);
textBoxContents.Lines = linesArray;
}
private StringCollection ReadFileIntoStringCollection()
{
const int MaxBytes = 65536;
StreamReader sr = new StreamReader(chosenFile);
StringCollection result = new StringCollection();
int nBytesRead = 0;
string nextLine;
while ((nextLine = sr.ReadLine()) != null)
{
nBytesRead += nextLine.Length;
if (nBytesRead > MaxBytes)
break;
result.Add(nextLine);
}
sr.Close();
return result;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix