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

cptpingu Messages postés 3835 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 1 novembre 2022 124
19 sept. 2011 à 11:52
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
3
cs_LA_Tupac Messages postés 305 Date d'inscription jeudi 29 avril 2004 Statut Membre Dernière intervention 18 janvier 2012 1
20 sept. 2011 à 02:15
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...
3
cptpingu Messages postés 3835 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 1 novembre 2022 124
28 sept. 2011 à 19:02
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
3
cptpingu Messages postés 3835 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 1 novembre 2022 124
3 oct. 2011 à 21:51
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
3

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

Posez votre question
BunoCS Messages postés 15342 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 26 janvier 2023 103
19 sept. 2011 à 09:00
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...
0
ddraper Messages postés 34 Date d'inscription dimanche 18 septembre 2011 Statut Membre Dernière intervention 14 janvier 2012
20 sept. 2011 à 13:40
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
0
cs_LA_Tupac Messages postés 305 Date d'inscription jeudi 29 avril 2004 Statut Membre Dernière intervention 18 janvier 2012 1
20 sept. 2011 à 13:47
Pas de soucis, n'hésite pas a me mp
0
BunoCS Messages postés 15342 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 26 janvier 2023 103
20 sept. 2011 à 13:54
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...
0
cs_LA_Tupac Messages postés 305 Date d'inscription jeudi 29 avril 2004 Statut Membre Dernière intervention 18 janvier 2012 1
20 sept. 2011 à 21:01
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.
0
ddraper Messages postés 34 Date d'inscription dimanche 18 septembre 2011 Statut Membre Dernière intervention 14 janvier 2012
23 sept. 2011 à 19:06
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!
0
cs_LA_Tupac Messages postés 305 Date d'inscription jeudi 29 avril 2004 Statut Membre Dernière intervention 18 janvier 2012 1
23 sept. 2011 à 20:39
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.
0
cs_LA_Tupac Messages postés 305 Date d'inscription jeudi 29 avril 2004 Statut Membre Dernière intervention 18 janvier 2012 1
23 sept. 2011 à 20:43
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).
0
ddraper Messages postés 34 Date d'inscription dimanche 18 septembre 2011 Statut Membre Dernière intervention 14 janvier 2012
23 sept. 2011 à 22:02
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!
0
ddraper Messages postés 34 Date d'inscription dimanche 18 septembre 2011 Statut Membre Dernière intervention 14 janvier 2012
23 sept. 2011 à 22:06
Rectification, ça change rien pour moi la variation des normes ou extension ascii.

J'avance, j'avance!
0
cs_LA_Tupac Messages postés 305 Date d'inscription jeudi 29 avril 2004 Statut Membre Dernière intervention 18 janvier 2012 1
25 sept. 2011 à 20:47
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
0
ddraper Messages postés 34 Date d'inscription dimanche 18 septembre 2011 Statut Membre Dernière intervention 14 janvier 2012
28 sept. 2011 à 17:16
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;
}

0
cptpingu Messages postés 3835 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 1 novembre 2022 124
28 sept. 2011 à 17:38
- É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
0
cptpingu Messages postés 3835 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 1 novembre 2022 124
28 sept. 2011 à 17:41
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
0
ddraper Messages postés 34 Date d'inscription dimanche 18 septembre 2011 Statut Membre Dernière intervention 14 janvier 2012
28 sept. 2011 à 17:57
CptPingu : ok pr les conseils généraux, mais pour mon problème de caractères entre l'entrée et la sortie ?
0
cptpingu Messages postés 3835 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 1 novembre 2022 124
28 sept. 2011 à 17:59
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
0
Rejoignez-nous