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

4 oct. 2011 à 14:59
à ceux qui en auront besoin un jour :

#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 = new char[nbOctet + 1];
  fichier.read(tableau, nbOctet);
  fichier.close();
  tableau[nbOctet] = 0;
  text.assign(tableau, nbOctet);
  delete[] 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 = "Entree.xyz";
  const std::string outputFile2 = "Sortie.xyz";

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

  //entrée
   std::string chiffrement= binaryFormat(text);

   //manipulation sur chiffrement ...

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

  return 0;
}
   // http://www.cppfrance.com/forum/sujet-METTRE-OCTETS-FICHIER-DANS-STRING_1547281.aspx

0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
4 oct. 2011 à 15:04
il est optimale de passer caractère après caractère de char en binaire[..] Quand j'aurai besoin de réel performance

Non, ce n'est absolument pas ça. Un nombre est un nombre !
La réprésentation que tu en fait est imaginaire uniquement.
Ex:
58 (décimal) 3A (Héxadécimal) 72 (octal) == 111010 (en binaire) == ':' (caractère)

On a ici une même valeur, mais vu de différente manière. Un nombre est un nombre !

Donc si je fais 5 + 7 (dec) ou si je fais 101 + 111 (bin), le résultat sera le même: un nombre. A toi de choisir ensuite la représentation. Tu peux très bien faire: 5 (dec) + 111 (bin) == D (hex).

Pour simplifier, quand tu fais:
char c 'a';, c'est comme si tu faisais char c 97; ou encore char c = 0x61;. Si tu fais un std::cout, tu verras 'a' apparaître.

Ex:
#include 

int main()
{
  int x = 97;

  std::cout << "x int: " << x << std::endl
            << "x char: " << static_cast<char>(x) << std::endl
            << "x double: " << static_cast<double>(x) << std::endl;

  int y = 0x61;
  std::cout << "y int: " << y << std::endl
            << "y char: " << static_cast<char>(y) << std::endl
            << "y double: " << static_cast<double>(y) << std::endl;

  int z = 'a';
  std::cout << "z int: " << z << std::endl
            << "z char: " << static_cast<char>(z) << std::endl
            << "z double: " << static_cast<double>(z) << std::endl;

  int a = 0b01100001;
  std::cout << "a int: " << a << std::endl
            << "a char: " << static_cast<char>(a) << std::endl
            << "a double: " << static_cast<double>(a) << std::endl;

  return 0;
}


Vouloir passer par du texte, est une aberration pour deux raisons:
- Performance catastrohpique.
- Pas possible de profiter des tous les opérateurs de manipulations de bits fournit dans le langage.

________________________________________________________________________
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 à 15:40
Vouloir passer par du texte, est une aberration pour deux


Je suis entièrement d'accord! La seule chose que je veux est une variable string qui contient TOUTES les données binaires de mon fichier d'entrée (que des 0 et 1) ! Mais avec le moins de temps d'exécution possible! Juste ça, un string qui contient mes données binaires et cela en peu de temps!

Après, c'est vrai que je n’emballe dans mes formulations de débutant. Ce qui fait qu'on se comprend pas ou tardivement. Mais l'idée est là : peut importe comment, faut un string hautement performant avec les 0 et 1 d'un fichier d'entrée pour le chiffrement.
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
4 oct. 2011 à 15:55
je veux est une variable string qui contient TOUTES les données binaires de mon fichier

C'est déjà ce que fait un std::string... (Y a tout dedans).
Un std::string contient un "char* data" qui est un tableau de caractères. Un caractère est un nombre d'un octet. Donc 8 bits.

Si tu veux inverser tous les 0 et les 1 d'un fichier:
void applyInvert(std::string& text)
{
  const unsigned int size =  text.size();
  for (unsigned int i = 0; i < size; ++i)
    text[i] = ~text[i];
}


Tu agis déjà sur le "binaire". Pas besoin de passer par une représentation textuelle du binaire.

faut un string hautement performant avec les 0 et 1 d'un fichier d'entrée pour le chiffrement.

Dans ce cas, ne rien toucher, cf plus haut.

Résumé: Passer par une représentation texutelle binaire.
Défauts:
- ~8 fois plus de RAM utilisé
- Au moins 8 fois plus d'opérations à faire => Perfs lamentable (au minimum 8 fois plus lent).
- Pas d'optim de manipulation de bit (le processeur à des facilités avec ça, ce qui accélère encore les choses).
- Nécessite de recoder les manipulateurs de bits à la main => Augmentation de la taille du code source et du temps de développement.

Avantage(s):
- Heu... Je ne vois pas. Vraiment.

________________________________________________________________________
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

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

4 oct. 2011 à 17:49
Avantage(s):

Étant débutant en c++, je vois que les manipulations d'un string en c++ pour faire mon chiffrement. Je me rends bien compte que cela multipliera par 8 à cause du passage octet vers binaire ...

J'avais commencé par rechercher une fonction qui me permettrait de jouer directement sur les données binaires sans passer par du textuelle. Pour être précis, je voulais des méthodes pour prendre une série de bits, les manipuler puis les envoyer vers un fichier de sortie. J'ai alors acheté un livre sur le c++. J'ai lu les 100 premières pages et j'ai cru que cela aller me suffire pour faire mon code de chiffrement. Avec ces 100 pages, je sais manipuler simplement des int, des char et des string. C'est à dire, prendre ou rajouter des trucs dans ces variables, y faire des opérations arithmétiques, et ce balader dynamiquement dans celles-ci.
Grâce au code (première version) que tu m'as fourni, je peux tester mon chiffrement avec des petits fichiers même si cela prendra du temps et de la ram. Quand j'aurai la preuve de la véracité de mon chiffrement, c'est vrai qu'il faudra penser à améliorer la performance du programme!

Mais je vais déjà y penser. Là, maintenant! Je vais oublier ma représentation textuelle binaire. Et pour voir si je te suis bien, tu me conseille ceci :
-lire un fichier et stocker ses octets dans un tableau de char
-pour chaque octet stocké dans un char de mon tableau de char, je ne prends pas sa valeur binaire textuelle car mes O ou 1 seront codé sur 8 bits (comme les caractères '0' et '1').
- la subtilité étant de passer par une autre représentation de mon char qui restera sur les 8bits de départ : prendre mon char en décimal, hexa ou autre

Si c'est bien ça, je pourrai me débrouiller avec les valeurs décimales de mes octets. Mais il faudra que je retombe sur du binaire. Alors, j'aurai plus qu'à construire une fonction qui, à une valeur d'un décimal (qui correspond à un char ), renvoie la donnée binaire et là je me démerde pour chiffrer. Je pense même qu'on y avait fait référence dans les anciennes pages de ce topic.
0
ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012

4 oct. 2011 à 17:58
Et si je passais par du "bitset" ? http://www.cplusplus.com/reference/stl/bitset/

Bitset peut-il m'éviter une représentation textuelle binaire ? Existe-t-il une classe en c++ (autre la 2ème version de ton code) ou un autre langage qui permet une manipulation des bits d'un fichier le plus rapidement et sans bouffer de la ram exagérément ? Le tout assez simple pour que je puisse l'apprendre à mon niveau. Je ne sais pas pourquoi mais je le pense : le langage Shell serait intéressant pour ouvrir un fichier et manipuler ses bits directement ?

Où alors je continue sur ta 2ème version pour améliorer la perf?
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
4 oct. 2011 à 18:03
Étant débutant en c++, je vois que les manipulations d'un string en c++ pour faire mon chiffrement.

J'ai bien compris ton point. Tu penses que si tu passes par des strings, il te sera plus facile d'arriver à un résultat. Que la difficulté sera moindre.
Or, la raison pour laquelle j'insiste, c'est que ce ne sera pas le cas. Avec une représentation textuelle, tu ne profites pas des opérateurs de manipulation de bits, et ça va vraiment te compliquer la vie.

Alors, j'aurai plus qu'à construire une fonction qui, à une valeur d'un décimal (qui correspond à un char ), renvoie la donnée binaire

En fait, tu n'as pas besoin de fonction qui renvoie une valeur binaire, car toutes valeurs est par nature binaire.

Voici l'exemple le plus simple que je puis te faire pour illustrer mes propos:
#include 

void chiffrer(std::string& text)
{
  const unsigned int size = text.size();
  for (unsigned int i = 0; i < size; ++i)
    text[i] = ~text[i];
}

int main()
{
  std::string s = "Une phrase a chiffrer";
  std::cout << "Clair: " << s << std::endl;

  chiffrer(s);
  std::cout << "Chiffrée: " << s << std::endl;

  chiffrer(s);
  std::cout << "Déchiffrée: " << s << std::endl;

  return 0;
}


Sans les manipulations de bits, la ligne "text[i ] = ~text[i ];" qui veut dire inverser les 0 et les 1 au niveau binaire, aurait été bien plus fastidieuse à écrire. Ici, j'inverse d'un coup 8 bits.

________________________________________________________________________
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
124
4 oct. 2011 à 18:07
Et si je passais par du "bitset" ? http://www.cplusplus.com/reference/stl/bitset/

Ce n'est pas nécessaire. Agit directement sur tes "char". Ça sera moins compliqué que d'utiliser cette classe pratiquement jamais utilisée :).

Je ne sais pas pourquoi mais je le pense : le langage Shell serait intéressant pour ouvrir un fichier et manipuler ses bits directement ?

Le shell ne travail qu'avec du texte. C'est un langage de script qui ne manie que du texte, et il n'est pas possible de travailler sur les bits.

________________________________________________________________________
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
124
4 oct. 2011 à 18:15
J'en profite pour te mettre de la doc:

- http://fr.wikipedia.org/wiki/Manipulation_de_bit
- http://alain.dancel.free.fr/c/c30_30.htm
- http://www.squalenet.net/fr/ti/tutorial_c/8-operateurs-arithmetiques-et-bits-a-bits.php5 (à partir du chapitre II)
- http://www.developpez.net/forums/d861866/c-cpp/c/manipulation-bits/ (Sujet de forum intéressant sur le sujet).

________________________________________________________________________
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 à 19:02
je prends la doc! ça semble exactement ce que je recherche!

Encore merci! Promis, je posterai une version avec des manipulateurs de bits!
0