Mettre des octets d'un fichier dans un string [Résolu]

Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
- - Dernière réponse : 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 !
Afficher la suite 

20/70 réponses

Meilleure réponse
Messages postés
3821
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
28 août 2019
86
3
Merci
Il n'y a pas 360000 solutions. Il te suffit d'ouvrir un fichier, trouver sa taille, et copier (d'un seul block ou en plusieurs fois) son contenu au format binaire dans un std::string.

Voici un exemple:

#include 
#include <fstream>

bool fileToString(const std::string& filename, std::string& content)
{
  std::ifstream file(filename.c_str(), std::ios::binary);
  if (!file)
    return false;

  file.seekg(0, std::ios::end);
  long size = file.tellg();
  file.seekg(0, std::ios::beg);
  char* page = new char[size];
  file.read(page, size);
  file.close();
  content.assign(page, size);
  delete[] page;

  return true;
}

int main(int argc, char** argv)
{
  if (argc < 2)
  {
    std::cerr << "Usage: " << argv[0] << " <files>" << std::endl;
    return 1;
  }

  for (int i = 1; i < argc; ++i)
  {
    std::string content;
    if (!fileToString(argv[i], content))
    {
      std::cerr << "Unable to open the file: " << argv[i] << std::endl;
      return 2;
    }

    std::cout << "content = " << content << std::endl
      << "size = " << content.size() << std::endl;
  }

  return 0;
}


________________________________________________________________________
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

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 195 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cptpingu
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
3
Merci
Je pense que la question vient d'un manque de compréhension.
Quand le fichier est ouvert en mode binaire (std::ios::binary cf. code plus haut),
on en extrait des chars. Mais ce n'est pas moins du binaire car un char est un octet réinterprété sous forme de caractère.
Donc pour travailler réellement en binaire sur tes fichiers, tu peux caster tes class ou objets divers en char* avant de les copier sous forme de texte dans des fichiers binaires
Ou si le but (mais je ne vois pas l’intérêt) est de faire des accès bit à bit, tu peux stocker le fichier dans un char* et avec un p'tit convertisseur decimal->binaire tu touche directement aux 01...mais bon voilà...

ex enregistrement binaire:
void SauveMonInt(const std::string &flnm, int MonInt)
{
    std::ifstream file(flnm.c_str(), std::ios::binary);
    file.write(reinterpret_cast<char*>(&MonInt), sizeof(int));
    file.close();
}

Bon ok y'a aucun contrôle des erreurs mais c'est le principe
Et effectivement il faut se méfier des problèmes de portabilité, notamment 32b->64b car la taille de certaines variables change.
Il faut aussi faire gaffe à l'alignement des données car un objet de 24Bytes en fera la plupart du temps 32 en mémoire mais ça peut différer en fonction du compilateur utilisé, des attributs de l'objet, et de l'architecture du système...

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 195 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cs_LA_Tupac
Messages postés
3821
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
28 août 2019
86
3
Merci
Je me suis permis quelques petits changements dans ton code. Notamment sur le découpage des fonctions, que tu ne fais pas du tout:
#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;
}

void test()
{
  for (char c = 'a'; c <= 'z'; ++c)
    std::cout << c << " -> " << formatCharToByte(c)
      << " -> " << formatByteToChar(formatCharToByte(c)) << std::endl;
}

std::string fileToString(const std::string& filename)
{
  std::ifstream fichier(filename.c_str(), std::ios::binary);
  if (!fichier.is_open())
  {
    std::cerr << "Impossible d'ouvrir le fichier en lecture !" << std::endl;
    return "";
  }

  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();

  return tableau;
}

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()
{
  //test();
  const std::string binFormat = binaryFormat(fileToString("testing.txt"));
  std::cout << binFormat << std::endl;

  std::cout << restoreFormat(binFormat) << std::endl;

  return 0;
}


________________________________________________________________________
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

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 195 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cptpingu
Messages postés
3821
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
28 août 2019
86
3
Merci
Agir directement sur le binaire, ne provoque aucune perte d'information quelque soit le type de fichier.
Ce que tu fais actuellement, c'est:
binaire -> représentation binaire en texte -> action -> représentation binaire en texte -> binaire
Alors que tu pourrais faire:
binaire -> action -> binaire

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

Exemple avec un xor:
#include 
#include <fstream>
#include <sstream>
#include 

static const unsigned int SHIFT = 8;

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;
}

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;
}

void applyXor(std::string& text)
{
  const unsigned int size = text.size();
  for (unsigned int i = 0; i < size; ++i)
    text[i] ^= 1; // autre exemple: text[i] -= 1 ou text[i] += 1,  etc...
}

int main()
{
  const std::string inputFile = "in";
  const std::string outputFile2 = "out";

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

  applyXor(text);

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

  return 0;
}


________________________________________________________________________
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

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 195 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cptpingu
Messages postés
14636
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
9 octobre 2019
90
0
Merci
Hello,
Peux-tu nous expliquer clairement ce que tu cherches à faire?
car traduire des caractères en octets selon la langue

Je ne comprends pas trop: un caractère = un octet (du moins, en ASCII)

@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
Commenter la réponse de BunoCS
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
0
Merci
Merci à tous! finalement je vais faire des tableaux de char en m'inspirant de vos codes.

étant débutant, ne vous étonnez pas si je fais appel à vous via un message privé pour me corriger!

Merci merci
Commenter la réponse de ddraper
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
0
Merci
Pas de soucis, n'hésite pas a me mp
Commenter la réponse de cs_LA_Tupac
Messages postés
14636
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
9 octobre 2019
90
0
Merci
De préférence, passes par le forum, ça peut aider la communauté


@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
Commenter la réponse de BunoCS
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
0
Merci
Bon par mp j'ai su que le but est bien de bosser bit à bit.
Donc j'explique:

On charge le fichier ouvert en binaire dans un char[taillefichier]
Ensuite on décompose octet par octet (char[0 -> taillefichier])
Et pour chaque char, on converti sa valeur entière ( 't' == 116 par ex.) en binaire.
Pour convertir en base 2 on a 8 cases de tailles: 128 64 32 16 8 4 2 1
avec 48 à convertir par ex. On cherche si on peut lui soustraire 128, non donc 0 dans la case de gauche.
Enlever 64 non plus donc 0 dans celle d'à coté, 32 oui donc 1 il reste 16. Du coup peut-on soustraire 16 à 16, oui! et pour le reste on met 0 (il ne reste rien)
ce qui donne 00110000 !
Pour la partie prog c'est à toi de jouer, une fonction qui transforme char->bool[7] et l'inverse pour réinsérer le char dans la chaîne.
Commenter la réponse de cs_LA_Tupac
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
0
Merci
Bonjour ou bonsoir !

J'y suis presque! Je sais prendre les octets d'un fichier et les mettre dans un tableau de char de la taille du nombre d'octet du fichier.

Mais le problème est que je bloque sur la conversion d'un char en int ...

1) Soit il existe une fonction qui convertit un char[i] en int. J'oublie atoi et istringsteam qui ne marche qu'avec un nombre dans un string ou un char vers un int.

2) Soit je donne une équivalence décimal de tous les char[i] possibles. Mais alors problème! Car les char sont en ansi et donc contient des caractères qui varient selon la langue ou l'ordinateur utilisée non'Ou bien l'ouverture en binaire donne toujours un même ensemble de caractère peut-importe l'ordinateur utilisé?

Voilà , j'y suis presque!
Commenter la réponse de ddraper
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
0
Merci
hey hey ça avance un peut oui.
Un char est un int sur 8 bits oublie atoi()
Comme un petit exemple vaut mieux qu'un long discourt:

char MyChar = 't';
int Myint = MyChar; // pas de conversion nécessaire ... 
std::cout<<"Tint:"<<Tint<<std::endl;
// Sortie: Tint:116


C'est la fonction d'affichage qui converti ce int 8bit en caractère mais les chaines de caractère sont bien des nombres.
Par contre les char étants sur 8 bits, il n'existe que 256 caractères...
char C = 310;//pas possible


J'espère que c'est assez clair.
Commenter la réponse de cs_LA_Tupac
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
0
Merci
ps: non c'est pas du ansi (ça n'existe pas)
C'est de l'ascii qui ne change pas selon le langage, ni l'OS (à ma connaissance).
Commenter la réponse de cs_LA_Tupac
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
0
Merci
Merde... : "Le code ASCII étendu n'est pas unique et dépend fortement de la plateforme utilisée."
http://www.commentcamarche.net/contents/base/ascii.php3

J'ai compris pour le char en int! J'avance!
Commenter la réponse de ddraper
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
0
Merci
Rectification, ça change rien pour moi la variation des normes ou extension ascii.

J'avance, j'avance!
Commenter la réponse de ddraper
Messages postés
305
Date d'inscription
jeudi 29 avril 2004
Statut
Membre
Dernière intervention
18 janvier 2012
0
Merci
héhé oui ça ne change rien car tu compte utiliser les octets bit à bit ... tu t'en fiches de savoir si ça donne un 't', un 'o' ou un '.' c'est une valeur
Commenter la réponse de cs_LA_Tupac
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
0
Merci
Salut à tous !

j'ai encore un problème avec mon code : il ne renvoie pas les bon caractères! Je m'explique ...

Pour vérifier que je sais bien récupérer des bits d'un fichier pour les manipuler puis les retransformer en fichier, j'ai construit mon code en 2 partie:

1)J'ouvre un fichier en lecture binaire. Je construit un tableau de char, puis je convertis chacun des char en int ,que je stocke dans un string. Là tout fonctionne selon moi.

2) Je prends las bits dans le string que je transforme en int puis en char dans un tableau de char qui va servir à créer le fichier de sortie.

Bref, normalement je dois avoir le même fichier. Sauf que, j'ai bien le même nombre d'octet en entrée comme en sortie mais les caractères sont tous différents! Si en entrée j'ai un fichier text avec juste "bonjour", en sortie j'ai un charabia inexplicable! à quel endroit du code ça cloche ?

#include 
#include <fstream>
#include <cmath>
#include <cstring>
#include <sstream>

using namespace std;
int main()
{
    ifstream fichier("testing.txt",ios::binary);
      if (!fichier.is_open())  //vérification
      cout << "Impossible d'ouvrir le fichier en lecture !";


int nbrOctet;
fichier.seekg(0,ios_base::end);
nbrOctet= fichier.tellg();
fichier.seekg(0,ios_base::beg);

// construction du tableau de char,
  char* tableau = new char[nbrOctet];
  fichier.read(tableau, nbrOctet);
  fichier.close();


  int i=0, valeurChar=0,j, d;
  string a="0";
  string b="1";
   string s;
   int totalTest1=0;

  for(i=0; i<nbrOctet; i++)
  {
         valeurChar=tableau[i];
         totalTest1=totalTest1+valeurChar;
         for(j=7;j>-1;j--) // convertion décimal vers binaire
                {
                    d=valeurChar-pow(2,j);
                    if(d>=0)  {s=s+b; valeurChar=d;}
                    else {s=s+a; }

                }

     }

     // s contient maintenant tout en binaire


string  aa, g; // string s est là où est stocké la chaine binaire, doit être un multiple de 8 si travail sur octet
int valeurCharA=0, tailleStringS=0, bb=0,f=0, gchiffre=0,jj,ii,ff,hh;
tailleStringS=s.size();
f=tailleStringS/8;
ff=f + 1; //Il ne faut que des multiples de 8, + 1 car on démarre de 1 et non de 0!
char* tableauSortie = new char[f];
char tableauAvent;


for(jj=1;jj<f; jj++) //Il ne faut que des multiples de 8
{
    bb=8*jj -1;
      aa=s.substr(bb,8);
    valeurCharA=0; //initialisation pour éviter erreur de valeur
    for(ii=7;ii>-1;ii--) // on lit en binaire de droite à gauche!!!
    {
                g=aa.at(ii);
                {
                    istringstream istr(g);
                    istr >> gchiffre;
                }
                if(gchiffre==1)
                {
                    hh=7-ii; // pr avoir le bon ii à la bonne position!
                    valeurCharA= valeurCharA + pow(2,hh);
                }

    }

     tableauAvent= valeurCharA; //convertion du int en char
    tableauSortie[jj]=tableauAvent; // remplissage du tableau de sortie    cout<<"\n int m= "<<m<;



}

  //fin du remplisage du tableau de char
   //début de la copie du tableau ds le dossier

     ofstream fichierSortie ("testingSortie.txt", ios::out | ios::binary); //ouverture en ecriture !!
      fichierSortie.write(tableauSortie, f);
      fichierSortie.close();
      cout<<"TERMINE !!!!!";





return 0;
}

Commenter la réponse de ddraper
Messages postés
3821
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
28 août 2019
86
0
Merci
- Évite les "using namespace", voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
- Évite de faire du "new" quand ce n'est pas nécessaire. Surtout si en plus tu oublies un "delete" derrière (fuite mémoire).
- Un std::ofstream à l'option std::ios::out implicite, inutile de le repréciser. (std::ifstream à lui std::ios::in implicite)

Je ne comprends pas ta logique. Le format binaire, c'est ce déjà ce que tu as en entrée. Ce n'est pas parce que tu stockes la représentation entière des caractères ASCII que c'est du binaire...
En gros, tu ne touches à rien et ça fonctionnera.

Ex:
#include 
#include <fstream>

int main()
{
  std::ifstream fichier("testing.txt", std::ios::binary);
  if (!fichier.is_open())
  {
    std::cerr << "Impossible d'ouvrir le fichier en lecture !" << std::endl;
    return 1;
  }

  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();// Pas obligatoire, le fichie se ferme à la desctruction de l'objet fichier

  const std::string buff = tableau;
  // buff contient ton fichier en binaire.

  std::ofstream fichierSortie ("testingSortie.txt", std::ios::binary);
  fichierSortie.write(buff.c_str(), buff.size());
  fichierSortie.close(); // Pas obligatoire, le fichie se ferme à la desctruction de l'objet fichierSortie
  std::cout << "TERMINE !!!!!" << std::endl;

  return 0;
}


________________________________________________________________________
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
Commenter la réponse de cptpingu
Messages postés
3821
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
28 août 2019
86
0
Merci
Ok, oublie mon dernier message. Je viens de comprendre ce que tu entends par "binaire".
Sache juste que ce n'est pas le bon terme (ce qui m'a induit en erreur).

Disons plutôt que tu cherches à obtenir une représentation en base 2 d'une source arbitraire.
Les conseils généralistes restent néanmoins valables.

________________________________________________________________________
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
Commenter la réponse de cptpingu
Messages postés
34
Date d'inscription
dimanche 18 septembre 2011
Statut
Membre
Dernière intervention
14 janvier 2012
0
Merci
CptPingu : ok pr les conseils généraux, mais pour mon problème de caractères entre l'entrée et la sortie ?
Commenter la réponse de ddraper
Messages postés
3821
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
28 août 2019
86
0
Merci
Je regarde actuellement. Ton format a-t-il une taille fixe ?

________________________________________________________________________
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
Commenter la réponse de cptpingu