Input past end bizarre

Signaler
Messages postés
832
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
24 octobre 2020
-
Messages postés
832
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
24 octobre 2020
-
Bonjour,
6560    FileNum = FreeFile: Open CheatFileName For Binary As #FileNum
6570    Do While Seek(FileNum) < LOF(FileNum)
6580        Line Input #FileNum, Record
6590        ...
6600    Loop
6610    Close #FileNum

J'ai une erreur 62 Input past end of file sur la ligne 6580.
Comment est-ce possible vu le test de la ligne précédente ?

11 réponses

Messages postés
191
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
21 octobre 2020
5
Normal Hervé, tu es en "Binary" et le" (line) Input #" s'utilise généralement en accès séquentiel "for INPUT as"...

Le "binary" a un LOF flottant et s'utilise avec des variables ou GET#,
Donc, pour le texte : "For Input as" ou "For output as"
Pour les blocs bytes ou les variables: "For Binary as"
Messages postés
832
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
24 octobre 2020
2
Bonjour,
comme d'habitude sur ce site je ne reçois pas de notification quand on répond, je viens de voir ton message.

Tu as bien sur raison sur le principe.
Cependant j'ouvre le fichier en binaire car, même s'il est construit en lignes, il contient des caractères encryptés donc binaires, il est construit dans un autre programme comme ceci
Open ParFileName For Output As #1
For i = 0 To Records.ListCount - 1
    Print #1, Encrypt(Records.List(i))
Next i
Close #1
Fonction de cryptage, "Allowed" étant la clé
Function Encrypt(UnCrypted As String) As String
Encrypt = ""
For i = 1 To Len(UnCrypted)
    Encrypt = Encrypt & Chr((Asc(Mid(UnCrypted, i, 1)) + (Asc(Mid(Allowed, (i Mod Len(Allowed)) + 1, 1)))) Mod 256)
Next
End Function

Si je l'ouvre en Input alors (line) Input ne donne parfois pas une ligne complète.
Ce que je ne comprends pas est que la plupart du temps sur des dizaines de milliers de cas l'ouvrir en binaire puis lire ligne par ligne fonctionne très bien, j'ai eu cette erreur une seule fois.
Messages postés
191
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
21 octobre 2020
5
Salut Hervé,
Oui, je voie ton problème.
Donc, à partir d'un fichier binaire, tu veux faire l'extraction de textes ASCII.

Le problème avec ta méthode, c'est que tu utilises 'Line Input" qui va chercher les Cr et les Lf de retours chariot.

Mais cette fonction considère que tout caractère non affichable est un ordre de retour chariot.

Comme sur certains formats, le binaire "h00" est utilisé comme balise d'échappement et de validation de valeurs chaîne, le Line input peut fonctionner de manière erratique.

Comme le contenu est encrypté cette valeur peut être présente dans la chaîne...
Tout comme les Cr et Lf de retour chariot...

Il faut soit créer un objet vide et charger le fichier avec ses caractéristiques inclues dans la "variable objet", soit ouvrir le fichier en binaire, et effectuer toi même la recherche sur des binaires caractéristique d'échappement, dans le fichier (CrLf, h00, h10...) ou sur les headers de données récurrentes.

L'ouverture du fichier en tant qu'objet est plus sûr et plus simple...
Tu charges ton fichier en entier, mais au moins, tu peux scanner l'objet sans avoir de valeurs texte corrompues.

Un truc du genre:
Dim Rec as new Records : ' Nom du type d'objet compatible.

FileNum = FreeFile 
Open CheatFileName For Binary As #FileNum
Get #FileNum, Rec()
Close #FileNum

Puis tu utilises les enfants de cet objet pour la récupération du texte...
Normalement, la structure des enregistrements sera chargée et compatible.
Messages postés
832
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
24 octobre 2020
2
Bonjour,
Est-ce que je comprends bien que tu veux mettre tout le fichier dans un array ?
Problème : sur
Get #FileNum, Rec()
j'ai "expected list separator" !

Bon j'ai trouvé, il faut 2 virgules
Get #FileNum, , Rec()


Mais ensuite at run time, sur le second Dim j'ai "User defined type not defined".
Dim Record As String
Dim CheatArray As New Records: Record

En fait je ne comprends pas ce que tu veux faire donc je ne sais pas ce que je fais.
Messages postés
191
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
21 octobre 2020
5
Salut Hervé,
Pas de panique, il faut que tu connaisses la structure du fichier et son organisation.
Dans un de tes message tu cites un fichier Accès, donc, as-tu une base de donnée et connais tu les variables compilées dans ce fichier ?

Donc, soit c'est un fichier brute sans infos de structure, soit c'est un fichier regroupant toutes les variables dans un header (la taille des variables, le type, si c'est une variable margée ou des valeurs numériques)...

Dans le premier cas, il faut scanner les valeurs octet par octet et dans l'autre, il faut charger la structure et réinitialiser les variables selon les données incluses dan la fichier lui même.

Pour avoir une idée de la structure du fichier, poste une copie d'écran du début d'un fichier à scanner... ça va être plus simple pour te répondre.
Messages postés
832
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
24 octobre 2020
2
Bonjour,
Où as-tu vu que je cite un fichier Accès ?
Il s'agit d'un fichier texte créé à l'aide de
Print
comme expliqué ici https://codes-sources.commentcamarche.net/forum/affich-10102999-input-past-end-bizarre#2
Je lis ensuite ce fichier à l'aide de
Line Input #FileNum, Record
ce qui a toujours très bien fonctionné sauf une seule fois où j'ai eu "Input past end", je me demandais pourquoi.
Messages postés
191
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
21 octobre 2020
5
Salut,

Bon, à priori, tu sauvegardes des données binaires (encryptées) sous un format texte.
Comme expliqué précédemment, ce type d'enregistrement ne convient pas, car les données envoyées sont constitués d'octets pouvant être mal interprétés.
Imagine que tu sauvegardes une chaîne binaire avec pour contenu chr(&h10)+chr(&h10)+chr(&h0A)+chr(&h0A)...
Ton enregistrement contient une seule chaîne... mais Line input y verra quatre lignes vides.
donc, si tu demandes une line, il sera décalé de quatre lignes.
Dans tous ça, tu as d'autres caractères de control pouvant désorganiser cette fonction.
"Line input" est a réserver au texte purs et non aux chaînes de données binaires.
Messages postés
832
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
24 octobre 2020
2
Bonjour,
En effet, le cryptage peut donner des caractères inférieurs à #20.
Il est bizarre que cette erreur ne soit survenue qu'une seule fois.

Comment dois-je faire pour enregistrer ces données dans un fichier record par record
et ensuite les lire record par record sachant que les records sont de longueur variable ?
Messages postés
191
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
21 octobre 2020
5
Salut,
Je te propose donc de sauver tes données en hexadécimal pour que ces chaînes ne possèdent pas de caractères spéciaux.
"10311A2B" peut être disséqué par groupe de deux et donnera ta chaîne binaire encryptés.
Avec un MID et HEX(), la récupération sera simple.
Amuse-toi bien.
Messages postés
2249
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
28 octobre 2020
115
bonjour
Dans ton code que voici
Open ParFileName For Output As #1
For i = 0 To Records.ListCount - 1
    Print #1, Encrypt(Records.List(i))
Next i
Close #1


Tu crées un fichier et tu cryptes chaque ligne pour ensuite la stocker dans le fichier .
L'idéal serait de stocker dans le fichier chaque ligne sans les crypter et une fois le fichier rempli entièrement tu cryptes ce même fichier .
Pour lire le fichier tu le décryptes d'abord et ensuite tu peux lire les lignes de ton fichier .
Ainsi plus de problème avec les octets cryptés

Messages postés
832
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
24 octobre 2020
2
Bonjour,
Merci à tous pour vos réponses qui sont autant de solutions, j'en ai trouvé une autre :
chaque caractère est crypté comme ceci, Key étant la clé d'encryptage
Chr((Asc(Mid(UnCrypt, i, 1)) + (Asc(Mid(Key, (i Mod Len(Key)) + 1, 1)))) Mod 256)

j'ajoute au Nème caractère le Nème caractère de la clé puis j'en prends le modulo 256
le résultat peut donc prendre n'importe quelle valeur entre #00 et #FF.
Pour éviter les caractères entre #00 et €1F je vais modifier comme ceci
Chr((Asc(Mid(UnCrypt, i, 1)) + (Asc(Mid(Key, (i Mod Len(Key)) + 1, 1)))) Mod 224 + 32)

j'ajoute au Nème caractère le Nème caractère de la clé puis j'en prends le modulo 224
le résultat peut donc prendre n'importe quelle valeur entre #00 et #DF
puis j'ajoute 32 pour que la valeur soit comprise entre #20 et #FF.

Ceci me semble plus simple parce que je ne dois modifier que les fonctions de cryptage et de décryptage, alors que les autres solutions impliquent de modifier les 7 endroits où j'utilise un fichier crypté.
Encore merci quand même pour m'avoir fait comprendre où était le problème.