Max*_*sky 28 c# cookies file-io httpwebrequest cookiecontainer
我CookieContainer从一个名为CookieJar的HttpWebRequest/HttpWebResponse会话中提取.我希望我的应用程序在运行之间存储cookie,因此CookieContainer在程序的一次运行中收集的cookie 也将在下一次运行时使用.
我认为这样做的方法是以某种方式将CookieContainer的内容写入磁盘.我的问题是:
UPDATE:第一个答案已经提出系列化的CookieContainer.但是,我不太熟悉如何序列化和反序列化这些复杂的对象.你能提供一些示例代码吗?建议是利用SOAPFormatter.
Luc*_*ity 30
这个问题困扰了我多年,我找不到任何工作.我把它解决了,所以把这些信息传播到世界各地.
使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
DW.*_*DW. 20
我没有尝试过,但它具有Serializable属性,因此可以使用.net二进制序列化[de]序列化,例如SoapFormatter.
这是您要求的代码段.
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);
Run Code Online (Sandbox Code Playgroud)
看看msdn似乎现在在.net 3.5中不推荐使用SoapFormatter,它建议你使用Binaryformatter.在过去,我发现SoapFormatter非常有用,因为该文件是可读的,这有助于在反序列化失败时进行诊断!这些格式化程序对版本更改很敏感,即使在汇编版本中也是如此(因此,如果您使用一个版本的框架反序列化升级框架,那么它可能不会反序列化,不确定),但如果这变为Binder属性,则可以解决这个问题.一个问题.我相信它们主要是为短期持久性/遥控设计的,但它们对你来说可能已经足够好了.
新的DataContractSerializer似乎无法使用它,所以这是出来的.
另一种方法是将CookieContainerData类写入[de]序列化XmlSerializer,并在此与CookieContainer之间手动转换.
IFormatter由于使用类进行序列化已被弃用,以前的所有答案都已过时https://aka.ms/binaryformatter
所以现在正确的方法是使用其他支持IEnumerable<T>.
这是一个使用的示例System.Text.Json
await using var fs = File.OpenWrite("cookies.json");
// Beware: GetAllCookies is available starting with .NET 6
JsonSerializer.Serialize(fs, cookieContainer.GetAllCookies());
Run Code Online (Sandbox Code Playgroud)
var cookieContainer = new CookieContainer();
await using var fs = File.OpenRead("cookies.json");
var cookieCollection = JsonSerializer.Deserialize<CookieCollection>(fs);
cookieContainer.Add(cookieCollection);
Run Code Online (Sandbox Code Playgroud)
有文本格式的 cookie很有趣。除了能够用于写入磁盘之外,它还可以用于其他目的。
为我工作!
使用LoadCookiesFromFile和SaveCookiesToFile函数分别加载和写入 cookie 到磁盘。
或者使用GetCookies和SetCookies函数来做同样的事情,但是把它当作一个字符串来操作。
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.
}
}
Run Code Online (Sandbox Code Playgroud)