Problème de lecture de fichier

pierrem69

Nouveau membre
Bonjour
Voilà je veux programmer un petit programme qui "cache" un fichier text dans une image genre .bmp . En fait je veux justement vérifier si ca marche ! C'est à dire si on peut le faire sans modifier l'image de façon visible à l'oeil nu. C'est bien sur inversible pour récuperer... C'est très con et très nul informatiquement mais bon cela peur servir à passer des email sans se faire choper par les RG (encore qu'ils ne faut pas les prendre pour des cons) en passant des secrets caché dans des images anodines... ;)

voici le programme (c'est ultra basique)

[cpp]
#include <iostream>
#include <string>
#include <fstream>
using namespace std;

const
rapport=20;//on veut par exemple remplacer, discretos un pixel sur 20 par un élément du texte
const
debut=1000;//estimation rapide de l'entête d'un fichier au format bmp
char nomtexte[14]="texte.txt";
char nomimage[14]="image.bmp";
char nomsortie[14]="sortie.bmp";

int main(void)
{
ifstream image;
ifstream texte;
ofstream sortie;
char pixel,lettre;
int i=0;
image.open(nomimage);
texte.open(nomtexte);
sortie.open(nomsortie);

for(int j=0;j<debut;j++) //C'est pour ne pas affecter les param du bmp
{
image.get(pixel);
sortie.put(pixel);

};

while(!(image.eof()))
{
i=i++;
if (i==rapport) //la hop on insère le caractère du fichier texte (une fois que i a atteind la valeur "rapport")
{
i=0;
if (!texte.eof())
{
image.get(pixel); //il faut remplacer donc on continu de lire l'image
texte.get(lettre);
sortie.put(lettre);
}

}
else
{
image.get(pixel);//là on fait que copier pixel à pixel image.bmp dans sortie.bmp
sortie.put(pixel);
}

};

image.close();
texte.close();
sortie.close();

return 0;
}
[/cpp]

C'est très simple et pourtant il y un problème :
le booléen image.eof() se vérifie bien avant la fin du fichier image.bmp. j'ai testé et le programme copie bien les 1000 premier caractères du fichier image.bmp sur sortie.bmp sans problème puis ensuite image.eof() est toujours vrai (donc le fichier est considérer comme fini).
Pouvez vous m'aider ? Sur le net je n'ai que des infos sur les anciennes version de eof sur C (EOF) qui posait poblème.
Est un problème de caractère ascii ? ou ai-je fait une grossière erreur ?
Si oui comment lire un fichier octet par octet autrement ?
 

batchy

Grand Maître
d'ici je vois que t'est sous windows

windows est l'un des derniers OS a ouvrir ses fichiers en mode ''texte'', c'est a dire que des caracteres comme EOF peuvent purement et simplement empecher la lecture des octets suivant ...

faut ouvrir ton fichier en mode binaire, il faut passer un deuxieme argument au constructeur, je crois que c'est ios::binary ou un truc dans ce goût la ...
 

pierrem69

Nouveau membre
Merci je pense que ca doit être ça !!
Mais il fallait connaitre........... (encore un coup de windows...)
 

Podia-Yourt

Nouveau membre
Mais non Windows c'est ce qui a de mieux !
Moi je connais pas du tout ta méthode pour lire les fichiers, pour lire par octets je fais comme ca :

char a;

FILE *file;
file=fopen("./nom.txt","r");

a=fgetc(file);
while (a!=EOF)
{
a=fgetc(file);
}
fclose(file);

J'ai jamais eut de problème avec ça pour les fichiers textes, mais pour les images c'est vrai que ca peut bugger, faut alors utiliser les fonctions binaire (read() et write() ), tu pouras trouver beaucoup beacoup d'info la dessu sur le net.
 

batchy

Grand Maître
(oh une notation unix)

mince alors, a quoi ça servais déjà dowhile() ?
Code:
do {
a=fgetc(file);
while (a!=EOF);

on peut très bien utiliser des fichiers binaires avec fopen et fgets, par exemple :
Code:
char a,s[2];
FILE* file;
if (!(file=fopen("./nom.txt,"rb"))
    Y_A_UNE_ERREUR(errno);
while(1) {
    if (!fgets(&s[0],2,file)) {
       if (errno) {
        Y_A_UNE_ERREUR(errno);
        } else {
           break;
        }
    }
    a=s[0];
}
if (!fclose(file))
    Y_A_UNE_ERREUR(errno);
 

frodon1

Grand Maître


La seule différence que je connaisse entre un [cpp]while(condition) { instructions; } [/cpp] et un [cpp]do { instructions; } while(condition);[/cpp] c'est :
■ dans le 1er cas la condition est testée avant de rentrer dans le while
■dans le 2ème tu exécutes au moins une fois les instructions de la boucle while avant de tester la condition.
Donc dans le 1er cas, tu peux très bien ne jamais rentrer dans ta boucle.

EDIT :
... zut j'avais pas vu l'instruction [cpp]a=fgetc(file);[/cpp] avant sa boucle while ...
Donc ton do{}while() est effectivement utile ici :D
 

KangOl

Grand Maître

on a dit en cpp !
les FILE* c'est en C, et encore...
 

Emmanuel Delahaye

Expert

Non. fgetc() retoure un int. a doit donc être obligatoirement de type int et non char, sinon, EOF (int < 0) risque d'être détecté de façon erronée.
J'ai jamais eut de problème avec ça pour les fichiers textes, mais pour les images c'est vrai que ca peut bugger, faut alors utiliser les fonctions binaire (read() et write() ), tu pouras trouver beaucoup beacoup d'info la dessu sur le net.
Tu peux parfaitement lire du binaire avec ce code (corrigé) à condition d'ouvrir le fichier en mode binaire ("rb").
 

Emmanuel Delahaye

Expert

Fonctionne aussi sous Windows.
mince alors, a quoi ça servais déjà dowhile() ?
Code:
do {
a=fgetc(file);
while (a!=EOF);
L'expression idiomatique est plutôt
Code:
int c;
while ((c=fgetc(file)) != EOF)
{   
   /* processing c ... */
}
on peut très bien utiliser des fichiers binaires avec fopen et fgets, par exemple :
Déconseillé. fgets() est orienté ligne de texte. On a pas d'info de longueur lue. Il peut y avoir des 0 au milieu de la ligne. D'autre part, fgets() ajoute un 0 final... Bref, on va rien retrouver du tout. Quel est le problème avec fread() qui est fait pour ça ?

 

pierrem69

Nouveau membre
En tout cas ce qui suit, comme cela m'avait été conseiller au début marche très bien avec N'IMPORTE QUEL FICHIER:

[cpp]
#include <fstream>
using namespace std;
int main(void)
{
char c;
char nomimage[14]="image.bmp";
ifstream image(nomimage,ios::in | ios::binary);
while(!(image.eof()))
{
c=image.get(pixel);
//blablabla "j'utilise c"
};

return 0;
}
[/cpp]
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 134
Messages
6 718 062
Membres
1 586 394
Dernier membre
Manoushk
Partager cette page
Haut