web-dev-qa-db-fra.com

Comment lire une ligne spécifique dans un fichier texte?

Avec un fichier texte, comment pourrais-je lire une ligne arbitraire et rien d’autre dans le fichier?

Dis, j'ai un fichier test.txt. Comment pourrais-je lire la ligne numéro 15 du fichier?

Tout ce que j'ai vu, c’est que l’ensemble du fichier texte est stocké sous la forme d’un tableau String, puis que la valeur du numéro de ligne est utilisée comme numéro de la chaîne à utiliser dans le tableau ... mais il existe certaines complications: Le fichier texte est énormément énorme et la machine que l'application que je code n'est pas vraiment un système de premier ordre. La vitesse n’est pas la priorité absolue, mais c’est un problème majeur.

Existe-t-il un moyen de SEULEMENT lire une ligne spécifique d'un fichier texte et stocker le résultat sous forme de chaîne?

Merci pour vos réponses: Le fichier est structuré en KINDA. Il contient 25 lignes d’informations, puis X lignes de chiffres, mais la ligne 17 des 25 premières a la valeur X.

Mais ensuite, il y a une ligne vide qui se répète partout comme un second enregistrement dans le fichier et X peut avoir une valeur différente pour chaque enregistrement.

Ce que je veux faire, c'est lire et stocker les 25 premières lignes en tant que valeurs indépendantes, puis stocker les prochaines lignes X (généralement environ 250) sous forme de tableau. Ensuite, je vais le stocker dans une base de données SQL et répéter l'opération avec l'enregistrement NEXT jusqu'à ce que j'atteigne l'enregistrement Y (le nombre d'enregistrements dans le fichier est à la ligne 3).

EDIT 2: D'accord, je pense avoir trouvé une solution basée sur une combinaison de réponses de votre part.

Je vais lire les 25 premières lignes et les stocker sous forme de tableau. Je vais copier le contenu pertinent du tableau dans des variables locales, puis supprimer les 25 premières lignes. Ensuite, je peux utiliser les informations pour stocker les prochaines lignes X (la valeur de l'élément 13 dans le tableau) sous forme de tableau, le sérialiser, le stocker dans une base de données puis supprimer les lignes que je viens de lire.

Je pourrais ensuite répéter le processus pour chaque enregistrement suivant.

Bien sûr, cela repose sur une hypothèse que je fais, qui pour être honnête, je ne suis pas sûr que ce soit vrai. Est-il possible de supprimer les premières n lignes d'un fichier texte à partir de C # sans avoir à tout lire et à le réécrire sans les premières n lignes?

50
ankushg

.NET 4.0 edit

Depuis .NET 4.0, il est possible d'accéder directement à une seule ligne d'un fichier. Par exemple, pour accéder à la ligne 15:

string line = File.ReadLines(FileName).Skip(14).Take(1).First();

Cela renverra uniquement la ligne requise


Comme vous ne pouvez pas prédire l'emplacement (pouvez-vous?) De la i-ème ligne du fichier, vous devrez également lire toutes les lignes précédentes. Si le numéro de ligne est petit, cela peut être plus efficace que la méthode ReadAllLines.

string GetLine(string fileName, int line)
{
   using (var sr = new StreamReader(fileName)) {
       for (int i = 1; i < line; i++)
          sr.ReadLine();
       return sr.ReadLine();
   }
}
91
Mehrdad Afshari

Si chaque ligne a une longueur fixe, vous pouvez ouvrir un flux autour d'elle, cherchez (octets par ligne) * n dans le fichier et lisez votre ligne à partir de là. 

using( Stream stream = File.Open(fileName, FileMode.Open) )
{
    stream.Seek(bytesPerLine * (myLine - 1), SeekOrigin.Begin);
    using( StreamReader reader = new StreamReader(stream) )
    {
        string line = reader.ReadLine();
    }
}

Sinon, vous pouvez simplement utiliser StreamReader pour lire les lignes jusqu'à ce que vous trouviez celle que vous voulez. De cette façon, le processus est plus lent mais reste une amélioration par rapport à la lecture de chaque ligne.

using( Stream stream = File.Open(fileName, FileMode.Open) )
{
    using( StreamReader reader = new StreamReader(fileStream) )
    {
        string line = null;
        for( int i = 0; i < myLineNumber; ++i )
        {
            line = reader.ReadLine();
        }
    }
}
12
Dave Downs

Non, malheureusement il n'y en a pas. Au niveau brut, les fichiers ne fonctionnent pas par numéro de ligne. Au lieu de cela, ils travaillent sur une base position/offset. Le système de fichiers racine n'a pas de concept de lignes. C'est un concept ajouté par les composants de niveau supérieur.

Donc, il n'y a aucun moyen de dire au système d'exploitation, s'il vous plaît ouvrir le fichier à la ligne bla. Au lieu de cela, vous devez ouvrir le fichier et éviter de compter les nouvelles lignes jusqu'à ce que vous ayez passé le nombre spécifié. Puis stockez le prochain jeu d'octets dans un tableau jusqu'à ce que vous atteigniez la nouvelle ligne suivante. 

4
JaredPar

Sauf si vous avez des lignes de taille fixe, vous devez lire chaque ligne jusqu'à atteindre la ligne souhaitée. Bien que vous n’ayez pas besoin de stocker chaque ligne, supprimez-la si ce n’est pas la ligne que vous désirez.

Modifier:

Comme mentionné précédemment, il serait également possible de rechercher dans le fichier si les longueurs de ligne étaient prévisibles, c'est-à-dire que vous pourriez appliquer une fonction déterministe pour transformer un numéro de ligne en une position de fichier.

3
Ron Warholic

Comme Mehrdad l'a dit, vous ne pouvez pas rechercher la n-ième ligne sans lire le fichier . Cependant, vous n'avez pas besoin de stocker le fichier entier dans la mémoire, vous devez simplement supprimer les données inutiles.

string line;
using (StreamReader sr = new StreamReader(path))
    for (int i = 0; i<15; i++)
    {
       line = sr.ReadLine();
       if (line==null) break; // there are less than 15 lines in the file
    }
2
VladV

LISEZ CINQ LIGNES CHAQUE FOIS, il suffit de mettre votre déclaration dans la déclaration if, thats it 

        String str1 = @"C:\Users\TEMP\Desktop\StaN.txt";   

        System.IO.StreamReader file = new System.IO.StreamReader(str1);

        line = file.ReadLine();

        Int32 ctn=0;

        try
        {

            while ((line = file.ReadLine()) != null)
            {

                    if (Counter == ctn)
                    {
                        MessageBox.Show("I am here");
                        ctn=ctn+5;
                        continue;
                    }
                    else
                    {
                        Counter++;
                        //MessageBox.Show(Counter.ToString());
                        MessageBox.Show(line.ToString());
                    } 
                }

            file.Close();
        }
        catch (Exception er)
        {

        }
2

Si les lignes ont toutes une longueur fixe, vous pouvez utiliser la méthode Seek d'un flux pour passer à la position de départ correcte. 

Si les lignes ont une longueur variable, vos options sont plus limitées. 

S'il s'agit d'un fichier que vous n'utiliserez qu'une fois, puis que vous supprimerez, vous ferez mieux de le lire et de le travailler en mémoire.

S'il s'agit d'un fichier que vous conservez et dont vous allez lire plus que d'écrire, vous pouvez créer un fichier d'index personnalisé contenant les positions de départ de chaque ligne. Ensuite, utilisez cet index pour obtenir votre position de recherche. Le processus de création du fichier d'index nécessite beaucoup de ressources. Chaque fois que vous ajoutez une nouvelle ligne au fichier, vous devez mettre à jour l'index. La maintenance devient donc un problème non trivial.

1
RB Davidson

Essayé et testé. C'est aussi simple que suit:

string line = File.ReadLines(filePath).ElementAt(actualLineNumber - 1);

Tant que vous avez un fichier texte, cela devrait fonctionner… .. Plus tard, en fonction des données que vous comptez lire, vous pouvez lancer la chaîne en conséquence et l'utiliser.

0
Karan Randhawa

Une variation. Produit une erreur si le numéro de ligne est supérieur au nombre de lignes.

string GetLine(string fileName, int lineNum)
{
    using (StreamReader sr = new StreamReader(fileName))
    {
        string line;
        int count = 1;
        while ((line = sr.ReadLine()) != null)
        {
            if(count == lineNum)
            {
                return line;
            }
            count++;
        }
    }
    return "line number is bigger than number of lines";  
}
0
paparazzo

Bien que vous ne puissiez pas rechercher directement une nième ligne dans un fichier non symétrique sans lire les données qu'il contient (car vous devez compter le nombre de lignes que vous avez progressées dans le fichier), vous pouvez compter les sauts de ligne jusqu'à ce que vous accédiez au fichier. ligne que vous voulez qui prend le moins de mémoire et a probablement les meilleures performances.

Cela économisera davantage en mémoire que tout lire dans un tableau, étant donné qu'il ne sera lu que dans le fichier jusqu'à ce qu'il atteigne la fin du fichier ou le numéro de la ligne (selon la première éventualité). Il est loin d'être parfait, mais conviendra probablement à vos besoins:

string line15 = ReadLine(@"C:\File.csv", 15);

public string ReadLine(string FilePath, int LineNumber){
    string result = "";
    try{
    if( File.Exists(FilePath) ){
        using (StreamReader _StreamReader = new StreamReader(FilePath)){
        for (int a = 0; a < LineNumber; a++) {
            result = _StreamReader.ReadLine();
        }
        }
    }
    }catch{}
    return result;
}
0
Dave

Si votre fichier contient des lignes de différentes longueurs et que vous devez les lire souvent et le lire rapidement, vous pouvez en créer un index en le lisant une fois, en enregistrant la position de chaque nouvelle ligne, puis en lisant une ligne. , il vous suffit de rechercher la position de la ligne dans votre index, d'y chercher et de lire la ligne.

Si vous ajoutez de nouvelles lignes au fichier, vous pouvez simplement ajouter un index de nouvelles lignes sans qu'il soit nécessaire de tout réindexer. Cependant, si votre fichier change quelque part dans une ligne que vous avez déjà indexée, vous devez le réindexer. 

0
user175779

Vous pouvez lire ligne par ligne pour ne pas avoir à lire le tout en même temps

int i=0
while(!stream.eof() && i!=lineNum)
    stream.readLine()
    i++
line = stream.readLine()
0
Samuel