2010-05-28 7 views
1

J'ai un ensemble de données en C# que je peux sérialiser en utilisant dataset.WriteXml(filename); mais je veux que le fichier contienne aussi d'autres données (essentiellement des méta-données sur l'ensemble de données).Le moyen le plus simple de combiner un ensemble de données et d'autres données dans un seul fichier?

Je pourrais ajouter une autre table à l'ensemble de données qui contenait les métadonnées, mais je préférerais le garder séparé, si possible.

Essentiellement, je pense que je veux créer une «combinaison de fichiers de fichier, qui ressemble à ceci:

size_of_file1 
file1 
size_of_file2 
file2 
... etc 

Ensuite, je voudrais charger le fichier dans la mémoire, et diviser le fichier en flux distincts, de sorte que je peux nourrir l'ensemble de données dans dataset.ReadXml(stream); et les métadonnées dans quelque chose d'autre.

Son possible? Quelqu'un peut-il me dire comment je peux le faire?

Merci

Tim


PS. Je voudrais que le fichier résultant reste lisible par l'homme.

Répondre

1

Ceci est possible.

Vous devez en faire un fichier binaire (illisible) et utiliser les classes BinaryWriter et BinaryReader pour lire et écrire les longueurs.

Vous pouvez lire un fichier comme ceci:

using (FileStream combinedFile = File.Open(...)) 
using (var binReader = new BinaryReader(combinedFile)) { 
    while(!combinedFile.EOF) { 
     long segmentLength = binReader.ReadInt64(); 

     var bytes = new byte[segmentLength]; 
     long totalRead = 0; 
     while(bytesRead < segmentLength) { 
      int read = combinedFile.Read(bytes, totalRead, Math.Min(4096, segmentLength - totalRead)); 
      if (read == 0) 
       throw new InvalidDataException(); 
     } 

     yield return new MemoryStream(bytes); 
    } 
} 

EDIT Pour créer un fichier lisible par l'homme, écrire la longueur du segment en tant que chaîne de longueur fixe (rembourré à un nombre raisonnable de chiffres , tel que 16), éventuellement suivi d'une nouvelle ligne. La taille de segment maximale est la longueur de la chaîne.

Vous pouvez lire un fichier comme ceci:

const int LengthPadding = 16 

using (FileStream combinedFile = File.Open(...)) 
using (var binReader = new BinaryReader(combinedFile)) { 
    while(!combinedFile.EOF) { 
     char[] segmentLengthChars = binReader.ReadChars(16); 

     long segmentLength = long.Parse(new string(segmentLengthChars)); 

     binReader.ReadChars(2); //Skip the newline 

     var bytes = new byte[segmentLength]; 
     long totalRead = 0; 
     while(bytesRead < segmentLength) { 
      int read = combinedFile.Read(bytes, totalRead, Math.Min(4096, segmentLength - totalRead)); 
      if (read == 0) 
       throw new InvalidDataException(); 
     } 

     yield return new MemoryStream(bytes); 
    } 
} 

Pour écrire la longueur du segment, appelez

binWriter.WriteChars(length.ToString().PadLeft(16, '0').ToCharArray()); 
binWriter.WriteChars(new char[] { '\r', '\n' }); 

Vous devez passer explicitement un codage et CultureInfo.InvariantCulture le cas échéant.

+0

Désolé - Je dois que ce soit lisible par l'homme! Je vais ajouter cela à la question. Est-il possible de le faire et de le rendre lisible par l'homme? –

1

Vous pouvez étendre l'objet DataSet ajouter vos métadonnées en tant que propriétés et sérialisation que ...

+0

J'ai essayé d'ajouter une propriété de chaîne simple à l'objet dataset et lui ai donné une valeur, mais la fonction WriteXml() n'a pas sérialisé la valeur pour moi - que dois-je faire pour sérialiser mes propriétés supplémentaires? –

+0

Vous pourriez essayer d'ajouter le [XmlElement ("Property_MyNewStringProperty"]] dans l'espoir de dire au sérialiseur qu'il doit faire attention à la propriété de la chaîne. – priehl

1

Si elle doit être lisible utilisation d'un fichier XML. Stockez les métadonnées dans un élément et l'ensemble de données dans un autre élément.

This thread will show you how

1

Si vous voulez écrire simplement le XML sur un nœud après l'autre comme celui-ci:

DataSet ds; 
// populate ds with some data 
string serialized; 
using (System.IO.StringWriter sw = new System.IO.StringWriter()) 
{ 
    string metaData = "<MetaData version=\"1.0\" date=\"" + System.Xml.XmlConvert.ToString(DateTime.Now) + "\">" + 
     "<Detail>Some more details</Detail></MetaData>"; 
    sw.Write(metaData); 
    ds.WriteXml(sw, System.Data.XmlWriteMode.WriteSchema); 
    sw.Close(); 
    serialized = sw.ToString(); 
} 

Ensuite, vous pouvez le lire comme une série de noeuds dans un fragment de document XML comme celui-ci , en profitant de la capacité de l'ensemble de données à utiliser un XMLReader:

using (System.IO.StringReader sr = new System.IO.StringReader(serialized)) 
{ 
    System.Xml.XmlReaderSettings xs = new System.Xml.XmlReaderSettings(); 
    xs.ConformanceLevel = System.Xml.ConformanceLevel.Fragment; 
    System.Xml.XmlReader xr = System.Xml.XmlTextReader.Create(sr, xs); 
    xr.Read(); 
    string metaData = xr.ReadOuterXml(); 
    Console.WriteLine(metaData); 
    ds = new System.Data.DataSet(); 
    ds.ReadXml(xr); 
    ds.WriteXml(Console.Out); 
} 
Questions connexes