[C#]Problème avec la méthode Seek sur un FileStream

Bonjour,

J’ai un soucis et j’ai beau chercher, je ne vois pas d’où vient le problème.

Je cherche à récupérer les 128 derniers octets d’un fichier. Pour cela je me place sur le 128ème octet de mon fichier en partant par la fin avec la méthode Seek, mais au final je ne récupère qu’un buffer vide (de dimension 0).
Voilà mon code :

FileStream fs= new FileStream(Path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite ); BinaryReader br = new BinaryReader(fs); fs.Seek(128, SeekOrigin.End); byte[] buf1 = new byte[128]; buf1 = br.ReadBytes(buf1.Length);

Je n’ai peut être pas bien saisi le fonctionnement de cette fonction.

Merci de votre aide.

Je cite :

[code]Syntaxe
C#public override long Seek (
long offset,
SeekOrigin origin
)

Paramètres
offset
Point par rapport au origin à partir duquel la recherche doit commencer.

origin
Spécifie le début, la fin ou la position actuelle en tant que point de référence pour origin, à l’aide d’une valeur du type SeekOrigin.

Valeur de retour
Nouvelle position dans le flux.[/code]

Autrement dit, tu tente actuellement de lire les 128 octets qui suivent la fin de ton fichier.

Essaye plutot avec

ne pas verifier les valeurs de retour, c est mal

rhoo le boulet que je suis…

Je pensais que le pointeur se mettait à la 128ème position mais dans l’autre sens. Merci bien Bishop

Non relevant ici, cher ami.
En C/C++, ou la valeur de retour indique l’éventuelle erreur, il est vrai qu’il est indiqué de verifier. En C# on à nos amies les exceptions.

[quote=“Tzim, post:5, topic: 31652”]Non relevant ici, cher ami.
En C/C++, ou la valeur de retour indique l’éventuelle erreur, il est vrai qu’il est indiqué de verifier. En C# on à nos amies les exceptions.[/quote]
Ceci dit, ca m’a surpris de constater que le Seek dépasse allégrement la fin du fichier et lit quand meme sans lever d’exception.

Donc a priori, pas d’exception si ton fichier est ouvert en RW.

Le ReadBytes doit renvoyer un byte de longueur nulle.
A noter qu’il y’a confusion dans l’utilisation de Readbytes : ReadBytes renvoit un nouveau tableau, il n’est pas nécessaire de lui allouer un buffer au préalable. Pour lire dans un buffer, il faut utiliser Read(byte, int, int).

Le code adéquoit :

using (FileStream fs= new FileStream(Path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite )) { using (BinaryReader br = new BinaryReader(fs)) { fs.Seek(-128, SeekOrigin.End); byte[] buf1 = br.ReadBytes(128); } }

Oui… SVP… disposez vos objets IDisposable ou faites un using (ca qui revient au meme).

Bon je pose ma question de gros naze en C#. Ca fait quoi exactement using ? Ca indique quand est-ce que le programme peut virer la ressource?

Dans ce cas tu te retrouves pas tres vite avec 76 indentations ?

(j’avais prevenu)

C’est que pour les objets IDisposable. Donc non pas 76 indentations, et c’est en gros equivalent a

MachinChoseDisposable machinChose; try { ... } finally { machinChose.Dispose(); }

Enfin tu te retrouves avec 76 indentations sur tu fais 76 “using” imbriqués…
(mais tu t’en fous, tu les vois pas les indentations)

Et puis pour déclarer plusieurs “using” d’un coup, pas besoin d’imbriquer… on peut faire:

using(Pouet monPouet = new Pouet()) using(Tadah unTadah = new Tadah()) using(Ploutch ohBahDisDoncUnPloutchCaAlors = new Ploutch()) { // pouet, tadah, ploutch }

L’interet c’est d’etre sur que les objets sont bien disposés au moment ou on a fini avec eux, et de pas attendre le passage du GC ?

Il me semble. (Question suivante: quel est l’interet du GC qui est censé disposer les objets quand on s’en sert plus ? (ou plutot quand la ram est pleine))

Rhaa … B)

Faut pas confondre.
Le GC libère les ressources managées. Il passe par là et termine l’existance des objets managés qui n’ont plus lieu d’être.

La méthode Dispose à une autre utilité : elle libère les ressources (natives ou non) planquées derrière l’objet en question. Ici, pour le FileStream, c’est un Handle natif sur le fichier ouvert : Dispose permet de fermer le fichier et de libérer le Handle sans attendre que le GC passe par là (gardant un fichier bloqué par le programme), ce qui n’est pas contrôlable. Dispose ne va pas terminer pour autant la vie de l’objet FileStream.

[quote=“Tzim, post:14, topic: 31652”]Rhaa … B)

Faut pas confondre.
Le GC libère les ressources managées. Il passe par là et termine l’existance des objets managés qui n’ont plus lieu d’être.

La méthode Dispose à une autre utilité : elle libère les ressources (natives ou non) planquées derrière l’objet en question. Ici, pour le FileStream, c’est un Handle natif sur le fichier ouvert : Dispose permet de fermer le fichier et de libérer le Handle sans attendre que le GC passe par là (gardant un fichier bloqué par le programme), ce qui n’est pas contrôlable. Dispose ne va pas terminer pour autant la vie de l’objet FileStream.[/quote]

Mais euh… Si tu ferme bien ce genre de choses à la main ? J’veux dire, si pour chaque .Open() que t’a (que ca soit un FileStream, Un SqlDataReader, ou n’importe quoi qui garde qque chose d’ouvert qque part), tu fait bien un .Close(), est-ce que ca vaux quand meme le coup de faire un .Dispose() ?

[quote=“Tzim, post:5, topic: 31652”]Non relevant ici, cher ami.
En C/C++, ou la valeur de retour indique l’éventuelle erreur, il est vrai qu’il est indiqué de verifier. En C# on à nos amies les exceptions.[/quote]
c’est pas tout a fait ce que je voulais dire, en regardant la valeur de retour au debug, il aurait pu voir qu elle etait de plus en plus grande, et le mettre sur la piste du seek dans le mauvais sens.

exception ou pas, si une fonction prend la peine de renvoyer une valeur, c est pas juste pour faire joli.

C’est pas une raison. Si l’objet est IDisposable, il doit etre disposé explicitement, c’est tout B)

Il se peut que le systeme soit assez malin pour essayer de sauver les meubles en nettoyant dans le finalizer (catastrophique niveau perfs) ou qu’il laisse carrement fuir des ressources natives (le finalizer tourne dans un autre thread, parfois c’est impossible de nottoyer correctement de puis un autre thread), il se peut meme que tu ais fais le menage par d’autre methodes, mais faut appeller .Dispose().

Chef ! Oui, Chef ! B)

Haaaan ok. Faudrait que ca soit écrit comme ca sur MSDN en fait, pour être plus clair, parce que moi je voyais ca comme un « bonus » que tu peut appeler si a un moment t’a besoin d’être sur et certain qu’il est bien disposé. Tiens d’ailleurs question, est-ce que le Code Analyser repere ce genre de trucs ? ou y a un moyen simple (plutot que de passer ses nuits sur MSDN) pour trouver qui est Disposable ? (a part l’intellisense). Par exemple, j’avais jamais pensé que Pen puisse en être un.

Fxcop les repere a priori oui.