web-dev-qa-db-fra.com

utiliser fstream pour lire chaque caractère, y compris les espaces et les retours à la ligne

Je voulais utiliser fstream pour lire un fichier txt.

J'utilise inFile >> characterToConvert, mais le problème est que cela omet tous les espaces et les retours à la ligne.

J'écris un programme de cryptage donc j'ai besoin d'inclure les espaces et les nouvelles lignes.

Quelle serait la bonne façon de procéder pour y parvenir?

30
Tomek

La meilleure façon est probablement de lire le contenu complet du fichier dans une chaîne, ce qui peut être fait très facilement en utilisant la méthode rdbuf() d'ifstream:

std::ifstream in("myfile");

std::stringstream buffer;
buffer << in.rdbuf();

std::string contents(buffer.str());

Vous pouvez ensuite utiliser la manipulation de chaîne régulière maintenant que vous avez tout dans le fichier.

Alors que Tomek posait des questions sur la lecture d'un fichier texte, la même approche fonctionnera pour la lecture de données binaires, bien que l'indicateur std :: ios :: binary doive être fourni lors de la création du flux de fichiers d'entrée.

48
Jason Etheridge

Pour le chiffrement, il vaut mieux ouvrir votre fichier en mode binaire. Utilisez quelque chose comme ça pour mettre les octets d'un fichier dans un vecteur:

std::ifstream ifs("foobar.txt", std::ios::binary);

ifs.seekg(0, std::ios::end);
std::ifstream::pos_type filesize = ifs.tellg();
ifs.seekg(0, std::ios::beg);

std::vector<char> bytes(filesize);

ifs.read(&bytes[0], filesize);

Edit: correction d'un bug subtil selon les commentaires.

22
luke

Je n'ai pas testé cela, mais je pense que vous devez effacer le drapeau "sauter les espaces blancs":

inFile.unsetf(ios_base::skipws);

J'utilise la référence suivante pour les flux C++: IOstream Library

14
Adam Holmberg

Une grande partie des avantages de la couche istream est de fournir un formatage et une analyse de base pour les types simples ro et à partir d'un flux. Aux fins que vous décrivez, rien de tout cela n'est vraiment important et vous êtes simplement intéressé par le fichier sous forme de flux d'octets.

À ces fins, vous pouvez être mieux d'utiliser simplement l'interface basic_streambuf fournie par un filebuf. Le comportement "ignorer les espaces blancs" fait partie des fonctionnalités de l'interface istream dont vous n'avez tout simplement pas besoin.

filebuf est à la base d'un ifstream, mais il est parfaitement valide de l'utiliser directement.

std::filebuf myfile;
myfile.open( "myfile.dat", std::ios_base::in | std::ios_base::binary );

// gets next char, then moves 'get' pointer to next char in the file
int ch = myfile.sbumpc();

// get (up to) the next n chars from the stream
std::streamsize getcount = myfile.sgetn( char_array, n );

Jetez également un œil aux fonctions snextc (déplace le pointeur 'get' vers l'avant puis retourne le caractère courant), sgetc (obtient le caractère actuel mais ne déplace pas le pointeur 'get') et sungetc (sauvegarde le 'get' pointeur d'une position si possible).

Lorsque vous n'avez besoin d'aucun des opérateurs d'insertion et d'extraction fournis par une classe istream et que vous avez juste besoin d'une interface d'octets de base, souvent l'interface streambuf (filebuf, stringbuf) est plus appropriée qu'une interface istream (ifstream, istringstream).

3
CB Bailey
std::ifstream ifs( "filename.txt" );

std::string str( ( std::istreambuf_iterator<char>( ifs ) ), 
                 std::istreambuf_iterator<char>()
               );
3
Iakov Minochkin

Le code c ++ suivant lira un fichier entier ...


#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () 
{
  string line;
  ifstream myfile ("foo.txt");

  if (myfile.is_open()){

    while (!myfile.eof()){
      getline (myfile,line);
      cout << line << endl;
    }
    myfile.close();
  }
  return 0;
}

postez votre code et je peux vous apporter une aide plus spécifique à votre problème ...

3
mmattax

Vous pouvez appeler int fstream::get() , qui lira un seul caractère du flux. Vous pouvez également utiliser istream& fstream::read(char*, streamsize) , qui effectue la même opération que get(), juste sur plusieurs caractères. Les liens donnés incluent des exemples d'utilisation de chaque méthode.

Je recommande également la lecture et l'écriture en mode binaire. Cela permet aux caractères de contrôle ASCII d'être lus et écrits correctement dans les fichiers. Sinon, une paire d'opérations de chiffrement/déchiffrement peut entraîner des fichiers non identiques. Pour ce faire, vous ouvrez le flux de fichiers avec le ios::binary flag. Avec un fichier binaire, vous souhaitez utiliser la méthode read().

2
jdmichal

Un autre meilleur moyen consiste à utiliser istreambuf_iterator, et l'exemple de code est le suivant:

ifstream inputFile("test.data");

string fileData(istreambuf_iterator<char>(inputFile), istreambuf_iterator<char>());
2
user1621518

Pour le chiffrement, vous devriez probablement utiliser read () . Les algorithmes de chiffrement traitent généralement des blocs de taille fixe. Oh, et pour ouvrir en mode binaire (pas de traduction frmo\n\r en\n), passez ios_base :: binary comme deuxième paramètre au constructeur ou à l'appel open ().

1
Arkadiy

Facile

#include <fstream>
#include <iomanip>


ifstream ifs ("file");
ifs >> noskipws

c'est tout.

0
Flame
ifstream ifile(path);
std::string contents((std::istreambuf_iterator<char>(ifile)), std::istreambuf_iterator<char>());
ifile.close();
0
MCA

Je trouve également que la méthode get () de l'objet ifstream peut également lire tous les caractères du fichier, qui ne nécessitent pas unset std::ios_base::skipws. Citation de C++ Primer :

Plusieurs opérations non formatées traitent un flux un octet à la fois. Ces opérations, décrites dans le tableau 17.19, lisent plutôt les espaces blancs.

Ces opérations sont répertoriées comme suit: is.get () , os.put () , is.putback () , is.unget () et is.peek () .

Voici un code de travail minimum

#include <iostream>
#include <fstream>
#include <string>

int main(){
    std::ifstream in_file("input.txt");

    char s;

    if (in_file.is_open()){
        int count = 0;
        while (in_file.get(s)){

            std::cout << count << ": "<< (int)s <<'\n';
            count++;
        }

    }
    else{
        std::cout << "Unable to open input.txt.\n";
    }
    in_file.close();

    return 0;
 }

Le contenu du fichier d'entrée (cat input.txt) est

ab cd
ef gh

Le résultat du programme est:

0: 97
1: 98
2: 32
3: 99
4: 100
5: 10
6: 101
7: 102
8: 32
9: 103
10: 104
11: 32
12: 10

10 et 32 ​​sont une représentation décimale du caractère de nouvelle ligne et d'espace. De toute évidence, tous les caractères ont été lus.

0
jdhao