------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------
至今已是我写的第十篇技术博文,通过看老杨的视频与自己在大学里所学的相结合,写出这十篇博文还是很轻松的,但我从写技术日记的过程中领悟到,任何知识通过第一次的短期记忆还是很不靠谱的,需要我们中加以思考,并提炼成文,这样才能形成长期记忆,亦或是检验自己到底学到多少的一个标杆。
一、文件和流操作概述
文件可以看作是数据的集合,一般保存在磁盘或其他存储介质上。文件I/O(数据的输入/输出)通过流(Stream)来实现;流提供一种向后备存储写入字节和从后备存储读取字节的方式。对于流有5 种基本的操作:打开、读取、写入、改变当前位置、关闭。
2.1磁盘的基本操作
DriveInfo类提供方法和属性以查询驱动器信息。使用DriveInfo类可以确定可用的驱动器及其类型;确定驱动器的容量和可用空闲空间等。下面是磁盘的基本操作示例。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class DriverInfoTest
{
static void Main()
{
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
Console.WriteLine("驱动器 {0}", d.Name);
Console.WriteLine(" 类型: {0}", d.DriveType);
if (d.IsReady == true)
{
Console.WriteLine(" 卷标: {0}", d.VolumeLabel);
Console.WriteLine(" 文件系统: {0}", d.DriveFormat);
Console.WriteLine(" 当前用户可用空间: {0, 15}字节",d.AvailableFreeSpace);
Console.WriteLine(" 可用空间: {0, 15}字节",d.TotalFreeSpace);
Console.WriteLine(" 磁盘总大小: {0, 15}字节",d.TotalSize);
Console.ReadLine();
}
}
}
}
}
2.2目录的基本操作
Directory类和DirectoryInfo类提供用于目录基本操作的方法,包括创建、复制、移动、重命名和删除目录;获取和设置目录的创建、访问及写入的时间戳信息等。
Directory所有方法都是静态的,调用时需要传入目录路径参数。DirectoryInfo类提供实例方法,需要针对要操作的目录路径创建DirectoryInfo类的实例,然后调用相应的实例方法,适用于对目录路径执行多次操作。
Directory类的静态方法可以直接调用,而无需构建对象实例,故适用于对目录路径执行一次操作;然而Directory类的静态方法对所有方法都执行安全检查,如果需要多次重用某个对象,建议使用DirectoryInfo的相应实例方法。下面是DirectoryInfo类对目录的基本操作。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class DirectoryInfoTest
{
// 将源目录复制到目标目录.
static public void CopyDirectory(string SourceDirectory, string TargetDirectory)
{
DirectoryInfo source = new DirectoryInfo(SourceDirectory);
DirectoryInfo target = new DirectoryInfo(TargetDirectory);
//如果源目录不存在,返回主程序.
if (!source.Exists)
return;
//如果目标目录不存在,则创建之.
if (!target.Exists)
target.Create();
//文件复制.
FileInfo[] sourceFiles = source.GetFiles();
for (int i = 0; i < sourceFiles.Length; ++i)
File.Copy(sourceFiles[i].FullName, target.FullName + "\\" + sourceFiles[i].Name, true);
//目录复制.
DirectoryInfo[] sourceDirectories = source.GetDirectories();
for (int j = 0; j < sourceDirectories.Length; ++j)
CopyDirectory(sourceDirectories[j].FullName, target.FullName + "\\" + sourceDirectories[j].Name);
}
static void Main()
{
string path = @"c:\MyDir";
try
{
//利用DirectoryInfo类创建、删除目录
// 指定要操作的目录.
DirectoryInfo di = new DirectoryInfo(path);
// 确定目录是否存在.
if (di.Exists)
{
Console.WriteLine("目录{0}已经存在!", path);
return;
}
// 创建目录.
di.Create();
Console.WriteLine("目录{0}已经成功创建!", path);
// 删除目录.
di.Delete();
Console.WriteLine("\n目录{0}已经成功删除!", path);
//调用子程序,将源目录SourceDirectory复制到目标目录TargetDirectory
string SourceDirectory = @"c:\SrcDir";
string TargetDirectory = @"c:\TarDir";
CopyDirectory(SourceDirectory, TargetDirectory);
Console.WriteLine("\n源目录{0}所有内容已经成功复制到目标目录{1}中!", SourceDirectory, TargetDirectory);
}
catch (Exception e)
{
Console.WriteLine("\n操作失败: {0}", e.ToString());
}
finally { }
Console.ReadLine();
}
}
}
2.3文件的基本操作
File类和FileInfo类提供用于文件基本操作的方法,包括创建、复制、移动、重命名和删除文件;打开文件,读取文件内容和追加内容到文件;获取和设置文件的创建、访问及写入的时间戳信息等。
File所有方法都是静态的,调用时需要传入目录路径参数。FileInfo类提供实例方法,需要针对要操作的目录路径创建FileInfo类的实例,然后调用相应的实例方法,适用于对目录路径执行多次操作。
File类的静态方法可以直接调用,而无需构建对象实例,故适用于对文件执行一次操作;然而File类的静态方法对所有方法都执行安全检查,如果需要多次重用某个对象,建议使用FileInfo的相应实例方法。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class FileInfoTest
{
static void Main()
{
//string path = Path.GetTempFileName();
string path = @"c:\temp\SrcFile.txt";
FileInfo fi1 = new FileInfo(path);
if (!fi1.Exists)
{
//创建文件以写入内容.
using (StreamWriter sw = fi1.CreateText())
{
sw.WriteLine("Hello");
sw.WriteLine("And");
sw.WriteLine("Welcome");
}
}
//打开文件读取内容.
Console.WriteLine("源文件内容为:");
using (StreamReader sr = fi1.OpenText())
{
string s = "";
while ((s = sr.ReadLine()) != null) Console.WriteLine(s);
}
try
{
//string path2 = Path.GetTempFileName();
string path2 = @"c:\temp\DesFile.txt";
FileInfo fi2 = new FileInfo(path2);
//删除目标文件,确保成功复制.
fi2.Delete();
//文件复制.
fi1.CopyTo(path2);
Console.WriteLine("源文件 {0} 成功复制至目标文件 {1}.", path, path2);
//删除目标文件.
fi2.Delete();
Console.WriteLine("目标文件{0} 成功删除.", path2);
// 打开已存在的文件,或者创建新文件.
FileInfo fi = new FileInfo(path);
// 获取文件完整路径.
DirectoryInfo di = fi.Directory;
// 获取文件所在目录中所有文件和子目录信息.
FileSystemInfo[] fsi = di.GetFileSystemInfos();
Console.WriteLine("\n目录 '{0}' 包含以下文件和子目录:", di.FullName);
// 打印文件所在目录中所有文件和子目录信息.
foreach (FileSystemInfo info in fsi) Console.WriteLine(info.Name);
}
catch (Exception e)
{
Console.WriteLine("\n操作失败: {0}", e.ToString());
}
finally { }
Console.ReadLine();
}
}
}
三、文本文件的读取和写入
StreamReader类和 StreamWriter类分别以一种特定的编码从字节流中读取字符和向流中写入字符
StringReader类和 StringWriter类分别实现字符串的读取和写入操作
1.StreamReader和StreamWriter
StreamReader类实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。StreamReader主要用于读取标准文本文件的各行信息
StreamWriter类实现一个 TextWriter,使其以一种特定的编码向流中写入字符。StreamWriter主要用于写入标准文本文件信息
下面使用StreamReader类和StreamWriter类读写文本文件。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class StreamReaderWriterTest
{
private const string FILE_NAME = @"c:\temp\TestFile.txt";
public static void Main(String[] args)
{
// 创建StreamWriter实例以在文件中添加文本.
using (StreamWriter sw = new StreamWriter(FILE_NAME))
{
// 在文件中添加文本.
sw.Write("文本文件");
sw.WriteLine("的写入/读取示例:");
sw.WriteLine("----------------------------------");
// Arbitrary objects can also be written to the file.
sw.WriteLine("写入整数 {0} 或浮点数 {1}", 1, 4.2);
bool b = false; char grade = 'A'; string s = "Multiple Data Type!";
sw.WriteLine("写入Boolean 值、字符、字符串、日期:");
sw.WriteLine(b);
sw.WriteLine(grade);
sw.WriteLine(s);
sw.Write("当前日期为: ");
sw.WriteLine(DateTime.Now);
}
try
{
// 创建StreamReader实例以从文本文件中读取内容.
using (StreamReader sr = new StreamReader(FILE_NAME))
{
String line;
// 读取文本文件每一行的内容,直至文件结束.
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
catch (Exception e)
{ // 异常处理.
Console.WriteLine("该文件不能正常读取,原因如下:");
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
}
}
2.StringReader和StringWriter
StringReader类实现从字符串进行读取的 TextReader;StringWriter类实现一个用于将信息写入字符串的 TextWriter;使用StringReader类和StringWriter类读写字符串。
using System;
using System.IO;
namespace CSharpPractice.IO{
class StringReaderWriterTest
{
public static void Main(String[] args)
{
string textReaderText = "本段为第一段内容.\n\n" +
"第二段内容从这里开始.\n\n" +
"第三段内容也很简洁,只是示例而已.\n\n";
Console.WriteLine("原始文本内容如下:");
Console.WriteLine("-------------------------------------------\n{0}", textReaderText);
// 将原始文本textReaderText用一组双倍间距的句子创建一个连续的段落
// 每个句子以字符“.”结束
string aLine, aParagraph = null;
StringReader strReader = new StringReader(textReaderText);
while (true)
{
aLine = strReader.ReadLine();
if (aLine != null)
{
aParagraph = aParagraph + aLine + " ";
}
else
{
aParagraph = aParagraph + "\n";
break;
}
}
Console.WriteLine("修改后的文本(连续的段落aParagraph)内容如下:");
Console.WriteLine("-------------------------------------------\n{0}", aParagraph);
// 从连续的段落aParagraph恢复原始文本内容textReaderText.
int intCharacter;
char convertedCharacter;
StringWriter strWriter = new StringWriter();
strReader = new StringReader(aParagraph);
while (true)
{
intCharacter = strReader.Read();
// 转换成character前,检查字符串是否结束.
if (intCharacter == -1) break;
convertedCharacter = Convert.ToChar(intCharacter);
if (convertedCharacter == '.') //一个句子后加入2个回车换行
{
strWriter.Write(".\n\n");
// 忽略句子间的空格.
strReader.Read();
strReader.Read();
}
else
{
strWriter.Write(convertedCharacter);
}
}
Console.WriteLine("\n还原后的原始文本内容textReaderTex:");
Console.WriteLine("-------------------------------------------\n{0}", strWriter.ToString());
Console.ReadLine();
}
}
}
四、二进制文件的读取和写入
FileStream类支持通过其 Seek 方法随机访问文件;
BinaryReader类和 BinaryWriter类在 Streams 中读取和写入编码的字符串和基元数据类型.
1.FileStream类
FileStream类提供对文件进行打开、读取、写入、关闭等操作,既支持同步读写操作,也支持异步读写操作。FileStream支持使用Seek方法对文件进行随机访问,Seek通过字节偏移量将读取/写入位置移动到文件中的任意位置,字节偏移量是相对于查找参考点(文件的开始、当前位置或结尾,分别对应于SeekOrigin.Begin、SeekOrigin.Current和SeekOrigin.End)。下面是使用FileStream类对二进制文件进行随机访问。
using System;
using System.IO;
using System.Text;
namespace CSharpPractice.IO
{
class FileStreamTest
{
static void Main()
{
string path = @"c:\temp\MyTest.txt";
// 如果文件存在,则删除之.
if (File.Exists(path)) File.Delete(path);
// 创建文件.
using (FileStream fs = File.Create(path))
{
AddText(fs, "This is some text。");
AddText(fs, "This is some more text,");
AddText(fs, "\r\nand this is on a new line");
AddText(fs, "\r\n\r\n以下是字符子集:\r\n");
for (int i = 32; i < 127; i++)
{
AddText(fs, Convert.ToChar(i).ToString());
// 每行10字符.
if (i % 10 == 0) AddText(fs, "\r\n");
}
}
// 打开流,读取并显示其内容.
using (FileStream fs = File.OpenRead(path))
{
byte[] b = new byte[1024];
UTF8Encoding temp = new UTF8Encoding(true);
while (fs.Read(b, 0, b.Length) > 0)
{
Console.WriteLine(temp.GetString(b));
}
}
Console.ReadLine();
}
private static void AddText(FileStream fs, string value)
{
byte[] info = new UTF8Encoding(true).GetBytes(value);
fs.Write(info, 0, info.Length);
}
}
}
2.BinaryReader和BinaryWriter
BinaryReader类用特定的编码将基元数据类型读作二进制值,BinaryWriter类以二进制形式将基元类型写入流,并支持用特定的编码写入字符串。下面是使用BinaryWriter类和BinaryReader类读写二进制数据文件。
using System;
using System.IO;
namespace CSharpPractice.IO
{
class BinaryReaderWriterTest
{
private const string FILE_NAME = @"c:\temp\Test.data";
public static void Main(String[] args)
{
// 创建一个新的、空的数据文件.
if (File.Exists(FILE_NAME))
{
Console.WriteLine("文件 {0} 已经存在,删除之!", FILE_NAME);
File.Delete(FILE_NAME);
}
FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew);
// 创建BinaryWriter.
BinaryWriter w = new BinaryWriter(fs);
// 写数据到新的、空的数据文件中.
for (int i = 0; i < 11; i++)
{
w.Write((int)i);
}
w.Close();
fs.Close();
// 创建BinaryReader.
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();
Console.ReadLine();
}
}
}
五、通用I/O流类
BufferedStream 是向另一个 Stream(例如 NetworkStream)添加缓冲的 Stream;CryptoStream 将数据流链接到加密转换;MemoryStream 是一个非缓冲的流,可以在内存中直接访问它的封装数据。该流没有后备存储,可用作临时缓冲区;NetworkStream 表示网络连接上的 Stream。
MemoryStream类
MemoryStream创建其支持存储区为内存的流,使用MemoryStream流类:通过将内存用作备份来读取和写入数据。
using System;
using System.IO;
using System.Text;
namespace CSharpPractice.IO
{
class MemoryStreamTest
{
static void Main()
{
int count;
byte[] byteArray;
char[] charArray;
UnicodeEncoding uniEncoding = new UnicodeEncoding();
// 创建要写入的数据(2个字符串).
byte[] firstString = uniEncoding.GetBytes("常用的ASCII字符包括:");
char[] chars = new char[127];
for (int i = 65; i < 127; i++) chars[i] = (char)i;
byte[] secondString = uniEncoding.GetBytes(chars);
using (MemoryStream memStream = new MemoryStream(100))
{ // 将第1个字符串写入内存流.
memStream.Write(firstString, 0, firstString.Length);
// 将第2个字符串一个字节一个字节地写入内存流.
count = 0;
while (count < secondString.Length)
{
memStream.WriteByte(secondString[count++]);
}
// 将内存流的有关属性:
// “分配给流的字节数、流长度、流当前位置”输出到控制台.
Console.WriteLine(
"Capacity = {0}, Length = {1}, Position = {2}\n",
memStream.Capacity.ToString(),
memStream.Length.ToString(),
memStream.Position.ToString());
// 将当前内存流中的位置设置到内存流的开始.
memStream.Seek(0, SeekOrigin.Begin);
// 从内存流中读取20个字节的内容.
byteArray = new byte[memStream.Length];
count = memStream.Read(byteArray, 0, 20);
// 一个字节一个字节地读取内存流中剩下的字节.
while (count < memStream.Length)
{
byteArray[count++] = Convert.ToByte(memStream.ReadByte());
}
// 将字节数组转换为字符数组,并输出到控制台.
charArray = new char[uniEncoding.GetCharCount(byteArray, 0, count)];
uniEncoding.GetDecoder().GetChars(byteArray, 0, count, charArray, 0);
Console.WriteLine(charArray);
Console.ReadLine();
}
}
}
}
------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------