【问题标题】:C#: Writing a CookieContainer to Disk and Loading Back In For UseC#:将 CookieContainer 写入磁盘并重新加载以供使用
【发布时间】:2009-11-21 23:52:22
【问题描述】:

我有一个从名为 CookieJar 的 HttpWebRequest/HttpWebResponse 会话中提取的 CookieContainer。我希望我的应用程序在运行之间存储 cookie,因此在程序运行一次时收集在 CookieContainer 中的 cookie 也将在下一次运行时使用。

我认为这样做的方法是以某种方式将 CookieContainer 的内容写入磁盘。我的问题是:

  • 如何将 CookieContainer 写入磁盘?是否有内置功能,或者,如果没有,人们采取了哪些方法?是否有任何类可用于简化此操作?
  • 将 CookieContainer 写入磁盘后,如何将其重新加载以供使用

更新:第一个答案建议对CookieContainer 进行序列化。但是,我对如何序列化和反序列化如此复杂的对象不是很熟悉。您能否提供一些示例代码?建议是使用SOAPFormatter

【问题讨论】:

    标签: c# file-io cookies httpwebrequest cookiecontainer


    【解决方案1】:

    这个问题困扰了我很长时间,我找不到任何工作。我计算出来了,所以把这些信息公之于众。

    使用 BinaryFormatter 回答:

        public static void WriteCookiesToDisk(string file, CookieContainer cookieJar)
        {
            using(Stream stream = File.Create(file))
            {
                try {
                    Console.Out.Write("Writing cookies to disk... ");
                    BinaryFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(stream, cookieJar);
                    Console.Out.WriteLine("Done.");
                } catch(Exception e) { 
                    Console.Out.WriteLine("Problem writing cookies to disk: " + e.GetType()); 
                }
            }
        }   
    
        public static CookieContainer ReadCookiesFromDisk(string file)
        {
    
            try {
                using(Stream stream = File.Open(file, FileMode.Open))
                {
                    Console.Out.Write("Reading cookies from disk... ");
                    BinaryFormatter formatter = new BinaryFormatter();
                    Console.Out.WriteLine("Done.");
                    return (CookieContainer)formatter.Deserialize(stream);
                }
            } catch(Exception e) { 
                Console.Out.WriteLine("Problem reading cookies from disk: " + e.GetType()); 
                return new CookieContainer(); 
            }
        }
    

    【讨论】:

    • 有什么办法可以存储在 SQL 中而不是文件中?
    【解决方案2】:

    我还没有尝试过,但它具有 Serializable 属性,因此可以使用 .net 二进制序列化 [de] 序列化,例如肥皂格式化程序。

    这是您要求的代码 sn-p。

    var formatter = new SoapFormatter();
    string file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cookies.dat"); 
    
    using (Stream s = File.Create (file))
        formatter.Serialize(s, cookies);                            
    ...
    CookieContainer retrievedCookies = null;
    using (Stream s = File.OpenRead (file))
        retrievedCookies = (CookieContainer) formatter.Deserialize(s);
    

    查看 msdn 似乎 SoapFormatter 现在在 .net 3.5 中已弃用,它建议您使用 Binaryformatter。在过去,我发现 SoapFormatter 很有用,因为该文件是可读的,这有助于在反序列化失败时进行诊断!这些格式化程序即使在程序集版本中也对版本更改很敏感(因此,如果您使用框架的一个版本进行反序列化,升级框架,那么它可能不会反序列化,不确定),但是如果这变成一个问题。我相信它们主要是为短期持久性/远程处理而设计的,但在这里它们可能对你来说已经足够好了。

    新的 DataContractSerializer 似乎无法与它一起使用,所以它已经过时了。

    另一种方法是编写一个 CookieContainerData 类以使用 XmlSerializer [反]序列化并在此和 CookieContainer 之间手动转换。

    【讨论】:

    • 对序列化不太了解,能否提供一些示例代码?
    【解决方案3】:

    文本格式的 cookie 很有趣。除了可以用来写入磁盘之外,它还可以用于其他用途。

    为我工作!

    使用LoadCookiesFromFileSaveCookiesToFile函数分别加载cookies并将其写入磁盘。

    或者使用GetCookiesSetCookies 函数做同样的事情,但是将它作为一个字符串来操作。

    CookieContainer cookieContainer = new CookieContainer();
    
    void LoadCookiesFromFile(string path)
    {
        SetCookies(cookieContainer, File.ReadAllText(path));
    }
    
    void SaveCookiesToFile(string path)
    {
        File.WriteAllText(path, GetCookies(cookieContainer));
    }
    
    string GetCookies(CookieContainer cookieContainer)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            new BinaryFormatter().Serialize(stream, cookieContainer);
            var bytes = new byte[stream.Length];
            stream.Position = 0;
            stream.Read(bytes, 0, bytes.Length);
            return Convert.ToBase64String(bytes);
        }
    }
    
    void SetCookies(CookieContainer cookieContainer, string cookieText)
    {
        try
        {
            var bytes = Convert.FromBase64String(cookieText);
            using (MemoryStream stream = new MemoryStream(bytes))
            {
                cookieContainer = (CookieContainer)new BinaryFormatter().Deserialize(stream);
            }
        }
        catch
        {
            //Ignore if the string is not valid.
        }
    }
    

    【讨论】:

    • 我不会称其为“文本格式的 cookie”。它是“作为 base64 的二进制数据”。我认为 cookie 本身就是文本,因此如果您编写自己的基于文本的序列化程序,则可以将 cookie 存储为人类可读的文本 - 它可以是 JSON,或者只是缩进的文本部分。
    猜你喜欢
    • 2013-08-12
    • 1970-01-01
    • 2021-03-23
    • 2017-04-24
    • 1970-01-01
    • 2013-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多