IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

[Win32] Problème lecture de fichier


Sujet :

C++

  1. #1
    Membre actif
    Avatar de Blo0d4x3
    Inscrit en
    Octobre 2003
    Messages
    583
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 583
    Points : 265
    Points
    265
    Par défaut [Win32] Problème lecture de fichier
    Bonjour,

    Petit problème pour lire une image png, Le code suivant marche bien quand je veux lire un bête fichier txt, mais pas une imag png, Dans mon buffer szBuf, je me retrouve qu'avec les 4 premiers octets du fichier, dans le fichier lu, le cinquième est un 00. Je pense que c'est lui qui fait bugger mon code.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    fileHandle = CreateFile(ImagePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     
    	if (fileHandle == INVALID_HANDLE_VALUE)
    	{
    		printf("Error CreateFile: %d\n", GetLastError());
    	}
     
    	DWORD dwFileSize = GetFileSize(fileHandle, NULL);
     
    	if (dwFileSize <= 0)
    	{
    		printf("Error filesize\n");
    	}
    	else
    	{
    		printf("Filesize: %d\n", dwFileSize);
     
    		char *szBuf = new char[dwFileSize + 1];
    		DWORD dwBytes = 0;
     
    		if (!ReadFile(fileHandle, szBuf, dwFileSize, &dwBytes, NULL))
    		{
    			printf("Readfile failed: %d\n", GetLastError());
    		}
    		else
    		{
    			printf("sizeof read: %d, nbtoread: %d\n", sizeof(szBuf) / sizeof(szBuf[0]), dwFileSize);
     
    			printf("file: %s\n", szBuf);
    			string filecontent = string(szBuf);
    			printf("filecontent %s\n", filecontent);
    Si vous avez une solution.

    Merci

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Salut,

    pourquoi penses-tu avoir un pb ?
    Parce que printf("file: %s\n", szBuf); ou printf("filecontent %s\n", filecontent); affichent que qqs caractères uniquement ?
    Si oui, c'est normal, c'est un fichier binaire, donc des \0 y'en a un peu partout qui trainent. Vouloir afficher un fichier binaire dans la console, et comme du texte, c'est
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Attention, je ne vois rien dans ton code qui permette de s'assurer que szBuf[dwFileSize] est bien un caractère nul.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre actif
    Avatar de Blo0d4x3
    Inscrit en
    Octobre 2003
    Messages
    583
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 583
    Points : 265
    Points
    265
    Par défaut
    @bouzk printé un binaire c'est WTF je suis d'accord, c'était juste un test pour "voir" combien de caractères chelou j'aurai. et forcément il s'arrête à 4. Le sizeof read me renvoit 4...
    @Médinoc Le cinquième est un null

    Comment je peux m'assurer que le fichier est complet dans szBuff? Dans le debugger de VC je ne peux pas voir le contenu de la variable. :\

    EDIT:

    J'ai trouvé d'ou venait mon problème... après avoir lu l'image je l'encode en base64

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    string Base64Encode(const char *s)
    {
    	DWORD dwSize = 0;
    	char szData[1024] = { 0 };
     
    	CryptBinaryToStringA((BYTE*)s, strlen(s), CRYPT_STRING_BASE64, nullptr, &dwSize);
    	if (dwSize < 1024) CryptBinaryToStringA((BYTE*)s, strlen(s), CRYPT_STRING_BASE64, szData, &dwSize);
     
    	return szData;
    }
    Et ca doit être dans cette fontion que ca déconne avec l'histoire du null byte.

  5. #5
    Membre actif
    Avatar de Blo0d4x3
    Inscrit en
    Octobre 2003
    Messages
    583
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 583
    Points : 265
    Points
    265
    Par défaut
    Je cerne mieux le problème, à la lecture, j'ia pas de problème, le fichier est bien complet, c'est juste que convertis le szBuff en string, donc forcement ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    datas = datas + "&s=" + string(szBuf);
    Une bonne solution serait de convertir szBuff en quelle type avant de l'avoir en string?

  6. #6
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Tout dépend ce que tu veux en faire derrière. Mais std::string ne peut pas contenir de \0. Si tu veux un conteneur qui contienne des \0, std::vector<char> peut être une solution.

    Dans tous les cas, la signature de ta méthode base64encode n’est pas adaptée :*elle prend un char const*, donc une chaîne terminée par un \0. Or, tu as des \0 au milieu de ta valeur, que tu souhaites encoder en base64 (ça ne pose pas de problème particulier). Il faut donc que tu lui rajoutes un paramètre taille et modifie le corps en conséquence.

    Sinon, la remarque de Médinoc est toujours valide : ta chaîne n’est pas terminée par un \0. Sois-en conscient quand tu la manipules (ça n’est pas forcément un problème, mais ça demande de l’attention, c’est vite fait d’appeler une fonction qui s’attend à ce que la chaîne soit terminée par un \0, et là, c’est le drame).

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    En C, une fonction d'encodage Base64 prendrait en paramètres d'entrée un const unsigned char* (ou à la rigueur, un const void* qu'elle convertirait internement en ce type) et un size_t représentant la taille en bytes.

    En C++, vector<unsigned char> (en référence constante bien sûr) serait un type approprié, vu que je ne crois pas qu'il y ait de truc genre iterator<unsigned char> start, iterator<unsigned char> end (i.e., je n'ai pas l'impression qu'avec les itérateurs STL on puisse contraindre le type des objets itérés sans contraindre le type d'itérateur aussi... mais je peux me tromper, je connais très mal la STL)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre actif
    Avatar de Blo0d4x3
    Inscrit en
    Octobre 2003
    Messages
    583
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 583
    Points : 265
    Points
    265
    Par défaut
    ok.

    J'ai réussi à contourner mon problème en utilisant un LPSTR

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    LPSTR szBuf;
     
    ...
     
    DWORD dwFileSize = GetFileSize(fileHandle, NULL);
     
    szBuf = (LPSTR)LocalAlloc(LPTR, dwFileSize + 1);
     
    		if (!ReadFile(fileHandle, szBuf, dwFileSize, &dwBytes, NULL))
    		{
    			printf("Readfile failed: %d\n", GetLastError());
    		}
     
    datas = datas + "&s=" + (string)ToBase64(szBuf, dwFileSize + 1);
    Je l'encode avec une fonction ToBase64 trouvé sur le net..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    CStringA ToBase64(const void* bytes, int byteLength)
    {
    	ASSERT(0 != bytes);
     
    	CStringA base64;
    	int base64Length = Base64EncodeGetRequiredLength(byteLength);
     
    	VERIFY(Base64Encode(static_cast<const BYTE*>(bytes),
    		byteLength,
    		base64.GetBufferSetLength(base64Length),
    		&base64Length));
     
    	base64.ReleaseBufferSetLength(base64Length);
    	return base64;
    }
    Déjà j'ai plus de problème avec le null byte, mais le fichier base64 decodé est incomplet... J'ai essayer de caster le DWORD dwFileSize avec (int) mais ca ne change rien.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Blo0d4x3 Voir le message
    Je cerne mieux le problème, à la lecture, j'ia pas de problème, le fichier est bien complet, c'est juste que convertis le szBuff en string, donc forcement ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    datas = datas + "&s=" + string(szBuf);
    Une bonne solution serait de convertir szBuff en quelle type avant de l'avoir en string?
    std::string peut tout à fait convenir, à condition d'utiliser le bon constructeur. C'est identique à l'utilisation d'un vector<char> en pratique.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Sais-tu seulement ce qu'est un LPSTR?
    C'est toujours une chaîne de caractères, littéralement un typedef vers char *.

    Tu as exactement zéro raison d'utiliser un LPSTR comme pointeur vers un buffer contenant une suite arbitraire d'octets.

    PS: Tu ne nous avais pas dit que tu pouvais utiliser MFC ou ATL...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre actif
    Avatar de Blo0d4x3
    Inscrit en
    Octobre 2003
    Messages
    583
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 583
    Points : 265
    Points
    265
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Sais-tu seulement ce qu'est un LPSTR?
    C'est toujours une chaîne de caractères, littéralement un typedef vers char *.

    Tu as exactement zéro raison d'utiliser un LPSTR comme pointeur vers un buffer contenant une suite arbitraire d'octets.

    PS: Tu ne nous avais pas dit que tu pouvais utiliser MFC ou ATL...
    Ouais, j'avais remarqué après ...

    Pour les MFC ATL, je les utlisais pas au départ, puis en pensant que mon problème venait de mon ancienne fonction d'encodage en base64 j'y suis venu... reste à comprendre pourquoi le fichier décodé n'est pas le même ^^

    @Bousk je ne connais pas les vector<char>, je vais me renseigné dessus.

  12. #12
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    C’est à dire, incomplet ?

    Logiquement, quand tu décodes, il y a le même problème de caractères \0 : tu ne peux pas et ne dois pas traiter ton image comme une chaîne de caractère ! (une fois encodée en base64, en revanche, tu peux).

    Donc toutes les fonctions qui travaillent sur les chaînes terminées par des \0 (c’est normalement indiqué dans la doc) te sont interdites. Indice : si la signature d’une fonction contient char* mais pas de taille, elle t’es interdite. Te restent celles qui travaillent sur les pointeurs + taille si tu es en C, ou sur des types plus évolués si tu es en C++.

    C’est quoi la fonction base64decode que tu utilises ?

  13. #13
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 476
    Points
    11 476
    Billets dans le blog
    11
    Par défaut
    On aura beau me dire que ça revient au même, mais c'est quoi cette manie de vouloir mettre un fichier binaire dans un bidule de char? (buffer, vector, string)
    Tout ce que ça apporte, c'est de la confusion.
    Mets ça dans un buffer/vector de uint8_t et corrige les erreurs de compilation, et à mon avis ça se passera un peu mieux.
    et si tu veux pouvoir récupérer du texte, tu fais alors sciemment la conversion vers un string pour pouvoir le traiter en tant que texte. (ou tu écris une fonction pour les fichiers texte)
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  14. #14
    Membre actif
    Avatar de Blo0d4x3
    Inscrit en
    Octobre 2003
    Messages
    583
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 583
    Points : 265
    Points
    265
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    C’est à dire, incomplet ?

    Logiquement, quand tu décodes, il y a le même problème de caractères \0 : tu ne peux pas et ne dois pas traiter ton image comme une chaîne de caractère ! (une fois encodée en base64, en revanche, tu peux).

    Donc toutes les fonctions qui travaillent sur les chaînes terminées par des \0 (c’est normalement indiqué dans la doc) te sont interdites. Indice : si la signature d’une fonction contient char* mais pas de taille, elle t’es interdite. Te restent celles qui travaillent sur les pointeurs + taille si tu es en C, ou sur des types plus évolués si tu es en C++.

    C’est quoi la fonction base64decode que tu utilises ?
    Il en manque une partie, et certain octet ne me semble pas correct.

    C'est décodé par un script php, par la fonction base64_decode

    @dragonjoker59 ok je vais regardé avec ce type si ca me simplifie la vie.

  15. #15
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Peux-tu poster le code que tu utilises actuellement (après les modifications qu’on t’a suggérées). Sans ça, difficile de voir d’où vient le soucis.

  16. #16
    Membre actif
    Avatar de Blo0d4x3
    Inscrit en
    Octobre 2003
    Messages
    583
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 583
    Points : 265
    Points
    265
    Par défaut
    Pas encore toucher, je mettais mis sur une autre partie du projet entre temps, j'en suis donc rester à ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    CStringA ToBase64(const void* bytes, int byteLength)
    {
    	ASSERT(0 != bytes);
     
    	CStringA base64;
    	int base64Length = Base64EncodeGetRequiredLength(byteLength);
     
    	VERIFY(Base64Encode(static_cast<const BYTE*>(bytes),
    		byteLength,
    		base64.GetBufferSetLength(base64Length),
    		&base64Length));
     
    	base64.ReleaseBufferSetLength(base64Length);
    	return base64;
    }
     
     
    LPSTR szBuf;
     
    ...
     
    DWORD dwFileSize = GetFileSize(fileHandle, NULL);
     
    szBuf = (LPSTR)LocalAlloc(LPTR, dwFileSize + 1);
     
    		if (!ReadFile(fileHandle, szBuf, dwFileSize, &dwBytes, NULL))
    		{
    			printf("Readfile failed: %d\n", GetLastError());
    		}
     
    datas = datas + "&s=" + (string)ToBase64(szBuf, dwFileSize + 1);

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ça reste une classe dont le transport de données arbitraires et non zéro-terminées, bien que possible, n'est pas le but premier.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. [NASM] Petits problèmes lecture de fichier
    Par Jaronimo dans le forum Assembleur
    Réponses: 1
    Dernier message: 01/05/2008, 14h56
  2. [XPATH] problème lecture dans fichier XML
    Par DiamonDonald dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 26/02/2008, 09h57
  3. Problème lecture gros fichier texte
    Par UnnamedBoy dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 22/02/2008, 11h13
  4. problème lecture seule fichier image
    Par Damien69 dans le forum Langage
    Réponses: 1
    Dernier message: 23/03/2007, 16h53
  5. problème lecture de fichier
    Par nico33410 dans le forum Langage
    Réponses: 2
    Dernier message: 29/10/2006, 20h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo