件读写相关类——相当精要

来源:互联网 发布:tp非法数据对象 编辑:程序博客网 时间:2024/06/04 23:27
 

文件读写相关类介绍:
文件读写操作涉及的类主要是:
MarshalByRefObject 类:允许在支持远程处理的应用程序中跨应用程序域边界访问对象;
BinaryReader 类:用特定的编码将基元数据类型读作二进制值。
BinaryWriter 类: 以二进制形式将基元类型写入流,并支持用特定的编码写入字符串。
Stream 类: 提供字节序列的一般视图。
FileStream类:公开以文件为主的 Stream,既支持同步读写操作,也支持异步读写操作。
MemoryStream 类:创建其支持存储区为内存的流。
BufferedStream 类:给另一流上的读写操作添加一个缓冲层。
TextReader 类:表示可读取连续字符系列的阅读器。
TextWriter 类:表示可以编写一个有序字符系列的编写器。
StreamReader 类:实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。
StreamWriter 类:实现一个 TextWriter,使其以一种特定的编码向流中写入字符。
StringReader 类:实现从字符串进行读取的 TextReader。
StringWriter 类:实现一个用于将信息写入字符串的 TextWriter。该信息存储在基础StringBuilder中。
在使用它们之前最好能了解它们的继承关系,有助于作出最合适的选择:


另外还要注意一下FileInfo和File类的一些方法,如Create,CreateText,Open等,有时也会带来方便。
这些类的内容比较繁多,更多内容还请参考MSDN。

下面是一些常见的问题及其解决方案:
问题1:如何读写文本文件(并考虑不同的编码类型);
解决方案:
创建一个FileStream对象用以引用该文件。要写入文件,将FileStream对象封装在StreamWriter对象中,使用其重载了的Write方法;要读取文件,将FileStream对象封装在StreamReader对象中,使用其Read或ReadLine方法;
.NET Framework允许通过StreamWriter和StreamReader类操作任何流来读写文本文件。当使用StreamWriter类写入数据时,调用它的Write方法,该方法在重载后可以支持所有常见的C#数据类型,包括字符串、字符、整数、浮点数以及十进制数等。但Write方法总会将的得到的数据转换为文本,如果希望将这些文本转换回原来的数据类型,应使用WriteLine方法,以确保每个值都处于单独的一行上。
字符串的表现形式取决于你使用的编码,最常见的编码类型包括下面几种:ASCII,UTF-16,UTF-7,UTF-8。
.NET Framework在System.Text命名空间中为每种编码类型提供了一个类。在使用StreamWriter和StreamReader类时,可以指定需要的编码类型,或者使用默认的UTF-8。
而在读取文本文件时,则要使用StreamReader类的Read或ReadLine方法。Read方法读取单个字符或者指定个数的字符,返回类型为字符或字符数组;ReadLine方法则返回包含整行内容的字符串;ReadToEnd方法从当前位置读取至流的结尾。
(更多内容还请参考MSDN)
写入文本文件的示例:


using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
// 创建一个StreamWriter对象,使用UTF-8编码格式
using (StreamWriter writer = new StreamWriter(fs, Encoding.UTF8))
{
// 分别写入十进制数,字符串和字符类型的数据
writer.WriteLine(123.45M);
writer.WriteLine("String Data");
writer.WriteLine('A');
}
}


读取文本文件的示例:

// 以只读模式打开一个文本文件
using (FileStream fs = new FileStream(fileName, FileMode.Open))
{
using (StreamReader reader = new StreamReader(fs, Encoding.UTF8))
{
string text = string.Empty;

while(!reader.EndOfStream)
{
text = reader.ReadLine();
txtMessage.Text += text + Environment.NewLine;
}
}
}


问题2:如何读写二进制文件(使用强数据类型);
解决方案:
创建一个FileStream对象用以引用该文件。要写入文件,将FileStream对象封装在BinaryWriter对象中,使用其重载了的Write方法;要读取文件,将FileStream对象封装在BinaryReader对象中,使用相应数据类型的Read方法。
.NET Framework允许通过BinaryWriter和BinaryReader类操作任何流来读写二进制数据。当使用BinaryWriter类写入数据时,调用它的Write方法,该方法在重载后可以支持所有常见的C#数据类型,包括字符串、字符、整数、浮点数以及十进制数等,然后数据会被编码为一系列字节写入文件,也可以配置该过程中的编码类型。
在使用二进制文件时,一定要特别注意其中的数据类型。当你读取数据时,一定要使用BinaryReader类的某种强类型的Read方法。例如,要读取字符串,要使用ReadString方法。(BinaryWriter在写入二进制文件时总会记录字符串的长度以避免任何可能的错误)
写入文件的示例:

using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
using (BinaryWriter writer = new BinaryWriter(fs))
{
// 写入十进制数,字符串和字符
writer.Write(234.56M);
writer.Write("String");
writer.Write('!');
}
}


读取文件的示例:

// 以只读模式打开一个二进制文件
using (FileStream fs = new FileStream(fileName, FileMode.Open))
{
using (StreamReader sr = new StreamReader(fs))
{
MessageBox.Show("全部数据:" + sr.ReadToEnd());

fs.Position = 0;
using (BinaryReader reader = new BinaryReader(fs))
{
// 选用合适的数据类型读取数据
string message = reader.ReadDecimal().ToString() + Environment.NewLine;
message += reader.ReadString() + Environment.NewLine;
message += reader.ReadChar().ToString();
MessageBox.Show(message);
}
}
}


问题3:如何异步读取文件;
解决方案:
有时你需要读取一个文件但又不希望影响程序的执行。常见的情况是读取一个存储在网络驱动器上的文件。
FileStream提供了对异步操作的基本支持,即它的BeginRead和EndRead方法。使用这些方法,可以在.NET Framework线程池提供的线程中读取一个数据块,而无须直接与System.Threading命名空间中的线程类打交道。
采用异步方式读取文件时,可以选择每次读取数据的大小。根据情况的不同,你可能会每次读取很小的数据(比如,你要将数据逐块拷贝至另一个文件),也可能是一个相对较大的数据(比如,在程序逻辑开始之前需要一定数量的数据)。在调用BeginRead时指定要读取数据块的大小,同时传入一个缓冲区(buffer)以存放数据。因为BeginRead和EndRead需要访问很多相同的信息,如FileStream,buffer,数据块大小等,因此将这些内容封装一个单独的类当中是一个好主意。
下面这个类就是一个简单的示例。AsyncProcessor类提供了StartProcess方法,调用它开始读取,每次读取操作结束,OnCompletedRead回调函数会被触发,此时可以处理数据,如果还有剩余数据,则开始一个新的读取操作。默认情况下,AsyncProcessor类每次读取2KB数据。


class AsyncProcessor
{
private Stream inputStream;

// 每次读取块的大小
private int bufferSize = 2048;

public int BufferSize
{
get { return bufferSize; }
set { bufferSize = value; }
}

// 容纳接收数据的缓存
private byte[] buffer;

public AsyncProcessor(string fileName)
{
buffer = new byte[bufferSize];

// 打开文件,指定参数为true以提供对异步操作的支持
inputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, true);
}

public void StartProcess()
{
// 开始异步读取文件,填充缓存区
inputStream.BeginRead(buffer, 0, buffer.Length, OnCompletedRead, null);
}

private void OnCompletedRead(IAsyncResult asyncResult)
{
// 已经异步读取一个 块 ,接收数据
int bytesRead = inputStream.EndRead(asyncResult);

// 如果没有读取任何字节,则流已达文件结尾
if (bytesRead > 0)
{
// 暂停以模拟对数据块的处理
Debug.WriteLine("异步线程:已读取一块");
Thread.Sleep(TimeSpan.FromMilliseconds(20));

// 开始读取下一块
inputStream.BeginRead(buffer, 0, buffer.Length, OnCompletedRead, null);
}
else
{
// 结束操作
Debug.WriteLine("异步线程:读取文件结束");
inputStream.Close();
}
}
}


使用该类时可以这么写:

// 开始在另一线程中异步读取文件
AsyncProcessor asyncIO = new AsyncProcessor("test.txt");
asyncIO.StartProcess();

// 在主程序中,做其它事情,这里简单地循环10秒
DateTime startTime = DateTime.Now;
while (DateTime.Now.Subtract(startTime).TotalSeconds < 10)
{
Debug.WriteLine("主程序:正在进行");
// 暂停线程以模拟耗时的操作
Thread.Sleep(TimeSpan.FromMilliseconds(100));
}

Debug.WriteLine("主程序:已完成");


问题4:如何创建临时文件;
解决方案:
有时需要在特定用户的临时目录下创建一个临时文件,这要求该文件具有唯一的名称,避免与其它程序生成的临时文件相冲突。我们会有多种选择。最简单的是,在程序所在目录内使用GUID或时间戳加上随机值作为文件名称。但Path类提供的方法还是可以为你节省工作量,这就是它的静态GetTempFileName方法,它在当前用户的临时目录下创建一个临时文件(文件名称一定是唯一的),临时目录通常类似于这样:C:\Documents and Settings\[username]\Local Settings\Temp。

string tempFile = Path.GetTempFileName();

using (FileStream fs = new FileStream(tempFile, FileMode.Open))
{
using (BinaryWriter writer = new BinaryWriter(fs))
{
// 写入数据
writer.Write("临时文件信息");
}
}

// Do something

// 最后删除临时文件
File.Delete(tempFile);


问题5:如何获得随机文件名;
解决方案:
使用Path.GetRandomFileName方法,它与GetTempFileName方法的不同之处在于它仅仅返回一个字符串但不会创建文件。


问题6:监视文件系统的变化;
解决方案:
如果指定路径内的文件发生改变(比如文件被修改或创建),你希望能对此作出反应。
如果程序与其它多个程序或业务处理相关,常常需要创建一个程序,并且只有文件系统发生变化时它才处于活动状态。你可以创建一个这样的程序,让它定期区检测指定目录,此时会发现有件事情让你苦恼:检测得越频繁,就会浪费越多的系统资源;而检测得越少,那么检测到变化的时间就会越长。
这时可以使用FileSystemWatcher组件,指定要进行监视的目录或文件,并处理其Created,Deleted,Renamed,Changed事件。
要使用FileSystemWatcher组件,首先要创建它的一个实例,然后设置下列属性:
Path:指定要监视的目录;
Filter:指定要监视的文件类型,如”*.txt”;
NotifyFilter:指定要监视的变化类型;
FileSystemWatcher会引发四个关键的事件:Created,Deleted,Renamed,Changed。这些事件都在其FileSystemEventArgs参数中提供了相关文件的信息:如文件名,路径,改变类型,Renamed事件中还可以了解到改变前的文件名和路径。如果要禁用这些事件,则将它的EnableRaisingEvents属性设置为false。Created,Deleted,Renamed三个事件比较容易处理,但Changed事件就得当心了,你需要设置它的NotifyFilter属性以指示监视那些类型的变化。否则,程序会在文件被修改时淹没在不断发生的事件中(缓存区溢出)。

// 设置相关属性
watcher.Path = appPath;
watcher.Filter = "*.txt";
watcher.IncludeSubdirectories = true;

// 添加事件处理函数
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);


void OnRenamed(object sender, RenamedEventArgs e)
{
string renamedFormat = "File: {0} 被重命名为 :{1}";
txtChangedInfo.Text = string.Format(renamedFormat, e.OldFullPath, e.FullPath);
}

void OnChanged(object sender, FileSystemEventArgs e)
{
// 显示通知信息
txtChangedInfo.Text = "文件: " + e.FullPath + "发生改变" + Environment.NewLine;
txtChangedInfo.Text += "改变类型: " + e.ChangeType.ToString();
}


问题7:如何使用独立存储文件;
解决方案:
有时你需要将数据存储在文件中,但对本地硬盘驱动器却没有必要的权限(FileIOPermission)。这时要用到System.IO.IsolatedStorage命名空间中的类,这些类允许你的程序在特定用户的目录下将数据写入文件而不需要直接访问硬盘驱动器的权限:


// 创建当前用户的独立存储
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForAssembly())
{
// 创建一个文件夹
store.CreateDirectory("MyFolder");

// 创建一个独立存储文件
using (Stream fs = new IsolatedStorageFileStream("MyFile.txt", FileMode.Create, store))
{
StreamWriter writer = new StreamWriter(fs);
writer.WriteLine("Test Line!");
writer.Flush();
}

Debug.WriteLine("当前大小:" + store.CurrentSize.ToString() + Environment.NewLine);
Debug.WriteLine("范围:" + store.Scope.ToString() + Environment.NewLine);
string[] files = store.GetFileNames("*.*");
if (files.Length > 0)
{
Debug.WriteLine("当前文件:" + Environment.NewLine);
foreach (string file in files)
{
Debug.WriteLine(file + Environment.NewLine);
}
}
}

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买的桌子会晃怎么办 车子座椅皮坏了怎么办 裤子被椅子刮了怎么办 脚麻了被别人动怎么办 毛孔又粗又黑怎么办 手臂睡觉压麻了怎么办 睡觉压的胳膊麻怎么办 摔跤摔到腰肿了怎么办 牛奶喝多了拉稀怎么办 doc文档下载是乱码怎么办 家人被教练技术骗了怎么办 十个月宝宝不爱喝水怎么办 离婚后孩子找爸爸怎么办 离婚后孩子要找爸爸怎么办 断奶期间胸涨的难受怎么办 断奶胸涨的很疼怎么办 过了麦季身上老痒怎么办 过麦时候皮肤痒怎么办 颈部起红疙瘩痒怎么办 脚底痒身上痒该怎么办 生完孩子屁股疼怎么办 pr打开工程文件无响应怎么办 娃娃和老师有隔阂了怎么办 大人字写得不好怎么办 不会写好看的字怎么办 无限量流量限速了怎么办 长期化妆后皮肤变黄怎么办 手机密码忘记了打不开怎么办 手机解压包不知道密码怎么办 手机屏图标没了怎么办 b站页面卡顿怎么办 被全景视觉骗了怎么办? 逆战进去没声音怎么办 Mac电脑ai卡住了怎么办 pr字幕打不了字怎么办 pr手写字多笔画怎么办 家中挖矿噪音很大怎么办 学了栏目包装不想干怎么办 在文本打字乱了怎么办 体考后觉得成绩有出入怎么办 荧光棒进眼睛里怎么办