在 JSON.NET 中序列化 DataTable 时调用读取后无法覆盖
Can't overwrite after calling read when serializing DataTable in JSON.NET
我正在使用 C# .NET CORE v5 将 class 写入 serialize/deserialize 一个 class,其中包含一个 JSON 文件的数据表 JSON.net Visual Studio 2019. 当出现以下情况时,写入操作不会覆盖,而是将DataTable追加到文件中。
- 读取操作发生在写入之前。
- 正在序列化的 Class 必须包含 DataTable。
注意:我已经剥离了所有错误处理和支持功能以减少代码的大小,然后放入控制台应用程序中。
我试过的...
- 我发现注释掉 DataTable 似乎可以解决问题。
- 如果删除行“fs.Seek(0, SeekOrigin.Begin);”在读操作中。不过不出所料,这对写操作没有影响。
- 在 CloseFileStream() 函数中,我添加了对 GC.Collect() 的调用以确保 GC 正在发生,但没有成功。
- 原始函数 WriteJSONFile() 使用了 fileStream。我将其更改为其他方法,但问题仍然存在。请参阅该功能中的评论。
当我 运行 下面的代码时,我希望 JSON 文件包含以下内容。
{
"Name": "Test Name",
"dt": [
{
"Name": "Buckaroo Banzai",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Hoban Washburne",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Dr. Morbius",
"Num": 1,
"Test,typeof(string)": "abcd"
}
]
}
相反,我得到了这个文件,请注意 DataTable 被复制了两次。
{
"Name": "Test Name",
"dt": [
{
"Name": "Buckaroo Banzai",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Hoban Washburne",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Dr. Morbius",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Buckaroo Banzai",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Hoban Washburne",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Dr. Morbius",
"Num": 1,
"Test,typeof(string)": "abcd"
}
]
}
public static class FileOperations
{
private static FileStream fs = null;
private static string currentPath = null;
private static bool OpenFileStream(string path)
{
fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
currentPath = path;
return true;
}
public static bool ReadJSONFile<T>(string path, out T returnedInstanceOfClassFromJSONFile)
{
returnedInstanceOfClassFromJSONFile = default(T); //set to null
bool bSuccessOpenFileStream = true;
if (path != currentPath)
{
CloseFileStream();
bSuccessOpenFileStream = OpenFileStream(path);
}
if (bSuccessOpenFileStream)
{
using (StreamReader reader = new StreamReader(fs, Encoding.UTF8, true, 4096, leaveOpen: true))
using (JsonReader jreader = new JsonTextReader(reader))
{
fs.Seek(0, SeekOrigin.Begin);
JsonSerializer serializer = new JsonSerializer();
returnedInstanceOfClassFromJSONFile = (T)serializer.Deserialize(jreader, typeof(T));
}
return true;
}
return false;
}
public static bool WriteJSONFile(string path, object objectToSerialize)
{
CloseFileStream();
//I first tried using the streamwrite, but it has the same problem for example
//using (StreamWriter sw = new StreamWriter(fs, ....)
//using (JsonWriter writer = new JsonTextWriter(sw))
//{
// serializer.Serialize(writer, objectToSerialize);
//}
File.WriteAllText(path, JsonConvert.SerializeObject(objectToSerialize));
bool bSuccessOpenFileStream = OpenFileStream(path);
return bSuccessOpenFileStream;
}
private static void CloseFileStream()
{
if (fs != null)
{
fs.Close();
fs = null;
//shouldn't be requried, trying out of desperation
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
使用以下代码。请注意,如果您注释掉 ReadJSONFile,则不会出现此问题。
static void Main(string[] args)
{
Simple simple = new Simple();
string path = @"c:\somepath";
FileOperations.WriteJSONFile(path, simple);
FileOperations.ReadJSONFile(path, out simple); //comment this out and it works as expected
FileOperations.WriteJSONFile(path, simple);
FileOperations.WriteJSONFile(path, simple);
FileOperations.WriteJSONFile(path, simple);
FileOperations.WriteJSONFile(path, simple);
}
}
public class Simple
{
public string Name { get; set; }
public DataTable dt { get; set; }
public Simple()
{
Name = "Test Name";
dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Num", typeof(long));
dt.Columns.Add("Test,typeof(string)");
dt.Rows.Add("Buckaroo Banzai", 1, "abcd");
dt.Rows.Add("Hoban Washburne", 1, "abcd");
dt.Rows.Add("Dr. Morbius", 1, "abcd");
}
}
我认为这种情况发生在这条线上:
FileOperations.ReadJSONFile(path, out simple);
这一行实例化了一个简单对象
这会调用构造函数
构造函数用 3 行填充数据表
然后 ReadJSONFile 方法用文件中的数据填充对象 - 添加另外 3 行
我正在使用 C# .NET CORE v5 将 class 写入 serialize/deserialize 一个 class,其中包含一个 JSON 文件的数据表 JSON.net Visual Studio 2019. 当出现以下情况时,写入操作不会覆盖,而是将DataTable追加到文件中。
- 读取操作发生在写入之前。
- 正在序列化的 Class 必须包含 DataTable。
注意:我已经剥离了所有错误处理和支持功能以减少代码的大小,然后放入控制台应用程序中。
我试过的...
- 我发现注释掉 DataTable 似乎可以解决问题。
- 如果删除行“fs.Seek(0, SeekOrigin.Begin);”在读操作中。不过不出所料,这对写操作没有影响。
- 在 CloseFileStream() 函数中,我添加了对 GC.Collect() 的调用以确保 GC 正在发生,但没有成功。
- 原始函数 WriteJSONFile() 使用了 fileStream。我将其更改为其他方法,但问题仍然存在。请参阅该功能中的评论。
当我 运行 下面的代码时,我希望 JSON 文件包含以下内容。
{
"Name": "Test Name",
"dt": [
{
"Name": "Buckaroo Banzai",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Hoban Washburne",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Dr. Morbius",
"Num": 1,
"Test,typeof(string)": "abcd"
}
]
}
相反,我得到了这个文件,请注意 DataTable 被复制了两次。
{
"Name": "Test Name",
"dt": [
{
"Name": "Buckaroo Banzai",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Hoban Washburne",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Dr. Morbius",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Buckaroo Banzai",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Hoban Washburne",
"Num": 1,
"Test,typeof(string)": "abcd"
},
{
"Name": "Dr. Morbius",
"Num": 1,
"Test,typeof(string)": "abcd"
}
]
}
public static class FileOperations
{
private static FileStream fs = null;
private static string currentPath = null;
private static bool OpenFileStream(string path)
{
fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
currentPath = path;
return true;
}
public static bool ReadJSONFile<T>(string path, out T returnedInstanceOfClassFromJSONFile)
{
returnedInstanceOfClassFromJSONFile = default(T); //set to null
bool bSuccessOpenFileStream = true;
if (path != currentPath)
{
CloseFileStream();
bSuccessOpenFileStream = OpenFileStream(path);
}
if (bSuccessOpenFileStream)
{
using (StreamReader reader = new StreamReader(fs, Encoding.UTF8, true, 4096, leaveOpen: true))
using (JsonReader jreader = new JsonTextReader(reader))
{
fs.Seek(0, SeekOrigin.Begin);
JsonSerializer serializer = new JsonSerializer();
returnedInstanceOfClassFromJSONFile = (T)serializer.Deserialize(jreader, typeof(T));
}
return true;
}
return false;
}
public static bool WriteJSONFile(string path, object objectToSerialize)
{
CloseFileStream();
//I first tried using the streamwrite, but it has the same problem for example
//using (StreamWriter sw = new StreamWriter(fs, ....)
//using (JsonWriter writer = new JsonTextWriter(sw))
//{
// serializer.Serialize(writer, objectToSerialize);
//}
File.WriteAllText(path, JsonConvert.SerializeObject(objectToSerialize));
bool bSuccessOpenFileStream = OpenFileStream(path);
return bSuccessOpenFileStream;
}
private static void CloseFileStream()
{
if (fs != null)
{
fs.Close();
fs = null;
//shouldn't be requried, trying out of desperation
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
使用以下代码。请注意,如果您注释掉 ReadJSONFile,则不会出现此问题。
static void Main(string[] args)
{
Simple simple = new Simple();
string path = @"c:\somepath";
FileOperations.WriteJSONFile(path, simple);
FileOperations.ReadJSONFile(path, out simple); //comment this out and it works as expected
FileOperations.WriteJSONFile(path, simple);
FileOperations.WriteJSONFile(path, simple);
FileOperations.WriteJSONFile(path, simple);
FileOperations.WriteJSONFile(path, simple);
}
}
public class Simple
{
public string Name { get; set; }
public DataTable dt { get; set; }
public Simple()
{
Name = "Test Name";
dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Num", typeof(long));
dt.Columns.Add("Test,typeof(string)");
dt.Rows.Add("Buckaroo Banzai", 1, "abcd");
dt.Rows.Add("Hoban Washburne", 1, "abcd");
dt.Rows.Add("Dr. Morbius", 1, "abcd");
}
}
我认为这种情况发生在这条线上:
FileOperations.ReadJSONFile(path, out simple);
这一行实例化了一个简单对象
这会调用构造函数
构造函数用 3 行填充数据表
然后 ReadJSONFile 方法用文件中的数据填充对象 - 添加另外 3 行