web-dev-qa-db-fra.com

Lire les nombres d'un fichier texte en C #

C'est quelque chose qui devrait être très simple. Je veux juste lire les chiffres et les mots d'un fichier texte composé de jetons séparés par des espaces. Comment faites-vous cela en C #? Par exemple, en C++, le code suivant fonctionnerait pour lire un entier, un float et Word. Je ne veux pas avoir à utiliser une expression régulière ou écrire un code d'analyse syntaxique spécial.

ifstream in("file.txt");
int int_val;
float float_val;
string string_val;
in >> int_val >> float_val >> string_val;
in.close();

De plus, chaque fois qu'un jeton est lu, il ne doit pas y avoir plus d'un caractère au-delà du jeton. Cela permet à la lecture ultérieure du fichier de dépendre de la valeur du jeton lu. Comme exemple concret, considérons

string decider;
int size;
string name;

in >> decider;
if (decider == "name")
    in >> name;
else if (decider == "size")
    in >> size;
else if (!decider.empty() && decider[0] == '#')
    read_remainder_of_line(in);

L'analyse d'un fichier PNM binaire est également un bon exemple de la raison pour laquelle vous souhaitez arrêter de lire un fichier dès qu'un jeton complet est lu.

19
Joe

La réponse de Brannon explique comment lire les données binaires. Si vous voulez lire des données text, vous devez lire les chaînes, puis les analyser - pour lesquelles il existe des méthodes intégrées, bien sûr.

Par exemple, pour lire un fichier avec des données:

10
10.5
hello

Vous pourriez utiliser:

using (TextReader reader = File.OpenText("test.txt"))
{
    int x = int.Parse(reader.ReadLine());
    double y = double.Parse(reader.ReadLine());
    string z = reader.ReadLine();
}

Notez que cela n'a pas de traitement d'erreur. En particulier, il lève une exception si le fichier n'existe pas, si les deux premières lignes contiennent des données inappropriées ou s'il y a moins de deux lignes. La valeur null sera laissée dans z si le fichier ne comporte que deux lignes.

Pour une solution plus robuste qui peut échouer plus facilement, vous voudrez vérifier si reader.ReadLine() a retourné null (indiquant la fin du fichier) et utiliser int.TryParse et double.TryParse au lieu des méthodes Parse.

Cela suppose qu’il existe un séparateur de ligne entre les valeurs. Si vous voulez réellement lire une chaîne comme ceci:

10 10.5 hello

alors le code serait très similaire:

using (TextReader reader = File.OpenText("test.txt"))
{
    string text = reader.ReadLine();
    string[] bits = text.Split(' ');
    int x = int.Parse(bits[0]);
    double y = double.Parse(bits[1]);
    string z = bits[2];
}

Là encore, vous souhaiterez effectuer une détection et une gestion des erreurs appropriées. Notez que si le fichier ne contient en réalité qu'une seule ligne, vous pouvez utiliser plutôt File.ReadAllText, pour le rendre légèrement plus simple. Il y a aussi File.ReadAllLines qui lit l'intégralité du fichier dans un tableau de lignes.

EDIT: Si vous devez scinder tout espace, vous feriez mieux de lire le fichier entier avec File.ReadAllText, puis d’utiliser une expression régulière pour le scinder. À ce stade, je me demande comment vous représentez une chaîne contenant un espace.

D'après mon expérience, vous en savez généralement plus sur le format - qu'il y ait un séparateur de ligne ou plusieurs valeurs dans la même ligne, séparées par des espaces, etc.

J'ajouterais également que les formats mixtes binaire/texte sont généralement désagréables. La gestion simple et efficace du texte a tendance à être lue dans une mémoire tampon, ce qui devient problématique s'il existe également des données binaires. Si vous avez besoin d’une section de texte dans un fichier binaire, il est généralement préférable d’inclure un préfixe de longueur afin de ne pouvoir décoder que cette donnée.

23
Jon Skeet
using (FileStream fs = File.OpenRead("file.txt"))
{
    BinaryReader reader = new BinaryReader(fs);

    int intVal = reader.ReadInt32();
    float floatVal = reader.ReadSingle();
    string stringVal = reader.ReadString();
}
10
Brannon

J'aime utiliser StreamReader pour un accès rapide et facile aux fichiers. Quelque chose comme....

  String file = "data_file.txt";    
  StreamReader dataStream = new StreamReader(file);   
  string datasample;
  while ((datasample = dataStream.ReadLine()) != null)
  {

     // datasample has the current line of text - write it to the console.
     Console.Writeline(datasample);
  }
4
Paul

Pas exactement la réponse à votre question, mais juste une idée à considérer si vous débutez en C #: si vous utilisez un fichier texte personnalisé pour lire certains paramètres de configuration, vous pouvez vérifier les sujets de sérialisation XML dans .NET.

La sérialisation XML fournit un moyen simple d'écrire et de lire des fichiers au format XML. Par exemple, si vous avez une classe de configuration comme celle-ci:

public class Configuration
{
   public int intVal { get; set; }
   public float floatVal { get; set; }
   public string stringVal { get; set; }
}

vous pouvez simplement le sauvegarder et le charger en utilisant la classe XmlSerializer :

public void Save(Configuration config, string fileName)
{
   XmlSerializer xml = new XmlSerializer(typeof(Configuration));
   using (StreamWriter sw = new StreamWriter(fileName))
   {
       xml.Serialize(sw, config);
   }
}

public Configuration Load(string fileName)
{
   XmlSerializer xml = new XmlSerializer(typeof(Configuration));
   using (StreamReader sr = new StreamReader(fileName)))
   {
       return (Configuration)xml.Deserialize(sr);
   }
}

La méthode Save telle que définie ci-dessus crée un fichier avec le contenu suivant:

<Configuration>
    <intVal>0</intVal>
    <floatVal>0.0</floatVal>
    <stringVal></stringVal>
</Configuration>

L'avantage de cette approche est qu'il n'est pas nécessaire de changer les méthodes Save et Load si votre classe Configuration change.

3
Groo

C # ne semble pas avoir de lecteurs de flux formatés comme le C++ (je serais heureux d’être corrigé). Donc, l’approche de Jon Skeet consistant à lire le contenu sous forme de chaîne et à les analyser selon le type souhaité serait la meilleure solution.

0
Ramashish Baranwal

Essayez quelque chose comme ça: 

http://stevedonovan.blogspot.com/2005/04/reading-numbers-from-file-in-c.html

IMHO Peut-être pour lire un tutoriel c #, il sera vraiment utile d'avoir une vue d'ensemble avant de demander

0
jrbalderrama