Comment extraire les données d'un champ Mémo FoxPro à l'aide de .NET?
-
06-07-2019 - |
Question
J'écris un programme C # pour convertir une base de données FoxPro en XML et tout fonctionne, sauf que le champ Mémo est vide. Y at-il quelque chose qui me manque pour convertir ce bit?
J'utilise C # .Net 3.5 SP1, pilote OLE DB pour Visual FoxPro 9 SP 1. La chaîne de connexion est correcte, toutes les autres données étant extraites correctement.
Lorsque j'ai converti la base de données FoxPro en SQL Server, le champ Mémo y est également vide. Je ne peux donc pas convertir deux fois.
La solution
Nous avons fini par devoir travailler moi-même, mais peut-être que cela pourrait aider quelqu'un d'autre à l'avenir:
public static object GetDbaseOrFoxproRawValue(string DBPath, string TableName, string ColumnName,
string CompareColumnName, string CompareValue, bool CompareColumnIsAutoKey)
{
using (BinaryReader read = new BinaryReader(File.Open(
Path.Combine(DBPath, TableName + ".dbf"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
// Is it a type of file that I can handle?
if (new byte[] { 0x02, 0x03, 0x30, 0x43, 0x63, 0x83, 0x8b,
0xcb, 0xf5, 0xfb }.Contains(read.ReadByte()))
{
// Skip date.
read.BaseStream.Seek(3, SeekOrigin.Current);
// Read useful datas...
uint RecordCount = read.ReadUInt32();
ushort FirstRecord = read.ReadUInt16();
ushort RecordLength = read.ReadUInt16();
int FieldCount = FirstRecord - 296 / 32;
// Make sure things aren't stupid.
ColumnName = ColumnName.ToLower();
CompareColumnName = CompareColumnName.ToLower();
// Find target column (field)
string temp;
UInt32 CompareFieldOffset = uint.MaxValue, FieldOffset = uint.MaxValue;
byte CompareFieldLength = 0, FieldLength = 0;
char FieldType = ' ';
for (int i = 0; i < FieldCount; i++)
{
read.BaseStream.Seek(32 + (i * 32), SeekOrigin.Begin);
temp = Encoding.ASCII.GetString(read.ReadBytes(11)).Replace("\0", "").ToLower();
if (temp == CompareColumnName)
{
read.ReadChar();
CompareFieldOffset = read.ReadUInt32();
CompareFieldLength = read.ReadByte();
}
if (temp == ColumnName)
{
FieldType = read.ReadChar();
FieldOffset = read.ReadUInt32();
FieldLength = read.ReadByte();
}
if (CompareFieldOffset != uint.MaxValue && FieldOffset != uint.MaxValue)
break;
}
// Make sure we can continue.
if (CompareFieldOffset == uint.MaxValue ||
FieldOffset == uint.MaxValue) return null;
// Iterate through each record to find the one we want.
for (int index = 0; index < RecordCount; index++)
{
read.BaseStream.Seek(FirstRecord + (index * RecordLength) + CompareFieldOffset, SeekOrigin.Begin);
temp = Encoding.Default.GetString(read.ReadBytes(CompareFieldLength)).Replace("\0", "");
if (temp == CompareValue)
{
read.BaseStream.Seek(FirstRecord + (index * RecordLength) + FieldOffset, SeekOrigin.Begin);
switch (FieldType)
{
case 'M':
case 'I': return read.ReadUInt32();
case 'C':
default: return Encoding.Default.GetString(read.ReadBytes(FieldLength)).Replace("\0", "");
}
}
}
}
else
{
return null;
}
}
return null;
}
Il suffit de saisir le résultat et de l’utiliser comme index dans le fichier mémo (ce code est assez simple à l’aide de la documentation MSDN).
Autres conseils
Je ne connais pas très bien C #, FoxPro ou SQL Server. Je ne peux donc pas vous donner beaucoup de conseils à cet égard.
Toutefois, si vous ne trouvez pas de pilote approprié, vous pouvez envisager d’analyser vous-même les données brutes et les fichiers mémo. Une autre question a traité de cela:
Quel est le moyen le plus simple de lire un fichier FoxPro DBF à partir de Python?
Croyez-le ou non, ces formats de fichiers sont assez simples à analyser si vous décidez d'écrire votre propre analyseur C #. Ces spécifications sont disponibles auprès de Microsoft:
J'utilise ODBC pour relier les tables VFP 8 et les champs de mémo fonctionnent sans problème. Je ne sais pas si OLEDB est différent.
Vous n'avez peut-être pas de tables Visual FoxPro ici. De nombreux systèmes VFP utilisent les mêmes tables que l'application FoxPro 2 ou dBase qu'ils ont remplacée. Vous pouvez consulter l'en-tête du fichier ou simplement essayer l'un des autres pilotes ODBC pour voir s'ils fonctionnent.