Mettre des octets d'un fichier dans un string

Résolu
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
- 18 sept. 2011 à 23:04
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
- 4 oct. 2011 à 19:02
Bonjour à tous !
Malgrès mes recherches, je suis toujours bloqué.

En fait, je ne sais pas comment mettre les octets d'un fichier quelconque dans une variable string.
Oublions la méthode d'un tableau de char, car traduire des caractères en octets selon la langue utilsée ne me parait
pas judicieux (portabilité, endianess, etc).


Bref, existe-t-il une classe, une fonction ou quoi que ce soit en c++ qui permet de mettre le contenu binaire ("0 et 1")
d'un fichier dans une variable string (sans passer par du texte)? Et dans les autres langages de programmation'Est-ce
possible en java?


Si vous avez un bout de code expliqué,
une fonction ou quoi que ce soit, je prends!!!!




Merci d'avance pour vos réponses pédagogiques !

70 réponses

ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

30 sept. 2011 à 14:01
Maintenant c'est claire pour la ram, j'y vois mieux. Une der des der pour la fin (en enlevant ce que je voulais):

#include 
#include <fstream>
#include <sstream>
#include 

static const unsigned int SHIFT = 8;

std::string formatCharToByte(unsigned char value)
{
  const int shift = SHIFT - 1;
  const unsigned int mask = 1 << shift;
  std::ostringstream buff;

  for (int i = 1; i <= shift + 1; ++i)
  {
    buff << (value & mask ? '1' : '0');
    value <<= 1;
  }

  return buff.str();
}

unsigned char formatByteToChar(const std::string& binFormat)
{
  unsigned char res = 0;

  const int size = binFormat.size() - 1;
  for (int i = 0; i <= size; i++)
  {
    int b = 1;
    int n = binFormat[i] - '0';
    b <<= size - i;
    res += n * b;
  }
  return res;
}

bool fileToString(const std::string& filename, std::string& text)
{
  std::ifstream fichier(filename.c_str(), std::ios::binary);
  if (!fichier)
  {

    return false;
  }

  fichier.seekg(0, std::ios_base::end);
  const int nbOctet = fichier.tellg();
  fichier.seekg(0, std::ios_base::beg);

  char tableau[nbOctet];
  fichier.read(tableau, nbOctet);
  fichier.close();

  text.assign(tableau);
  return true;
}

bool stringToFile(const std::string& filename, const std::string& text)
{
  std::ofstream file(filename.c_str(), std::ios::binary);
  if (!file)
    return false;

  file.write(text.c_str(), text.size());
  file.close();

  return true;
}

std::string binaryFormat(const std::string& text)
{
  std::ostringstream buff;
  for (size_t i = 0; i < text.size(); ++i)
    buff << formatCharToByte(text[i]);

  return buff.str();
}

std::string restoreFormat(const std::string& text)
{
  std::ostringstream buff;
  for (size_t i = 0; i < text.size(); i += SHIFT)
    buff << formatByteToChar(text.substr(i, SHIFT));

  return buff.str();
}

int main()
{
  const std::string inputFile = "testingEntree.txt";
  const std::string outputFile2 = "testingSortie2.txt";

  std::string text;
  if (!fileToString(inputFile, text))
  {
    std::cerr << "Impossible d'ouvrir le fichier en lecture !" << std::endl;
    return 1;
  }

   
   //emplacement pour chiffrage
   
  if (!stringToFile(outputFile2, restoreFormat(chiffrement)))
  {
    std::cout << "Erreur sur fichier de sortie" << std::endl;
    return 3;
  }

  return 0;
}
0
cs_LA_Tupac
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
1
30 sept. 2011 à 14:07
c'est 4 GO pour du 32 bits

En fait c'est plus lié au système de fichier...
Sur du fat32b c'est bien 4Go mais le ntfs est bien au delà..
Et je ne parle pas de l'ext4
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
30 sept. 2011 à 14:13
C'est exact, j'ai confondu avec la RAM exploitable :)

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

1 oct. 2011 à 13:59
Aie aie aie CptPingu ! Le fichier de sortie a toujours une taille inférieur à 1ko. En fait seuls les 4 premiers octets d'une fichier d'entrée ressortent ... j'ai essayé sur plusieurs fichiers et avec ton code final page 4.

Hmmm il y a un problème!
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

1 oct. 2011 à 15:19
J'ai un peu plus de précision.

- Pour un fichier image en entrée vers un fichier image de sortie, le fichier image de sortie fait 4 octet :
  const std::string inputFile = "image.jpg";
  const std::string outputFile1 = "testingSortie1.txt";
  const std::string outputFile2 = "imagesortie.jpg";


- Pour un fichier image dont j'ai changé l'extension .jpg en .txt, le fichier de sortie en .txt est lui aussi de 4 octet encore :
  const std::string inputFile = "image.txt";
  const std::string outputFile1 = "testingSortie1.txt";
  const std::string outputFile2 = "imagesortie.txt";


- Pour un fichier image dont j'ai changé l'extension .jpg en .txt puis copier le contenu de ce fichier text vers le fichier testingEntree.txt, le fichier de sortie est identique en terme de caractère au fichier d'entrée (copie text de image.jpg) mais impossible de visionner l'image selon windows ...
  const std::string inputFile = "testingEntree.txt";
  const std::string outputFile1 = "testingSortie1.txt";
  const std::string outputFile2 = "testingSortie.txt";


- pour un fichier son.mp3 vers un fichier sonSortie.mp3, le programme cesse de fonctionner selon windows
-pour un fichier son.mp3 dont j'ai changé l'extension tel que son.txt pour une sortie en sonSortie.txt, le programme cesse de fonctionner aussi selon windows. Problème de mémoire ram?
  const std::string inputFile = "son.txt";
  const std::string outputFile1 = "testingSortie1.txt";
  const std::string outputFile2 = "sonSortie.txt";



Tout ces tests sont effectués sur la base de ton code en page 4, sans y avoir chiffrer quoi que se soit pour le moment. J'ai donc des fichiers entrée qui ne correspondent pas à ceux de la sortie. Soit font 4 octet, soit en jouant sur les extension on n'arrive pas à visionner.
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

3 oct. 2011 à 15:43
juste pour up le topic.
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
3 oct. 2011 à 16:14
J'ai fait une petite erreur dans la fonction fileToString. Je n'ai pas apposé de 0 terminal à la fin du buffer.
Il arrivait donc aléatoirement que l'on ne prenne plus de données que nécessaire (notamment des données qui ne faisaient pas partie du fichier, soi dit en passant).
Il suffit juste de créer le buffer dynamiquement, et de lui donner une taille supérieur à sa contenance de 1 (pour y mettre le fameux 0 terminal).

Version corrigé:
bool fileToString(const std::string& filename, std::string& text)
{
  std::ifstream fichier(filename.c_str(), std::ios::binary);
  if (!fichier)
    return false;

  fichier.seekg(0, std::ios_base::end);
  const int nbOctet = fichier.tellg();
  fichier.seekg(0, std::ios_base::beg);

  char* tableau = new char[nbOctet + 1];
  fichier.read(tableau, nbOctet);
  fichier.close();
  tableau[nbOctet] = 0;
  text.assign(tableau);
  delete[] tableau;

  return true;
}


________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
cs_LA_Tupac
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
1
3 oct. 2011 à 16:15
et de lui donner une taille supérieur à sa contenance de 1 (pour y mettre le fameux 0 terminal).

Une erreur on ne peut plus classique.
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

3 oct. 2011 à 18:14
quel farceur ce bon vieux contenance de 1

Avec la version corrigée, il n'y a plus le message windows "ce logiciel a cessé de fonctionner.".

Mais il reste encore un problème : les fichiers de sortie font tous 4 octets.
Ce sont les 4 premiers octets du fichier.

On y est presque!
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

3 oct. 2011 à 18:21
Je viens de penser à un truc : 4 octes= 32 bits ! N'y a t il pas un lien avec mon processeur 32 bits ... ?
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
3 oct. 2011 à 18:38
Une erreur on ne peut plus classique.

Tellement classique, qu'il m'arrive encore de la faire ! Je suis sur que ça m'arrivera encore dans 10 ans :p

Mais il reste encore un problème : les fichiers de sortie font tous 4 octets.

C'est normal. Dans un fichier binaire (image, éxecutable, etc..), il peut y avoir des '\0' au milieu de n'importe où. Contrairement à une chaîne ASCII classique (un seul à la fin). Or comme le 0 terminal ('\0' ou 0) veut dire fin de chaine, et bien tu t'arrête au milieu du fichier. Or un fichier d'entête d'un jpg contient un premier block de 4 octet et est séparé... par un 0. D'où ton erreur. (http://sylvain.fish.free.fr/JPEG_SIZE/Read_jpeg_size.htm)
Il suffit d'assigner une taille fixe forcée pour résoudre le souci.
Donc à la place de "text.assign(tableau);", il suffit de mettre: "text.assign(tableau, nbOctet);"

Le code:
bool fileToString(const std::string& filename, std::string& text)
{
  std::ifstream fichier(filename.c_str(), std::ios::binary);
  if (!fichier)
    return false;

  fichier.seekg(0, std::ios_base::end);
  const int nbOctet = fichier.tellg();
  fichier.seekg(0, std::ios_base::beg);

  char* tableau = new char[nbOctet + 1];
  fichier.read(tableau, nbOctet);
  fichier.close();
  tableau[nbOctet] = 0;
  text.assign(tableau, nbOctet);
  delete[] tableau;

  return true;
}


J'aimerais tout de même insister sur le fait, que pour chiffrer un fichier, on ne passe jamais pas sa représentation textuelle binaire, mais directement en affectant son contenu (qui est binaire par nature).

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
3 oct. 2011 à 18:41
D'ailleurs, avec une taille forcée, le 0 terminal n'est plus nécessaire vu qu'on connaît la position de fin.
On peut donc directement écrire:
bool fileToString(const std::string& filename, std::string& text)
{
  std::ifstream fichier(filename.c_str(), std::ios::binary);
  if (!fichier)
    return false;

  fichier.seekg(0, std::ios_base::end);
  const int nbOctet = fichier.tellg();
  fichier.seekg(0, std::ios_base::beg);

  char* tableau = new char[nbOctet];
  fichier.read(tableau, nbOctet);
  fichier.close();
  text.assign(tableau, nbOctet);
  delete[] tableau;

  return true;
}


________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

3 oct. 2011 à 20:54
Merci, merci et encore merci à vous 2 !!!

Tout fonctionne nickel!!

pour chiffrer un fichier, on ne passe jamais pas sa représentation textuelle binaire, mais directement en affectant son contenu (qui est binaire par nature)


Je comprends bien mais pour un fichier texte par exemple les caractères non affichables sont alors remplacer par des espaces et je perds de l'information car pour déchiffrer (de l'espace ou caractère non affichable) il y a perd d'information. Non?
Ou alors, comment toi tu le vois ?

ps: pour un fichier son de 4.7 octet, sans chiffrer, le code met 110s ... Je sens que la lenteur sera mon problème !


Encore un énorme merci!! Vous pouvez pas imaginer! Je vais exploser!!!!
0
cs_LA_Tupac
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
1
3 oct. 2011 à 23:21
Merci, merci et encore merci à vous 2 !!!

Ce fut un plaisir

Je suis sur que ça m'arrivera encore dans 10 ans :p

Voilà qui ne va pas me rassurer

les caractères non affichables sont alors remplacer par des espaces et je perds de l'information car pour déchiffrer (de l'espace ou caractère non affichable) il y a perd d'information. Non?

Oui et non, si tu veux imprimer les donnée ou les afficher à l'écran pour une saisie manuelle il est clair que oui. Mais comme le dit Pingu, le char[] c'est des octets, autrement dit, la matière première de nos systèmes informatiques qui comptent en base 8.
Que ce soit en fichier, en mémoire ou même en mémoire graphique, le ppcm* est tout le temp un char
Il suffit donc de ne jamais transposer ces chars en caractères pour ne pas perdre d'informations.

*ppcm: plus petit commun multiple.
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

4 oct. 2011 à 14:00
Ce fut un plaisir

à moi aussi!

Aucune différence, à part deux étapes inutiles en moins... Gain de perf assuré.


Le gain de performance est grand!!! J'ai pu le voir avec mon fichier son qui sert de test!

Mais ton dernier code renvoie bien des fichiers de sortie d'une bonne taille sauf qu'il est impossible de les lires (image ou son en sortie sans chiffrement préalable)...
Où est ce que ça coince ? Parce que le gain de perf est vraiment intéressant !!!
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
4 oct. 2011 à 14:10
La 1ère fois je prend un fichier "clair" en entrée et j'écris un fichier chiffré.
Si tu appliques le programme une deuxième fois sur le fichier "chiffré" cette fois-ci, tu retrouves un fichier "clair".

Pour retrouver l'état inital de ton programme, il suffit de faire:
applyXor(text); // chiffre
applyXor(text); // déchiffre


(Tu noteras que la fonction de chiffrement est la même que celle de déchiffrement, mais ce n'est pas toujours le cas).

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

4 oct. 2011 à 14:18
binaire -> action -> binaire

J'aimerai que dans la partie action je puisse avoir un string qui contient ces données binaires. Mais si je comprends bien, dans le dernier code avec gain de perf, tout est en caractère sur 8bits ? A moi de transformer les caractères en binaire puis des les chiffrer? C'est pas un peu la même chose que le premier code?

En fait, si j'insiste autant sur le string avec les données binaires c'est que mon chiffrement se base uniquement sur des données binaires (1 et/ou 0). La structure serait :
1)binaire (fichier entrée)==>string
2)string==>chiffrement==>string (chiffrement du string)
3)string==>binaire(fichier sortie)
avec le maximum de gain de perf alors.
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

4 oct. 2011 à 14:24
applyXor(text); // chiffre
applyXor(text); // déchiffre


Marche impec! Gain de temps énorme en occurrence!!
Mais je ne vois pas ou est la variable string qui stocke mes 0 et 1, applyXor(text); renvoie que du texte (caractères donc) non ? (Cfr mon avant dernier post)
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
4 oct. 2011 à 14:34
Un char c'est un octet donc 8 bits. La représentation textuelle, met un bit dans un char. Ton contenu devient donc 8 fois plus gros... pour rien ! Donc forcément, ça va plus vite d'agir directement sur les bits.

Tu peux très bien agir sur un bit particulier (encore heureux) sans passer par du texte.

Ex:
#include 

int main()
{
  unsigned char c = 6; // ou 0000 0110
  unsigned char inverse_c ~c; // ic 1111 1001 => 249
  unsigned char b 6 & 2; // 0000 0100> 2
  unsigned char z c | 1; // 0000 0111> 7

  std::cout << "c  =         " << static_cast(c) << std::endl
            << "inverse_c  = " << static_cast(inverse_c) << std::endl
            << "b  =         " << static_cast(b) << std::endl
            << "z  =         " << static_cast(z) << std::endl;
  return 0;
}


Renseigne toi sur les opérateurs de manipulation de bits (&, |, ^, ~, !, <<, >>, etc...).

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

4 oct. 2011 à 14:47
Si je comprends bien, il est optimale de passer caractère après caractère de char en binaire, plutôt que de faire passer tous les caractères en binaire (grossi de 8 fois le fichier).

Finalement et pour l'instant, je vais prendre la 1ère version. Quand j'aurai besoin de réel performance (inévitablement!) je continuerai la 2ème version du code.

Encore une fois merci à vous 2

vous roxxxxxez !!
0