好的,只是为了总结一下,这就是我登陆的地方。最后,我只是自己将二进制文件解析为相关记录,因为我没有使用任何 Faircom 东西所需的原始模式文件. 重新创建文件的任务与在 C# 中解析二进制文件所花费的时间一样多,因为这非常简单。
我确实看到 0xFA 记录似乎是“真实”记录,而 0xFD 记录表示它们已被“删除”。如果您更改了文件但尚未保存,原始程序确实能够“还原”文件,因此 faircom 数据库结构在 1994 年就允许它成为相当交钥匙的工具。
其他可能特定于或可能不特定于我的架构的一般观察结果...我有以下数据类型...字符串、字符串数组、字节数组、数字
我创建了一个看起来像这样的小 SchemaDefinition..
schema = new CTreeSchema();
schema.Columns.Add(new CTreeColumn("Ordinal", CTreeColumnType.Number, 4));
schema.Columns.Add(new CTreeColumn("Unknown3", CTreeColumnType.Number, 4));
schema.Columns.Add(new CTreeColumn("Unknown4", CTreeColumnType.Number, 4));
schema.Columns.Add(new CTreeColumn("Name", CTreeColumnType.String, 0));
schema.Columns.Add(new CTreeColumn("ExtendedData", CTreeColumnType.StringArray, 0));
然后我用这样的东西解析它......
public CTreeRecord(CTreeSchema schema, byte[] bytes)
{
_internalBytes = bytes;
RecordTypeId = bytes[0];
int byteIndex = 6;
foreach(var i in schema.Columns)
{
int endIndex = 0;
switch (i.Type)
{
case CTreeColumn.CTreeColumnType.String:
if (i.Length == 0)
{
//null terminated
endIndex = Array.IndexOf<byte>(bytes, 0x00, byteIndex);
i.Value = Encoding.ASCII.GetString(bytes.Skip(byteIndex).Take(endIndex - byteIndex).ToArray());
byteIndex += (1+ endIndex - byteIndex);
}
if (i.Length > 0)
{
//specific length
throw new NotSupportedException("Static Length String columns not supported.");
//byteIndex += i.Length;
}
break;
case CTreeColumn.CTreeColumnType.StringArray:
List<string> headerStrings = new List<string>();
endIndex = Array.IndexOf<byte>(bytes, 0x00, byteIndex);
byte[] arrayBytes = bytes.Skip(byteIndex).Take(endIndex - byteIndex).ToArray();
byteIndex += (1 + endIndex - byteIndex);
List<byte[]> headerBytes = SplitByteString(arrayBytes, 0x01, false);
foreach (byte[] b in headerBytes)
{
headerStrings.Add(Encoding.ASCII.GetString(b));
}
i.Value = headerStrings;
break;
case CTreeColumn.CTreeColumnType.ByteArray:
List<byte[]> byteArray = new List<byte[]>();
for (int a = 0; a < i.Length; a++)
{
endIndex = Array.IndexOf<byte>(bytes, 0x00, byteIndex);
byteArray.Add(bytes.Skip(byteIndex).Take(endIndex - byteIndex).ToArray());
byteIndex += (1 + endIndex - byteIndex);
}
i.Value = byteArray;
break;
case CTreeColumn.CTreeColumnType.Number:
switch (i.Length)
{
case 2:
i.Value = BitConverter.ToUInt16(bytes, byteIndex);
break;
case 4:
i.Value = BitConverter.ToUInt32(bytes, byteIndex);
break;
}
byteIndex += i.Length;
break;
case CTreeColumn.CTreeColumnType.Date:
throw new NotSupportedException("Date columns not supported.");
break;
}
Columns.Add(i);
}
}
private List<byte[]> SplitByteString(byte[] bytes, byte splitValue, bool removeEmptyEntries)
{
List<byte[]> splitBytes = new List<byte[]>();
int currentIndex = 0;
while (currentIndex < bytes.Length)
{
int splitIndex = Array.IndexOf<byte>(bytes, splitValue, currentIndex);
if (splitIndex >= 0)
{
//found one
int currentLength = splitIndex - currentIndex;
if (!(currentLength == 0 && removeEmptyEntries))
{
splitBytes.Add(bytes.Skip(currentIndex).Take(currentLength).ToArray());
currentIndex += (1 + currentLength);
}
else
{
currentIndex++;
}
}
else
{
//not found, just take until end now..
splitBytes.Add(bytes.Skip(currentIndex).Take(bytes.Length - currentIndex).ToArray());
currentIndex += (bytes.Length - currentIndex);
}
}
return splitBytes;
}
总而言之,它非常丑陋并且非常特定于这个应用程序,但是如果有人必须处理 C Faircom 数据库文件,这可能会提供一些理智。