Lire x octets (x variable) dans un gros fichier à une position de pointeur y [Résolu]

Signaler
-
 Utilisateur anonyme -
Bonjour j'aimerai savoir quelle est la différence entre le mode d'accés aux fichiers par 'fso' (OpenAsTextStream etc) et 'OPEN GET INPUT ect' en terme de performance.

J'essai de récuperer dans un fichier de 1go 10 caractères se trouvant à '500mo'. J'utilise donc pour ca ce code :

Dim fs, a, b, c As String
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.GetFile("grosfichier.dat")
Set b = a.OpenAsTextStream(1)
b.Skip (500000000)
c = b.Read(10)

Le problème c'est que contrairement à 'OPEN GET...' il lit la partie [0mo-500mo] du fichier avant de me donner le résultat et ça prend donc un temps fou (on voit dans le gestionnaire de tâches que 500mo on été lus).

J'ai bien tenté de passer par 'OPEN, GET' mais on doit passer par des strings de tailles constantes (x as string * 5) pour récupérer x octets or dans mon programme on peut récupérer 20 comme 500 octets.

J'ai lu plusieurs tutoriels (dont l'excellent de celiphane) mais je trouve toujours pas de réponse à ma question...

14 réponses

Messages postés
1488
Date d'inscription
mercredi 5 février 2003
Statut
Membre
Dernière intervention
3 décembre 2007
22
Non, on n'est pas obligé de passer par des string fix !!!

Dim varTxt As String
Dim varCanal As Integer
...
varCanal = FreeFile
Open fichier For Binary As varCanal
varTxt = Space(NombreDeOctets)
Get #varCanal, octetDebut, varTxt
Close varCanal

et le tour est joué normalement !!!

Dit moi si ça fonctionn pour ton truc ?

Enjoy
<hr size="2" width="100%">
( Si une réponse vous convient, cliquez sur le bouton "Réponse acceptée". )
3
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 114 internautes nous ont dit merci ce mois-ci

Messages postés
1488
Date d'inscription
mercredi 5 février 2003
Statut
Membre
Dernière intervention
3 décembre 2007
22
Ben fait une string de 100 octets non !!!

Enjoy

<hr size="2" width="100%">
( Si une réponse vous convient, cliquez sur le bouton "Réponse acceptée". )

heu non j'ai dit 100 ca peut etre 500000 la n'est pas le probleme ni la question, ca doit être variable.

Ca marche niquel merci beaucoup ;)

Derniere question quelle est la différence entre l'accès par FSO et par ce moyen (open, get, input...). Pourquoi ces deux moyens?
Messages postés
3140
Date d'inscription
vendredi 14 mai 2004
Statut
Membre
Dernière intervention
11 mars 2019
25
pour faire simple, oublie fso
tu peux lire aussi dans un tableau d'octets



varCanal = FreeFile


Open fichier For Binary As varCanal
Redim B(
NombreDeOctets-1
) As Byte
Get #varCanal, octetDebut, B
Close varCanal




Daniel

ok thx
Messages postés
1488
Date d'inscription
mercredi 5 février 2003
Statut
Membre
Dernière intervention
3 décembre 2007
22
Dit Dan, je voulais te demander... Quel est l'intéret d'un tel tableau face à une variable ???
Est-ce que l'accès est plus rapide qu'avec Mid$ ?
Normalement, il prends plus de place en mémoire non !?
Est-ce plus rapide pour récupérer les données ???
Je me suis toujours demandé l'utilité des tableaux de bits en la matière!

Kroman, pour répondre a ta question :
Le FSO est un objet VBA (livré avec Excel & cie) alors que Open est une instruction (qui date des toutes premières versions du BASIC!!!). Le FSO ne permet d'ailleurs pas de faire la même chose que Open !!! Le FSO est surtout là pour simplifier les manipulations au niveau du disque (existance des dossiers, présence d'un fichier, ...). Il existe des instruction/fonctions internes au VB qui permettent aussi la manipulation sur le disque (création d'un dossier, ...) mais le FSO permet d'éviter d'avoir à coder plein de tests... Cependant, son utilisation est controversée... Perso, j'ai bien l'utiliser parce qu'il permet de gagner du temps de codage...

Est-ce que cela répond à ta question ???

Enjoy

<hr size="2" width="100%">
( Si une réponse vous convient, cliquez sur le bouton "Réponse acceptée". )
Messages postés
3140
Date d'inscription
vendredi 14 mai 2004
Statut
Membre
Dernière intervention
11 mars 2019
25
un Tableau de Byte c'est du numérique donc toujours plus rapide que des Strings,

ça ne prend qu'un octet par caractère pas plus, pas d'adresse, pas de
longueur de chaînes, et encore moins d'Unicode, donc ça prend au moins
2 fois moins de place qu'une chaîne correspondante.



si on veut ensuite accèder à chacun des caractères, c'est la solution
idéale, toutes les fonctions chaînes étant très gourmandes en temps.



fso peut faire beaucoup de choses certes, mais il le fait surtout très lentement,

toute solution qui évite fso lui est préférable.




Daniel
Messages postés
1488
Date d'inscription
mercredi 5 février 2003
Statut
Membre
Dernière intervention
3 décembre 2007
22
(cf. désolé pour la petite erreur bits/bytes !)

Hum... intéressant en effet!!! En effet... dit comme ça... Je sais pas pourquoi mais j'ai toujours eu l'impression que les tableaux prenaient plus de place en mémoire (peut-être parce que j'ai du lire un truc sur les tableaux de variant...).

Mais dit moi, qu'entands-tu pas "pas d'adressage" ???

Et es-tu vraiment certain qu'en Mid$ ce soit plus lent ??? (je te ferais confiance... j'irrais pas vérifier!)
Pi dit moi aussi au passage, MidB (j'ai toujours pas très bien compris... il traite les caractères uniquement sur 2 bytes ou uniquement sur 1 ???) ne pourrait-il pas fair l'affaire ici ?

Sinon, pour le FSO, on ne l'utilise jamais pour de grands traveaux et je trouve, perso, que sa "lenteur" n'est en rien un problème pour une utilisation "normale"... Enfin, on va pas relancer la polémique n'est-ce pas (cf. les nombreux posts sur le forum traitant de ce délicat sujet...).

Enjoy

<hr size="2" width="100%">
( Si une réponse vous convient, cliquez sur le bouton "Réponse acceptée". )
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
64
FSO à oublier dans la plupart des tâches....
les fonctions intrinsèques à VB sont de bonne facture....

les tableaux VB (qui sont en fait des SafeArray) ne consomme pas trop, le header doit faire 10 octets, a tout casser.... le reste, ce sont les données les unes a la suite des autres... avec le tableau de Byte, tu sais ou tu en est, et pour accéder a un caractère particulier, c'est la solution a favoriser

les chaines, en VB sont stockées en Unicode. MidB accède a chaque octet de la chaine (deux octets par caractères)

Renfield
Admin CodeS-SourceS - MVP Visual Basic
Messages postés
3140
Date d'inscription
vendredi 14 mai 2004
Statut
Membre
Dernière intervention
11 mars 2019
25
attend je reprends tout

les chaînes en Vb sont en BString, comme toutes les variables, elles
ont une adresse (que l'on obtient avec VarPtr) , mais pour les chaînes
c'est un pointeur qui pointe sur la vraie chaîne (adresse obtenue avec
StrPtr) 2 octets par caractères, 2 zéro à la fin, et la taille qui se
trouve devant sur 4 caractères, donc assez compliqué à gérer, quand la
chaîne n'est pas encore définie, le pointeur est à zéro, et quand on
affecte la chaîne, Vb doit trouver la place nécessaire et cela prend du
temps.

les autres variables ont leurs adresses définies au départ, la place est déjà réservée et c'est plus rapide.

les chaînes fixes ne sont pas en BString, elles ont déjà la place réservée, toujours en Unicode mais pas de zéro à la fin.
faut
se méfier de ce que fait Vb par derrière, il transforme les Unicodes en
non Unicode pour envoyer aux API's, il transforme les chaînes fixes en
chaîne BString pour être compatible avec les autres, etc...

Bref tout cela prend du temps, et les yeux fermés même sans tester, je
dirais que le type Byte même si c'est le plus lent des numériques, doit
toujours être plus rapide que les String.



j'ai pas encore utilisé MidB, faut voir ça:

Dim Str As String

Str = "ABCD"

MsgBox LenB(MidB(Str, 1, 1))

MsgBox LenB(Mid(Str, 1, 1))



une chaîne de 1 octet, je sais pas trop où je vais mettre ça ???

je viens de voir le Message de Renfied alors que j'ai pas encore envoyé
le mien, c'est vrai qu'on peut accéder au deuxième octet de l'Unicode:



MsgBox MidB(Str, 1, 1) donne "A"

MsgBox MidB(Str, 2, 1) donne rien

MsgBox TypeName(MidB(Str, 1, 1)) donne "String"

MsgBox Asc(MidB(Str, 1, 1)) se plante ???



Dim c As String

c = MidB(Str, 1, 1)

MsgBox LenB(c) 'un seul caractère ????

c = "A"

MsgBox LenB(c) 'pourtant une chaîne normale fait au moins 2




Daniel
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
64
d'ailleurs, concernant les API
VB travaille en Unicode, on l'a vu.
Il nous faut utiliser la version Ascii des API car win95/98 ne prenaient a l'epoque pas l'Unicode. (il existe un complément pour qu'ils le prenne en compte)
VB convertit en interne, nos chaines a chaque appel API, ce qui est lent, vous imaginez bien...

une parade existe pourtant, et je vous concocte depuis quelques semaines maintenant un petit quelque chose dont vous me direz des nouvelles, je pense....

Renfield
Admin CodeS-SourceS - MVP Visual Basic
Messages postés
1488
Date d'inscription
mercredi 5 février 2003
Statut
Membre
Dernière intervention
3 décembre 2007
22
Ben on attend ça avec impatience!!!

Bon, je ne suis toujours pas certain de bien maitrisé ce - pardonnez l'expression - "merdier" !!! Mais bon, dans l'ensemble, je crois avoir saisi... Enfin, vous verrez bien dans mes prochains posts (y'a en effet des chances que je vous repose la question )

Enjoy

<hr size="2" width="100%">
( Si une réponse vous convient, cliquez sur le bouton "Réponse acceptée". )

Oups j'avais pas vu vos réponses alors merci (avec un peu de retard désolé) aux participants

J'ai remplacé la gestion des fichiers de fso par les instructions OPEN/GET et c'est 2 fois plus rapide (je ne passe donc plus par fso que pour lister les fichiers / sous-dossiers d'un dossier).

Par contre le seul souci c'est qu'une fois un OPEN effectué en binary sur un fichier, celui ci n'est plus accesible par aucun autre programme tant que "close" n'a pas été appelé...