Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Des fois que vous auriez déjà eu ça : la lecture d'un gros fichier texte plante sur un manque de mémoire. Pourtant le fichier fait moins de 2 Go, qui est une limite possible pour les strings mais j'essaie de lire le fichier dans un blob avec FileReadEx() et il ne fait "que" 130 632 351 octets. C'est un fichier xml et mon PB est 11.5.1 build 4843
Le code est simplissime et le plantage est sur la ligne du FileReadEx():
string ls_file long ll_hfile blob lbl_bigfile ll_hfile = FileOpen( as_file, StreamMode! ) FileReadEx( ll_hfile, lbl_bigfile ) // <=== BOUM ! FileClose( ll_hfile ) return string( lbl_bigfile, GetBlobEncoding(lbl_bigfile) )
La fonction GetBlobEncoding() c'est un truc à moi qui retourne un type encoding (encodingAnsi!, encodingutf8!, ...) en fonction du contenu d'un blob, ça me permet de gérer moi même certains problèmes lié aux encodages.
Bon, je pense que la lecture de ce gros fichier pour finir dans une string n'est pas la meilleure solution avec PB et va peut-être se faire remanier. C'était pour gérer la validation xml par rapport à un schéma, et ça fonctionne sur d'autre fichiers plus petits.
Hors ligne
Salut, dans ton mailslot tu utilises une fonction externe :
Function boolean ofx_ReadFile ( ulong hFile , & ref string lpBuffer , & ulong nNumberOfBytesToRead , & ref ulong lpNumberOfBytesRead , & ulong lpOverlapped) library "kernel32.dll" alias for "ReadFile"
ça ne marche pas mieux ?
Hors ligne
Je ne me souvenais plus de ça...
Cool, j'ai au moins un lecteur de mes œuvres !
Je comptais chercher une solution sans devoir passer par l'api windows, mais je vais quand même essayer.
Hors ligne
Bonjour,
Pourquoi ne pas tenter une boucle de fileRead jusqu'a ce que la fonction te retourne 0.
Si je dis pas de connerie (ça fait un moment que j'ai pas fait de lecture de fichier) le pointeur devrait bouger au fur et à mesure des fileread si ton fichier est ouvert en streamMode comme c'est le cas dans ton code (si c'est pas le cas faut jouer avec fileSeek).
Tu remplis au coup par coup par bloc de 32 765 bytes ta variable ls_file avec le résultat de ton file read.
string ls_file, ls_returnChars = "" long ll_hfile, ll_nbOfReturnChars = 0 ll_hfile = FileOpen( as_file, StreamMode! ) do ll_nbOfReturnChars = FileRead( ll_hfile, ls_returnChars ) if ll_nbOfReturnChars > 0 then ls_file = ls_file + ls_returnChars end if loop while ll_nbOfReturnChars > 0 FileClose( ll_hfile ) return ls_file
J'ai pas le temps de tester avec un fichier de ta volumétrie mais ça devrait passser je pense.
Dernière modification par Van (16-12-2015 13:57:55)
Hors ligne
J'ai tenté de remplacer la lecture par ceci :
- détermination de la taille du faichier
- allocation par un blob_alloc() des "fast funcs" qui n'oblige pas à bricoler en allouant une string avec space() pour pouvoir écrire dans le buffer depuis l'API
- lecture du fichier avec un ReadFile système comme suggéré par Erasorz
Résultat :
il y a toujours un bug de plus : ça fonctionne très bien avec le gros xml, mais ça plante alors dans ma fonction GetBlobEncoding() où un if Byte(blobmid(ab_data,1,1)) = 255 (en fait elle ne "plante" pas vraiment, elle ne fait juste plus rien, plus d'activité CPU et ne rend pas la main) alors que PB utilise déjà ~380 Mo de RAM.
constant ulong GENERIC_READ = 2147483648 //0x80000000 constant ulong FILE_SHARE_READ = 1 constant ulong OPEN_EXISTING = 3 constant ulong FILE_ATTRIBUTE_NORMAL = 128 blob btest boolean lb_read ulong lul_size, lul_read, lul_hfile string as_file = 'C:\temp\edifact\TPTASS_L0_201512_P000778899_ASS0012345_20151218_001.xml' lul_size = FileLength(as_file) btest = blob_alloc(lul_size) lul_hfile = CreateFile (as_file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) lb_read = readfile(lul_hfile, btest, lul_size, lul_read /*bytes*/, 0) closehandle(lul_hfile) messagebox("blob", len(btest))
Hors ligne
seki a écrit:
Je comptais chercher une solution sans devoir passer par l'api windows, mais je vais quand même essayer.
La solution qui fonctionne sans planter, c'est de sous-traiter la validation à un bout de Perl et LibXML : on lui passe le chemin vers le fichier et le schéma, et on récupère la liste des erreurs éventuelles.
Hors ligne
Les applications 32 bits sont limitées à 2GB de mémoire, mais via un petit outils on peut aller jusqu'a 3GB , voir ici https://scn.sap.com/thread/3425191
Peut être que cela résoudra votre problème de mémoire.
Hors ligne
J'ai découvert cet outil il y a peu, mais le problème n'est pas là : ~380 Mo (application) + ~120 Mo (fichier qu'on essaie de charger) ça reste bien inférieur à 2 Go.
Pas grave je m'en suis tiré avec du Perl
Hors ligne
Et je n'arrive pas à ajouter le [RESOLU], en fait je n'arrive plus à modifier de message pour cause HTTP_REFFERER incorrect
Hors ligne