提问人:Artemis Venatrix 提问时间:2/4/2022 最后编辑:CharliefaceArtemis Venatrix 更新时间:2/4/2022 访问量:522
为什么 c# 在创建任何文件流之前创建文件?
Why is c# creating a file before any file stream is created?
问:
背景:
我正在创建一个 avaloniaUI 项目,其中我有一个 json 配置,其中包含一个类,可以在初始化和编辑时对其进行序列化和反序列化。如果在初始化时找不到该文件,则该类会创建一个包含默认属性列表的新文件。这个类应该是代码中唯一可以做到这一点的部分。
问题:
由于某种原因,配置文件(如果尚不存在)是在 config 序列化程序类的构造函数调用之前创建的。这导致我和我的朋友认为该文件是在项目的其他地方创建的。但事实并非如此,因为我使用控制 f 工具梳理整个项目以查找任何文件流、创建命令或对配置路径的引用,并且我发现除了应该创建配置但从未运行的代码之外,没有其他能够生成文件。因此,发生的情况是在调用应该处理生成的代码之前,文件被创建为空,从而跳过正确的生成代码,这会导致 json 在文件反序列化时加载空字符串,并创建空值异常。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Newtonsoft.Json;
namespace RefOrganizerAvalonia.Util
{
public class ConfigSerializer
{
public List<ConfigItem> Items { get; }
private string _configPath;
private static List<ConfigItem> BuildConfig()
{
return new List<ConfigItem>()
{
new ConfigItem("PageResultSize", 50, typeof(int))
,new ConfigItem("ResultsPerLine", 5, typeof(int))
};
}
private List<ConfigItem> LoadConfig()
{
using (FileStream fs = new FileStream(_configPath, FileMode.Open))
{
var sr = new StreamReader(fs);
var dataStr = sr.ReadToEnd();
return JsonConvert.DeserializeObject(dataStr) as List<ConfigItem>;
}
}
public ConfigSerializer()
{ //break point here reveals that even before any of the constructor code is executed the
//file is created from an unknown location
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);
_configPath = Path.Join(path, "ref_organizer_config.json");
Debug.WriteLine(_configPath);
Debug.WriteLine(File.Exists(_configPath));
if (!File.Exists(_configPath)) //never accessed because the (empty) file already
//exists by this point despite no code that can create
//it being executed
{
Debug.WriteLine("Config Not Found");
//Save BuildConfig() results in json string and write to file
Items = BuildConfig();
SaveConfig();
}
else
{
Items = LoadConfig();
}
}
private void SaveConfig()
{
using (FileStream fs = new FileStream(_configPath, FileMode.OpenOrCreate))
{
Debug.WriteLine("Save Config Triggered");
var data = JsonConvert.SerializeObject(Items);
Debug.WriteLine($"Serialized Config: {data}");
var sw = new StreamWriter(fs);
sw.Write(data);
}
}
}
}
执行的测试:
- 更改配置序列化程序类的调用顺序和位置。
结果:在初始化配置序列化程序之前,仍会创建具有配置名称和路径的空文件。
- 更改变量的路径。
_configPath
结果:以新名称创建的空文件。
- 将功能设置为私有。
SaveConfig()
结果:没有变化。
注意:
如果您出于任何原因需要 avalonia 项目代码的其他上下文,请给我留言,我会尽快发布。
答:
在我跟踪代码的小型测试中,问题似乎出在方法上。遍历代码应该会发现代码行......正在执行,但是,实际上没有向文件写入任何内容。添加语句应确保... ...完成。将命令添加到编写器似乎实际上是将数据写入文件。SaveConfig()
sw.Write(data);
Flush
StreamWriter
sw.Write(data);
Flush()
private void SaveConfig() {
using (FileStream fs = new FileStream(_configPath, FileMode.OpenOrCreate)) {
Debug.WriteLine("Save Config Triggered");
var data = JsonConvert.SerializeObject(Items);
Debug.WriteLine($"Serialized Config: {data}");
var sw = new StreamWriter(fs);
sw.Write(data);
sw.Flush();
}
}
编辑。。。StreamWriter
应包装在 using
语句中。
进一步的测试表明,将语句包装在 周围是必需的,并且应该实现。因此,将 包装在语句中应该会为您提供数据。以下是该语句的更好方法。Using
StreamWriter
StreamWriter
using
Flush
using
private void SaveConfig() {
using (FileStream fs = new FileStream(_configPath, FileMode.OpenOrCreate)) {
Debug.WriteLine("Save Config Triggered");
var data = JsonConvert.SerializeObject(Items);
Debug.WriteLine($"Serialized Config: {data}");
using (var sw = new StreamWriter(fs)) {
sw.Write(data);
}
}
}
评论