文件和流(序列化)


       可以借助另一項技術把數據保存到文件--序列化。序列化是一個基於 .NET 流的高層模型。就本質而言,序列化允許你把整個活動的對象轉換為一系列字節,並把這些字節寫入 FileStream 之類的流對象中。以后,你可以重新讀取這些字節從而重建原對象。

       你的類必須符合下列條件才能使用序列化:

  • 在類的聲明前必須有 Serializable 特性
  • 類的所有公有和私有變量必須是可序列化的
  • 如果該類從其他類繼承,所有的父類都必須可序列化

       如果你違反任一規則,在你序列化對象時會得到一個 SerializationException 異常。

 

       下面是一個可用於保存日志信息的可序列化類:

[Serializable]
public class LogEntry
{
    public string Message { get; set; }
 
    public DateTime Date { get; set; }
 
    public LogEntry(string message)
    {
        this.Message = message;
        this.Date = DateTime.Now;
    }
}

提示:

       類使可以包含不需要序列的數據的,例如某個大型字段可以很方便的重建或者出於安全性的考慮。遇到這些情況,在恰當的變量前加入 NonSerialized 特性即可。反序列化數據以創建原對象的副本時,不可序列化的變量會返回它們的默認值。

 

       要把可序列化對象轉換為字節流,必須使用一個實現 IFormatter 接口的類。

       .NET Framework 包含兩個這樣的類:

  • BinaryFormatter:把對象序列化成壓縮的二進制格式。(位於 System.Runtime.Serialization.Formatters.Binary 命名空間)
  • SoapFormatter:使用 SOAP XML 格式產生一個相對長一些的基於文本的信息。(位於 System.Runtime.Serialization.Formatters.Soap 命名空間,同時還需要先引用程序集 System.Runtime.Serialization.Formatters.Soap.dll )

以先前的示例為基礎加以修改,看一下怎么序列化對象:

private void Log(string message)
{
    FileMode mode;
    if (ViewState["LogFile"] == null)
    {
        ViewState["LogFile"] = GetFileName();
        mode = FileMode.Create;
    }
    else
    {
        mode = FileMode.Append;
    }
 
    string fileName = ViewState["LogFile"].ToString();
    using (FileStream fs = new FileStream(fileName, mode))
    {
        LogEntry entry = new LogEntry(message);
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(fs, entry);
    }
}

 

不再讀取原始數據,現在反序列化每個保存的實例:

protected void btnRead_Click(object sender, EventArgs e)
{
    if (ViewState["LogFile"] != null)
    {
        StringBuilder log = new StringBuilder();
 
        string fileName = ViewState["LogFile"].ToString();
        using (FileStream fs = new FileStream(fileName, FileMode.Open))
        {
            BinaryFormatter formatter = new BinaryFormatter();
 
            // 文件中被序列化的對象有多個,因此要用循環
            while (fs.Position < fs.Length)
            {
                // 每一次反序列化出一個對象,流中的位置(Position)都會前進到下一個對象前
                LogEntry entry = (LogEntry)formatter.Deserialize(fs);
                log.Append(entry.Date.ToString());
                log.Append("<br />");
                log.Append(entry.Message);
                log.Append("<br /><br />");
            }
        }
        lblInfo.Text = log.ToString();
    }
    else
    {
        lblInfo.Text = "There is no log file";
    }
}

 

總結:

       至此,文件和流這一部分講述了如何利用 .NET 類來獲取文件系統信息,如何使用文件和序列化對象,還講述了數據綁定如何與文件類一起工作,如何用 Path 類彌補安全漏洞,如何處理多用戶場景里對文件資源的爭奪,最后,還說了使用 GZIP 的數據壓縮。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM