浅学C#(21)——流(2)读取写入文件、串行化对象、监控文件

版权声明:转载请注明出处 https://blog.csdn.net/le_17_4_6/article/details/86636541
FileStream对象

表示在磁盘或网络路径上指向文件的流,提供了在文件中读写字节的方法
构造方法
public FileStream ( string path, FileMode mode )
public FileStream ( string path, FileMode mode, FileAccess access )
Read 用于只读
Write 用于只写
ReadWrite 用于读写

FileStream  fs=new FileStream(“D:\\1.txt”,FileMode.Open,FileAccess.Read,FileShare.None);
//等价于
FileStream  fs=File.Open(“D:\\1.txt”,FileMode.Open,FileAccess.Read,FileShare.None);

FileStream  fs=new FileStream(“D:\\1.txt”,FileMode.OpenOrCreate,FileAccess.Write,FileShare.None);
//等价于
FileStream  fs=File.OpenWrite(“D:\\1.txt”);

文件位置
FileStream类维护内部文件指针,该指针指向文件中进行下一次读写操作的位置

public override long   Seek ( long offset, SeekOrigin origin ) 

offset为文件指针以字节为单位的移动距离
origin为开始计算的起始位置

  • SeekOrigin.Begin Current End
aFile.Seek(8, SeekOrigin.Begin);
aFile.Seek(2, SeekOrigin.Current);
aFile.Seek(-5, SeekOrigin.End);

读取数据
不仅可以读取文本文件,还可以读取图像和声音文件
public override int Read ( byte[] array, int offset, int count )
array为字节数组
offset为字节数组中开始写入数据的位置
count指定从文件中读出多少字节
int ReadByte( )
从文件中读取一个字节,并将读取位置提升一个字节

写入数据
public override void Write ( byte[] array, int offset, int count )
使用从缓冲区读取的数据将字节块写入该流
void WriteByte( byte value )
将一个字节写入文件流的当前位置

创建文件

用File创建文件

using    System.IO;
string   strTempPath=Path.GetTempPath( );
string   strFileName=Path.Combine(strTempPath, “test.txt”);
FileStream   aFile=File.Create(strFileName);
if   ( File.Exists(strFileName) )
   Console.WriteLine(“File  {0}  have created”, strFileName);
else
   Console.WriteLine(“File {0} created failed”, strFileName);
aFile.Close( );
File.Delete(strFileName);

用FileInfo创建文件

FileInfo   bFile=new  FileInfo(strFileName);
FileStream   cFile=bFile.Create();
if   ( bFile.Exists)
   Console.WriteLine(“File  {0}  have created”,strFileName);
else
   Console.WriteLine(“File {0} created failed”, strFileName);
cFile.Close( );
bFile.Delete( );

从随机访问文件中读取数据

 byte[] byData = new byte[200];
 char[] charData = new char[200];
 try  {
    FileStream aFile = new FileStream("E:/程序/f2.java", FileMode.Open);
    aFile.Seek(90, SeekOrigin.Begin);
    aFile.Read(byData, 0, 200);
  }
 catch (IOException e)
   {
 	Console.WriteLine("An IO exception has been thrown");
      Console.WriteLine(e.ToString());
      Console.ReadKey();
      return;
   }
	Decoder d = Encoding.UTF8.GetDecoder();
	 d.GetChars(byData, 0, byData.Length, charData, 0);
	 Console.WriteLine(charData);
	 Console.ReadKey();
}

将数据写入随机访问文件

byte[] byData;
char[] charData;
 try
 {
    FileStream aFile = new FileStream("E:/Temp.txt", 
                                     FileMode.Create);
    charData = "My pink half of the  
                          drainpipe.".ToCharArray();
    byData = new byte[charData.Length];
    Encoder e = Encoding.UTF8.GetEncoder();
 e.GetBytes(charData, 0, charData.Length, byData, 0, true);
    aFile.Seek(0, SeekOrigin.Begin);
    aFile.Write(byData, 0, byData.Length);
 }
catch (IOException ex)
 {
    Console.WriteLine("An IO exception has been thrown!");
    Console.WriteLine(ex.ToString());
    Console.ReadKey();
    return;
 }
StreamWriter对象
  • StreamWriter的构造方法
  • public StreamWriter ( string path )
  • public StreamWriter ( string path, bool append )
    append 为false,则创建一个新文件,或截取现有文件并打开它
    append 为true,则打开文件,保留原有数据。如果找不到文件,则创建一个新文件
  • public StreamWriter ( Stream stream )
FileStream   aFile=new  FileStream(“Log.txt”, FileMode.CreateNew);
StreamWriter  sw=new  StreamWriter(aFile);

public override void Write ( string value )
将字符串写入流,参数除字符串外可以是任何基本数据类型
public virtual void WriteLine ( string value )
将字符串写入流并换行,参数除字符串外可以是任何基本数据类型

try
 {
    FileStream aFile = new FileStream("E:/Log.txt“,    
                                     FileMode.OpenOrCreate);
    StreamWriter sw = new StreamWriter(aFile);
    bool truth = true;            
    sw.WriteLine("Hello to you.");
    sw.WriteLine("It is now {0} and things are looking  
     good.",  DateTime.Now.ToLongDateString());
    sw.Write("More than that,");
    sw.Write(" it's {0} that C# is fun.", truth);
    sw.Close();
 }
 catch (IOException e)
 {
    Console.WriteLine("An IO exception has been thrown!");
    Console.WriteLine(e.ToString());
    Console.ReadLine();
    return;
 }
StreamReader对象

StreamReader的构造方法
public StreamReader ( Stream stream )
public StreamReader ( string path )
常用方法
public override int Read ()
读取输入流中的下一个字符。到达流末尾则返回-1
public override string ReadLine ()
从当前流中读取一行字符,并将数据作为字符串返回

FileStream   aFile=new  FileStream(“Log.txt”, FileMode.Open);
StreamReader  sw=new  StreamReader(aFile);

int Read ( char[] buffer, int index, int count )
从index开始,将当前流中的最多count个字符读入buffer中
string ReadToEnd()
从流的当前位置到末尾读取流
public virtual int ReadBlock (char[] buffer, int index, int count )
常用属性
BaseStream
返回基础流

string strLine;
 try
 {
    FileStream aFile = new FileStream("Log.txt", 
                                     FileMode.Open);
    StreamReader sr = new StreamReader(aFile);
    strLine = sr.ReadLine();
    while (strLine != null)
    {
       Console.WriteLine(strLine);
       strLine = sr.ReadLine();
    }
    sr.Close();
 }
catch (IOException e)
{
   Console.WriteLine("An IO exception has been thrown!");
   Console.WriteLine(e.ToString());
   return;
 }
     Console.ReadKey();
StreamReader   sr=new  StreamReader(aFile);
int   nChar;
nChar=sr.Read( );
while  (nChar!=-1)
 {
     Console.Write(Convert.ToChar(nChar));
     nChar=sr.Read();
  }
 sr.Close( );
StreamReader   sr=new  StreamReader(aFile);
strLine=sr.ReadToEnd( );
Console.WriteLine(strLine);
sr.Close( );

用分隔符分隔的文件
String类的Split方法
public string[] Split ( params char[] separator )

public static void Main() { 
  string words = "this is a list of words, with: a bit of punctuation."; 
  string [] split = words.Split(new Char [] {' ', ',', '.', ':'});
   foreach (string s in split) {
      if (s.Trim() != "") 
          Console.WriteLine(s); 
   } 
} 
private static List<Dictionary<string, string>> GetData(out List<string> columns)
{
	 string strLine;
	 string[] strArray;
	 char[] charArray = new char[] { ',' };
	 List<Dictionary<string, string>> data = new List<Dictionary<string, string>>();
 	 columns = new List<string>();
	 try
	 {
	    FileStream aFile = new FileStream("E:/SomeData.txt", FileMode.Open);
	    StreamReader sr = new StreamReader(aFile);
	    strLine = sr.ReadLine();
	    strArray = strLine.Split(charArray);
	    for (int x = 0; x <= strArray.GetUpperBound(0); x++)  {
	       columns.Add(strArray[x]);
		}
		strLine = sr.ReadLine();
		while (strLine != null)    {
		  strArray = strLine.Split(charArray);
		  Dictionary<string, string> dataRow = new Dictionary<string, string>();
		   for (int x = 0; x <= strArray.GetUpperBound(0); x++)
		   {
		      dataRow.Add(columns[x], strArray[x]);
		   }
	       data.Add(dataRow);
	       strLine = sr.ReadLine();
	    }
	    sr.Close();
	    return data;
	 }
	 catch (IOException ex)
	 {
	    Console.WriteLine("An IO exception has been thrown!");
	    Console.WriteLine(ex.ToString());
	    Console.ReadLine();
	    return data;
	 }
}
 static void Main(string[] args)
  {
     List<string> columns;
     List<Dictionary<string, string>> myData = GetData(out columns);
     foreach (string column in columns)
     {
        Console.Write("{0,-20}", column);
     }
     Console.WriteLine();
     foreach ( Dictionary<string, string> row in myData )
     {
        foreach (string column in columns)
        {
           Console.Write( "{0,-20}", row[column] );
        }
        Console.WriteLine();
     }
     Console.ReadKey();
  }
BinaryReader

常用函数
public virtual XXX readXXX( ) 对各种基本数据类型的读取
public virtual int Read ()
public virtual int Read ( byte[] buffer, int index, int count )
public virtual int Read ( char[] buffer, int index, int count )
构造函数
public BinaryReader ( Stream input )
public BinaryReader( Stream input, Encoding encoding )

BinaryWriter

常用函数
public virtual void Write(XXX xx)
public virtual void Write ( byte[] buffer, int index, int count )
public virtual void Write ( char[] chars, int index, int count )
构造函数
protected BinaryWriter ()
public BinaryWriter ( Stream output )
public BinaryWriter ( Stream output, Encoding encoding )

读写压缩文件

System.IO.Compression命名空间中有两个压缩流类,DeflateStream和GZipStream
Deflate算法和GZip算法都是公开的,免费的
对于这两个类,必须用已有的流初始化它们
构造方法
public GZipStream ( Stream stream, CompressionMode mode )
CompressionMode.Compress 压缩基础流
CompressionMode.Decompress 解压缩基础流
public DeflateStream ( Stream stream, CompressionMode mode )

static void SaveCompressedFile(string filename, string data)
  {
     FileStream fileStream =new FileStream(filename, FileMode.Create, FileAccess.Write);
     GZipStream compressionStream =  new GZipStream(fileStream, CompressionMode.Compress);
     StreamWriter writer = new  StreamWriter(compressionStream);
     writer.Write(data);
     writer.Close();
  }
static string LoadCompressedFile(string filename)
  {
     FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
     GZipStream compressionStream = new GZipStream(fileStream, CompressionMode.Decompress);
     StreamReader reader = new StreamReader(compressionStream);
     string data = reader.ReadToEnd();
     reader.Close();
     return data;
  }
static void Main(string[] args)
  {
     try
     {
        string filename = "compressedFile.txt";
        Console.WriteLine( "Enter a string to compress (will be repeated 100 times):");
        string sourceString = Console.ReadLine();
        StringBuilder sourceStringMultiplier = new StringBuilder(sourceString.Length * 100);
        for (int i = 0; i < 100; i++)
        {
           sourceStringMultiplier.Append(sourceString);
        }
        sourceString = sourceStringMultiplier.ToString();
        Console.WriteLine("Source data is {0} bytes long.", sourceString.Length);

		SaveCompressedFile(filename, sourceString);
		Console.WriteLine("\nData saved to {0}.", filename);
		FileInfo compressedFileData = new FileInfo(filename);
		Console.WriteLine("Compressed file is {0} bytes long.", compressedFileData.Length);

		string recoveredString = LoadCompressedFile(filename);
		recoveredString = recoveredString.Substring(0, recoveredString.Length / 100);
		 Console.WriteLine("\nRecovered data: {0}", recoveredString);
		 Console.ReadKey();
	}
	catch (IOException ex)
     {
        Console.WriteLine("An IO exception has been thrown!");
        Console.WriteLine(ex.ToString());
        Console.ReadKey();
     }
}

串行化对象

.NET Framework在System.Runtime.Serialization和System.Runtime.Serialization.Formatters命名空间中提供了串行化对象的基础架构
System.Runtime.Serialization.Formatters.Binary在该命名空间中包含的BinaryFormatter类能把对象串行化为二进制数据,把二进制数据串行化为对象
System.Runtime.Serialization.Formatters.Soap在该命名空间中包含的SoupFormatter类能把对象串行化为SOAP格式的XML数据,把SOAP格式的XML数据串行化为对象

IFormatter接口

void Serialize ( Stream serializationStream, Object graph )
将对象或具有给定根的对象图形序列化为所提供的流。
Object Deserialize ( Stream serializationStream )
反序列化所提供流中的数据并重新组成对象图形

IFormatter   serializer=new  BinaryFormatter( );
serializer.Serialize(myStream, myObject);

IFormatter   serializer=new  BinaryFormatter( );
MyObjectType   myNewObject=serializer.Deserialize(myStream) as   MyObjectType;
[Serializable]
public class Product
{
  public long Id;
  public string Name;
  public double Price;
  [NonSerialized]
  string Notes;
  public Product(long id, string name, double price, string notes)
  {
     Id = id;
     Name = name;
     Price = price;
     Notes = notes;
  }
 public override string ToString()    {
     return string.Format("{0}: {1} (${2:F2}) {3}", Id, Name, Price, Notes);
  }
}
static void Main(string[] args)
  {
     try
     {
        List<Product> products = new List<Product>();
        products.Add(new Product(1, "Spiky Pung", 1000.0, "Good stuff."));
        products.Add(new Product(2, "Gloop Galloop Soup", 25.0, "Tasty."));
        products.Add(new Product(4, "Hat Sauce", 12.0, "One for the kids."));

        Console.WriteLine("Products to save:");
        foreach (Product product in products)
        {
           Console.WriteLine(product);
        }
        Console.WriteLine();
		IFormatter serializer = new BinaryFormatter();
		FileStream saveFile =  new FileStream("E:/Products.bin", FileMode.Create, FileAccess.Write);
		serializer.Serialize(saveFile, products);
		saveFile.Close();
		            
		FileStream loadFile =  new FileStream("E:/Products.bin", FileMode.Open, FileAccess.Read);
		List<Product> savedProducts = serializer.Deserialize(loadFile) as List<Product>;
		loadFile.Close();
		Console.WriteLine("Products loaded:");
		foreach (Product product in savedProducts)
        {
           Console.WriteLine(product);
        }
	}
     catch (SerializationException e)
     {
        Console.WriteLine("A serialization exception has been thrown!");
        Console.WriteLine(e.Message);
     }
     catch (IOException e)
     {
        Console.WriteLine("An IO exception has been thrown!");
        Console.WriteLine(e.ToString());
     }
     Console.ReadKey();
  }

监控文件结构

使用FileSystemWatcher的基本过程
首先设置一些属性,指定监控的位置、内容以及引发应用程序要处理的事件的时间
然后给FileSystemWatcher提供定制事件处理程序的地址,当发生重要事件时,FileSystemWatcher就调用这些属性
打开FileSystemWatcher,等待事件
启用FileSystemWatcher对象之前必须设置的属性
Path
设置要监控的文件位置或目录
NotifyFilter
NotifyFilters枚举值规定在被监控的文件内要监控哪些内容
可能的枚举值是
Attributes
CreateTime
DirectoryName
FileName
LastAccess
LastWrite
Security
Size
这些表示要监控的文件或文件夹的属性,如果规定的属性发生变化,就引发事件
Filter
监控文件的过滤器

必须为Changed、Created、Deleted和Renamed编写事件处理程序。当修改与Path、NotifyFilter和Filter属性匹配的文件或目录时,就引发每一个事件
将EnableRaisingEvents属性设置为true,就可以开始监控工作

FileSystemEventArgs类的属性

public WatcherChangeTypes ChangeType { get; }
WatcherChangeTypes.All 文件或文件夹的创建、删除、更改或重命名。
Changed 文件或文件夹的更改。更改的类型包括大小、属性、安全设置、最近写入时间和最近访问时间方面的更改。 
Created 文件或文件夹的创建。 
Deleted 文件或文件夹的删除
Renamed 文件或文件夹的重命名
FullPath 获取受影响的文件或目录的完全限定的路径。
Name 获取受影响的文件或目录的名称

RenamedEventArgs的属性

OldFullPath 获取受影响的文件或目录的前一个完全限定的路径。
OldName 获取受影响的文件或目录的旧名称。

public Form1()
  {
     InitializeComponent();
     this.watcher = new System.IO.FileSystemWatcher();
     this.watcher.Deleted += new System.IO.FileSystemEventHandler(this.OnDelete);
     this.watcher.Renamed += new System.IO.RenamedEventHandler(this.OnRenamed);
     this.watcher.Changed += new System.IO.FileSystemEventHandler(this.OnChanged);
     this.watcher.Created += new System.IO.FileSystemEventHandler(this.OnCreate);
     DirectoryInfo aDir = new DirectoryInfo(@"C:\\FileLogs");
     if (!aDir.Exists)
        aDir.Create();
  }
 public void UpdateWatchText(string  newText)
  {
     lblWatch.Text = newText;
  }
public void OnChanged(object source, FileSystemEventArgs e) {
     try
     {
        StreamWriter sw = new StreamWriter("C:/FileLogs/Log.txt", true);
        sw.WriteLine("File: {0} {1}", e.FullPath, e.ChangeType.ToString());
        sw.Close();
        this.BeginInvoke(new UpdateWatchTextDelegate(UpdateWatchText),
           "Wrote change event to log");
     }
     catch (IOException)
     {
        this.BeginInvoke(new UpdateWatchTextDelegate(UpdateWatchText),
           "Error Writing to log");
     }
  }
public void OnRenamed(object source, RenamedEventArgs e)
  {
     try
     {
        StreamWriter sw = new StreamWriter("C:/FileLogs/Log.txt", true);
        sw.WriteLine("File renamed from {0} to {1}", e.OldName, e.FullPath);
        sw.Close();
        this.BeginInvoke(new UpdateWatchTextDelegate(UpdateWatchText), "Wrote renamed event to log");
     }
     catch (IOException)
     {
        this.BeginInvoke(new UpdateWatchTextDelegate(UpdateWatchText), "Error Writing to log");
     }
  }
public void OnDelete(object source, FileSystemEventArgs e)
  {
     try
     {
        StreamWriter sw = new StreamWriter("C:/FileLogs/Log.txt", true);
        sw.WriteLine("File: {0} Deleted", e.FullPath);
        sw.Close();
        this.BeginInvoke(new UpdateWatchTextDelegate(UpdateWatchText), "Wrote delete event to log");
     }
     catch (IOException)
     {
        this.BeginInvoke(new UpdateWatchTextDelegate(UpdateWatchText), "Error Writing to log");
     }
  }
public void OnCreate(object source, FileSystemEventArgs e)
  {
     try
     {
        StreamWriter sw = new StreamWriter("C:/FileLogs/Log.txt", true);
        sw.WriteLine("File: {0} Created", e.FullPath);
        sw.Close();
        this.BeginInvoke(new UpdateWatchTextDelegate(UpdateWatchText), "Wrote create event to log");
     }
     catch (IOException)
     {
        this.BeginInvoke(new UpdateWatchTextDelegate(UpdateWatchText), "Error Writing to log");
     }
  }
 private void cmdBrowse_Click(object sender, EventArgs e)
  {
     if (FileDialog.ShowDialog() != DialogResult.Cancel)
     {
        txtLocation.Text = FileDialog.FileName;
        cmdWatch.Enabled = true;	
     }
  }
 private void cmdWatch_Click(object sender, EventArgs e)
  {
     watcher.Path = Path.GetDirectoryName(txtLocation.Text);
     watcher.Filter = Path.GetFileName(txtLocation.Text);
     watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.Size;
     lblWatch.Text = "Watching " + txtLocation.Text;
    watcher.EnableRaisingEvents = true;
  }

猜你喜欢

转载自blog.csdn.net/le_17_4_6/article/details/86636541