Récupérer la position de début et fin de string dans un fichier c#

Karibot Messages postés 89 Date d'inscription mardi 19 janvier 2010 Statut Membre Dernière intervention 21 juin 2016 - 28 oct. 2011 à 19:09
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 - 18 nov. 2011 à 08:54
Bonjour,
je cherche à indexer un gros fichier de données qui contient des blocs identiques de 4 lignes chacun. voici la structure de mon fichier:
item->velue
date->value
desc->value

ce que je souhaire faire c'est créer un index (dictionnary<string, string>) du couple item -> desc, sauf que "desc" est une une grande chaine de caractètres, très longues... donc prend de la memoire quand je la charge via des regex (outofmemory). oui parce qu'au début, je récupérais les elements de mon index grace à des regex et je stockais dans mon dico les valeur de item->desc...

la ce que j'ai essayé de faire c'est d'au lieu de chercher à stocker toute la chaine, je vais juste stocker les positions de début et de fin du "desc". donc j'aimerai avoir au final dans mon dico un couple item->pos_debut;pos_fin, sauf que je n'y arrive pas, cela me sort un truc bizarre!
je vous laisse mon code, et espère que quelqu'un puisse m'éclairer sur le sujet.
            Dictionary<string, string> Index = new Dictionary<string, string>();
            oRd = new StreamReader(file);
            string l;
            string item = string.Empty;
            long pos_debut = 0;
            long pos_fin = 0;
            while ((l = oRd.ReadLine()) != null)
            {
                if (l.StartsWith("item"))
                    item = l.Split('\t')[1];
                else if (l.StartsWith("date"))
                {
                    //je suppose que le pointeur et au bout de la ligne donc commence le début de la ligne suivante
                    pos_debut = oRd.BaseStream.Position;
                }
                else if (l.StartsWith("desc"))
                    pos_fin = oRd.BaseStream.Position;
                else
                    continue;

                if (!string.IsNullOrEmpty(item) && pos_debut > 0 && pos_fin > 0)
                {
                    if (!Index.ContainsKey(item))
                        Index.Add(item, pos_debut+";"+pos_fin);
                    else
                        continue;

                    item = string.Empty;
                    pos_debut = 0;
                    pos_fin = 0;
                }
            }


merci pour vos réponses!

7 réponses

Whismeril Messages postés 19035 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 1 mai 2024 656
28 oct. 2011 à 21:11
Bonsoir,

peux tu donner quelques lignes d'exemple de ton fichier.
Quand je teste ton code avec des lignes que j'ai imaginé, BaseStream.Position me retourne toujours la même valeur.

D'autre part, le dictionnaire ne me parait pas la meilleure solution,
puisque tu cherches à enregistrer 3 paramètres.

A ta place je créerai une classe avec Item, Debut et Fin et je stockerai les occurrences dans une List<T>.



Whismeril
0
Karibot Messages postés 89 Date d'inscription mardi 19 janvier 2010 Statut Membre Dernière intervention 21 juin 2016 2
29 oct. 2011 à 11:02
ben le fichier est comme je l'ai décrit plus haut voici un exemple:
item->dvd
date->12092011
desc->GFT65REIJFU876RYT6YEBFUD9875URJE0PMSLKF,FJU54GGDTEHDJJDKFSMXW01H13N8...

les "->" = tabulation

merci pour le conseil concernant la classe, je vais certainement le suivre, mais cela ne régle pas mon problème de positions

merci pour ta réponse!
0
Whismeril Messages postés 19035 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 1 mai 2024 656
29 oct. 2011 à 11:55
J'ai fait 3 lignes de ce format (enfin presque pour la date j'avais mis 12/09/2011), et la position retournée à chaque BaseStream.Position est la même, et est égale au nombre de caractères de mon fichier test.
Je ne trouve pas de fonction donnant la position de la ligne dans le flux, alors je te propose un truc dans ce style:

            while ((l = oRd.ReadLine()) != null)
            {
                l2 = oRd.ReadLine();//ligne date
                l3 = oRd.ReadLine();// ligne desc
                pos_debut = l.Length+ l2.Length;
                pos_fin = pos_debut + l3.Length;

                MaClasse MaClasse = new MaClasse(l.Split('\t')[1], pos_debut, pos_fin);
                //etc....

            }


Whismeril
0
Karibot Messages postés 89 Date d'inscription mardi 19 janvier 2010 Statut Membre Dernière intervention 21 juin 2016 2
30 oct. 2011 à 09:52
hello,
je suis en train de tester ta méthode avec pas mal de modifications :)

je récupére bien mon tableau item->positions, et la j'essaye de lire dans le fichier suivant les positions. donc je fais:
int count = pos_fin - pos_debut;
char[] buffer = new char[count];
oRd.ReadBlock(buffer, pos_debut, count);


mais il bute sur le readblock avec cette erreur:
"l'offset et la longueur étaient hors limites pour ce tableau ou bien le nombre superieur au nombre d'éléments de l'index à la fin de la collection source"

j'ai essayer d'augmenter la taille du buffer pour qu'il soit supérieur au count mais j'ai toujours la meme erreur...

une idée?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Whismeril Messages postés 19035 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 1 mai 2024 656
30 oct. 2011 à 12:02
Bonjour,

je contaste la même chose.
Ca ne marche qu'avec

oRd.ReadBlock(buffer, 0, count);


Je ne comprends pas pourquoi.

Je ne vois qu'une boucle pour lire n blocks jusqu'à arriver à la bonne position.
Pas glop.
Je n'ai pas la solution désolé.

Whismeril
0
cgandco Messages postés 219 Date d'inscription mercredi 26 octobre 2011 Statut Membre Dernière intervention 22 juin 2017 9
17 nov. 2011 à 17:46
Bonjour à tous,

Mille excuses pour le retard.

Ceci ne peut-il pas provenir du fait que "readline" n'enregistre (a mon avis) pas les [CR][LF] etc... alors que pour "readblock" ils sont stockés car c'est un tableau de char.

Un décalage doit donc se produire à cet endroit.

il faut peut être calculer pos_debut et pos_fin en ajoutant le nombre de caractères non stocké par "readline" avant de les mettre dans le dictionnaire ou la list.

C'est simplement une idée sans avoir testé.

Bonne soirée
0
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
18 nov. 2011 à 08:54
Salut,

quelle taille a ton fichier de données ?
j'ai du mal à imaginer une OutOfMermoryException hors fuite mémoire (ou alors avec un fichier de presque 2Go)
0
Rejoignez-nous