我有以下C#脚本:
public bool Insert(QueryBuilder builder) {
try {
using (FileStream fs = new FileStream(GetFinalPath(builder.GetFileName()), FileMode.Append, FileAccess.Write)) {
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, builder.GetModels());
}
return true;
} catch (IOException e) {
return false;
}
}
当我插入一行时,一切都很好,只要我插入另一行,它就不会显示..
这是我的选择功能
public Collection Select(QueryBuilder builder) {
List<Model> result = new List<Model>();
List<Model> resultHistory = new List<Model>();
Collection collection = new Collection();
try {
using (FileStream fs = new FileStream(GetFinalPath(builder.GetFileName()), FileMode.Open, FileAccess.Read)) {
// check if file isn't empty
if (fs.Length > 0) {
BinaryFormatter formatter = new BinaryFormatter();
result = (List<Model>) formatter.Deserialize(fs);
}
}
// TODO: check this select
if (builder.IsWithHistory()) {
using (FileStream fs = new FileStream(GetFinalPath(builder.GetBackupFileName()), FileMode.Open, FileAccess.Read)) {
// check if file isn't empty
if (fs.Length > 0) {
BinaryFormatter formatter = new BinaryFormatter();
resultHistory = (List<Model>) formatter.Deserialize(fs);
}
}
}
} catch (IOException e) {
}
// check if there are criterias
if (builder.IsSelectAll()) {
collection = new Collection(result, resultHistory);
} else {
var resultList = new List<Model>();
var historyList = new List<Model>();
// loop through initial result
for (int i = 0; i < result.Count; i++) {
var model = result[i];
var properties = model.GetType().GetProperties();
// go through each property of the model
foreach (var property in properties) {
// go through each criteria of the builder map
foreach (var fieldItem in builder.GetMap()) {
// check if criteria is available in the properties
if (property.Name == fieldItem.Key) {
// check if value is equal
// TODO: add string operation support
if (property.GetValue(model).Equals(fieldItem.Value)) {
resultList.Add(model);
}
}
}
}
}
// loop through history result
for (int i = 0; i < resultHistory.Count; i++) {
var model = result[i];
var properties = model.GetType().GetProperties();
// go through each property of the model
foreach (var property in properties) {
// go through each criteria of the builder map
foreach (var fieldItem in builder.GetMap()) {
// check if criteria is available in the properties
if (property.Name == fieldItem.Key) {
// check if value is equal
// TODO: add string operation support
if (property.GetValue(model).Equals(fieldItem.Value)) {
historyList.Add(model);
}
}
}
}
}
collection = new Collection(resultList, historyList);
}
return collection;
}
答案 0 :(得分:0)
是的,这就是问题所在。
据我所知,序列化过程将序列化数据的长度存储在文件中。因此,如果追加数据,反序列化调用只能看到第一个序列化数据,因为它读取了要反序列化的数据的长度。
// Our data to be serialized
str1 = "ThisIsATest"; // length=11
str2 = "Trash"; // length=5
// Thats what the serializer does: Write the length of the data, write the acutal data. The pipe is not written, just for better readability
// Initial file write...
11|ThisIsATest
// Appending the second string
11|ThisIsATest|5|Trash
// The raw file content
11ThisIsATest5Trash
// The deserializer reads the length field and then the number of
// bytes as data and ends there. It does not know that there is other
// data following, since you used to separate serialization calls...
所以你有两个选择:
按照我的第一个答案,或者,如果你想保留文件附加内容,请在formatter.Deserialize
调用后获取流的位置,一次又一次地调用该函数,直到你在流的末尾。