2009-12-29 6 views
2

Actuellement, j'ai une application qui lit et écrit plusieurs propriétés d'une ou deux classes de base dans un fichier .txt en utilisant le Serializer binaire.Comment enregistrer un fichier lisible par l'homme

J'ai ouvert le fichier txt dans notepad et comme il est formaté pour l'application, il est pas très lisible à l'œil humain, pas pour moi en tout cas = D

J'ai entendu d'utiliser XML, mais assez la plupart de mes recherches semblent trop compliquées.

Le type de données que j'essaie de sauvegarder est simplement une collection de classes "Person.cs", rien de plus qu'un nom et une adresse, toutes les chaînes privées mais avec des propriétés et marquées Serializable.

Quelle serait la meilleure façon d'enregistrer réellement mes données d'une manière qui puisse être facilement lue par une personne? Il serait également plus facile d'apporter de petites modifications aux données de l'application directement dans le fichier au lieu de devoir le charger, le modifier et l'enregistrer.

Edit:

J'ai ajouté la façon actuelle je suis enregistrement et le chargement de mes données, mon _userCollection est qu'il suggère et Nuser/nMember sont un entier.

#region I/O Operations 

    public bool SaveData() 
    { 
     try 
     { 
      //Open the stream using the Data.txt file 
      using (Stream stream = File.Open("Data.txt", FileMode.Create)) 
      { 
       //Create a new formatter 
       BinaryFormatter bin = new BinaryFormatter(); 
       //Copy data in collection to the file specified earlier 
       bin.Serialize(stream, _userCollection); 
       bin.Serialize(stream, nMember); 
       bin.Serialize(stream, nUser); 
       //Close stream to release any resources used 
       stream.Close(); 
      } 
      return true; 
     } 
     catch (IOException ex) 
     { 
      throw new ArgumentException(ex.ToString()); 
     } 
    } 

    public bool LoadData() 
    { 
     //Check if file exsists, otherwise skip 
     if (File.Exists("Data.txt")) 
     { 
      try 
      { 
       using (Stream stream = File.Open("Data.txt", FileMode.Open)) 
       { 
        BinaryFormatter bin = new BinaryFormatter(); 

        //Copy data back into collection fields 
        _userCollection = (List<User>)bin.Deserialize(stream); 
        nMember = (int)bin.Deserialize(stream); 
        nUser = (int)bin.Deserialize(stream); 
        stream.Close(); 

        //Sort data to ensure it is ordered correctly after being loaded 
        _userCollection.Sort(); 
        return true; 

       } 
      } 
      catch (IOException ex) 
      { 
       throw new ArgumentException(ex.ToString()); 
      } 
     } 
     else 
     { 
      //Console.WriteLine present for testing purposes 
      Console.WriteLine("\nLoad failed, Data.txt not found"); 
      return false; 
     } 
    } 

Répondre

6

Remplacez votre BinaryFormatter par XMLSerializer et exécutez le même code exact.

Le seul changement que vous devez faire est le BinaryFormatter prend un constructeur vide, alors que pour l'XMLSerializer vous devez déclarer le type dans le constructeur:

XmlSerializer serializer = new XmlSerializer(typeof(Person)); 
+0

XmlSerializer a un certain nombre de limitations par rapport à BinaryFormatter ... par exemple, il ne peut pas sérialiser les données privées. DataContractSerializer est probablement un meilleur choix –

+0

Le DataContractSerializer est amusant, mais personnellement je pense que l'utilisation de XMLSerializer est plus proche du BinaryFormatter en raison de la nature non opt-in et des mêmes attributs. –

+0

Je pense que Thomas est plus proche de la vérité ici ... en particulier, avec le service-pack, le comportement par défaut de DCS contre un type non-attribué est très similaire à BF. Bien sûr, ni BF ni DCS non-attribué est une bonne option, pour exactement cette raison! –

3

Vous pouvez mettre en œuvre votre propre PersonsWriter, qui prend un StreamWriter comme argument du constructeur et a une méthode qui prend un WriteIList<Person> comme entrée pour analyser une représentation textuelle agréable.

Par exemple:

public class PersonsWriter : IDisposable 
{ 
    private StreamWriter _wr; 

    public PersonsWriter(IList<Person> persons, StreamWriter writer) 
    { 
     this._wr = writer; 
    } 

    public void Write(IList<Persons> people) { 
     foreach(Person dude in people) 
     { 
      _wr.Write(@"{0} {1}\n{2}\n{3} {4}\n\n", 
       dude.FirstName, 
       dude.LastName, 
       dude.StreetAddress, 
       dude.ZipCode, 
       dude.City); 
     } 
    } 

    public void Dispose() 
    { 
     _wr.Flush(); 
     _wr.Dispose(); 
    } 
} 
+0

C'est une bonne idée, mais je voudrais qu'il soit générique, donc je peux l'utiliser dans d'autres applications, car ils utilisent actuellement la même méthode pour enregistrer des données. –

0

Essayez le DataContractSerializer

Il sérialise objets en XML et est très facile à utiliser

+0

Je dirais que cette partie * facile à utiliser *. –

1

YAML est une autre option pour le balisage lisible par l'homme qui est également facile à analyser.Il existe des bibliothèques disponibles pour C# ainsi que presque toutes les autres langues populaires. Voici un échantillon de ce que yaml ressemble à:

invoice: 34843 
date : 2001-01-23 
bill-to: &id001 
    given : Chris 
    family : Dumars 
    address: 
     lines: | 
      458 Walkman Dr. 
      Suite #292 
     city : Royal Oak 
     state : MI 
     postal : 48046 
0

Je pense vraiment que vous devriez aller avec XML (regarder dans DataContractSerializer). Ce n'est pas si compliqué. Vous pourriez probablement même juste remplacer BinarySerializer avec XMLSerializer et aller.

Si vous ne voulez toujours pas faire cela, vous pouvez écrire un fichier texte délimité. Ensuite, vous devrez écrire votre propre méthode de lecture (bien que vous puissiez presque utiliser la méthode split).

//Inside the Person class: 
public override string ToString() 
{ 
    List<String> propValues = new List<String>(); 

    // Get the type. 
    Type t = this.GetType(); 

    // Cycle through the properties. 
    foreach (PropertyInfo p in t.GetProperties()) 
    { 
     propValues.add("{0}:={1}", p.Name, p.GetValue(o, null)); 
    } 

    return String.Join(",". propValues.ToArray()) 
} 

using (System.IO.TextWriter tw = new System.IO.StreamWriter("output.txt")) 
{ 
    tw.WriteLine(person.ToString()); 
} 
1

Franchement, comme un être humain, je ne trouve pas XML à tout ce que lisible. En fait, ce n'est pas vraiment conçu pour être lu par les humains.

Si vous voulez un format lisible par l'homme, alors vous devez le construire. Par exemple, vous avez une classe Personne qui a un prénom, un nom de famille et un numéro de sécurité sociale en tant que propriétés. Créez votre fichier, et faites-lui écrire 3 lignes, avec une description du champ dans les cinquante premiers (nombre aléatoire de ma tête) et ensuite avec le caractère 51, la valeur commence à être écrite.

Cela produira un fichier qui ressemble comme:

First Name-------Stephen 
Last Name -------Wrighton 
SSN -------------XXX-XX-XXXX 

Puis, en les lisant, votre programme devrait savoir où les données commence sur chaque ligne, et ce que chaque ligne est pour (le programme saurais que la ligne 3 est la valeur du SSN). Mais rappelez-vous, pour vraiment gagner en lisibilité humaine, vous sacrifiez la portabilité des données.

+0

En fait SGML, dont XML est une dérivée, a été conçu exactement pour être lisible par l'homme tout en maintenant la possibilité de l'analyser par programmation, d'où sa verbosité. C'est aussi dans la recommandation XML 1.0. 'Les documents XML devraient être lisibles par l'homme et raisonnablement clairs. 'Trouvé: http://www.w3.org/TR/xml/#sec-origin-goals Si ce n'était pas pour cela, JSON (ou similaire compact orienté vers les données langues) serait un meilleur choix. +1 pour avoir remarqué que la "vraie" lisibilité humaine porte la portabilité. –

+1

Bon point, mais OMI, il y a une différence entre humain-lisible et lisible par l'homme. humain-lisible signifie qu'il peut être interprété dans un format lisible par l'homme avec une certaine pensée mais n'a pas besoin d'interprétation par ordinateur, tandis que lisible par l'homme signifie que les données sont stockées/affichées dans un format que les humains peuvent facilement consommer.Un exemple pas parfait: l'ouverture d'un fichier HTML dans le Bloc-notes est humainement lisible alors que l'ouverture de ce même fichier HTML dans FireFox est lisible par l'homme. –

Questions connexes