2010-10-12 8 views
2

Est-il possible en C++ de supprimer/rogner une nouvelle ligne à partir d'un fichier texte?C++ supprime une nouvelle ligne à la fin du fichier texte

Par exemple

content content 
content content 
content content 
<- this line in the text file is empty and needs to go -> 
+0

Oui, mais je suggère une langue de niveau supérieur. Peut-être python, ce qui rendrait cela si facile. Combien de fichiers doivent avoir fait cela? – JoshD

+2

Etes-vous sûr que cette ligne existe réellement et n'est pas un artefact de votre éditeur? Si la dernière ligne avec le contenu est terminée avec '\ n', un éditeur peut afficher une dernière ligne vierge même si cette ligne contient zéro donnée. –

+0

Je n'ai même pas pensé à utiliser '\ n'. J'utilisais endl. – NateTheGreatt

Répondre

2

Bien sûr! Une façon de le faire serait de read the file to a std::string

#include <fstream> 
#include <string> 

// Add this code inside your main() function 
std::ifstream ifs("filename.txt");  
std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); 

et ensuite utiliser l'une des techniques décrites ici:

C++ Remove new line from multiline string

Vous pouvez ensuite remplacer le fichier avec le nouveau résultat. Bien sûr, cette approche n'est pas pratique quand il s'agit de fichiers très volumineux (disons 2Go) mais ce n'est pas une contrainte selon votre question initiale.

Ce thread est également doté d'un excellent matériel de détection de nouvelles lignes.

+0

C'était très utile. Je vous remercie! – NateTheGreatt

0

Vous devez lire tout le contenu de fichier et écrire le contenu à nouveau de telle sorte qu'aucune ligne vide existe, ou la façon dont vous voulez.

+0

Droit, c'est ce que je pensais. Comment ferais-je cela? – NateTheGreatt

+0

je ne peux pas vous dire jusqu'à ce que je connais le format de fichier exact. lire sur C++ fstream: http://www.cplusplus.com/reference/iostream/fstream/ – Donotalo

+0

Le format de fichier est exactement comme ci-dessus, juste avec plus de lignes de contenu plus variable – NateTheGreatt

2
ifstream fin("input.txt"); 
vector<string> vs; 
string s; 
while(getline(fin,s)) 
    vs.push_back(s); 
fin.close(); 

ofstream fout("input.txt"); 
for(vector<string>::iterator it = vs.begin(); it != vs.end(); ++it) 
{ 
    if(it != vs.begin()) 
     fout << '\n'; 
    fout << *it; 
} 
0

Vous pouvez créer un filtre simple, appliqué comme dans:

remove_empty_last_line <input.txt> output.txt 

Ou, vous pouvez créer votre propre flux d'entrée de fichier ala:

#include <fstream> 

std::ifstream myin(filename); 

Ensuite, le code ressemblerait (non testé) ...

char c, d, e; 

if (cin.get(c)) 
    if (cin.get(d)) 
    { 
     while (cin.get(e)) 
     { 
      cout << d; 
      c = d; 
      d = e; 
     } 
     if (c != '\n' || d != '\n') 
      cout << d; 
    } 
    else 
     cout << c; 

(Subst. ituez myin pour cin si désiré, alors myin.close()). Pas besoin d'utiliser std :: strings pour quelque chose de si simple: ils ralentissent tout simplement. L'une des grandes forces de C (et donc C++) est de pouvoir traiter efficacement les données d'un personnage à la fois.

0

La méthode la plus efficace consiste à rechercher jusqu'à la fin du fichier et à déplacer le pointeur de fin de fichier vers l'arrière. Malheureusement, ceci n'est pas portable car il n'y a pas de façon standard de définir le pointeur de fin de fichier dans les bibliothèques standard C ou C++. Vous devez utiliser une fonction spécifique à la plate-forme, telle que SetEndOfFile sous Windows ou ftruncate sous POSIX. Par exemple:

void RemoveFinalNewline(const char *filename) 
{ 
#if defined(_WIN32) 
    HANDLE hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
    if(hFile == INVALID_HANDLE_VALUE) 
     ; // handle error 

    LARGE_INTEGER fileSize; 
    if(GetFileSizeEx(hFile, &fileSize) == 0) 
     ; // handle error 
    if(fileSize.QuadPart < 2) 
     ; // this case is left as an exercise to the reader 

    LARGE_INTEGER newFilePtr; 
    newFilePtr.QuadPart = -2; 
    if(SetFilePointerEx(hFile, &newFilePtr, NULL, FILE_END) == 0) 
     ; // handle error 

    char lastTwoBytes[2]; 
    if(ReadFile(hFile, lastTwoBytes, 2, NULL, NULL) == 0) 
     ; // handle error 

    if(lastTwoBytes[1] == '\n') 
    { 
     fileSize.QuadPart--; 
     if(lastTwoBytes[0] == '\r') 
      fileSize.QuadPart--; 
     if(SetFilePointerEx(hFile, &fileSize, NULL, FILE_BEGIN) == 0) 
      ; // handle error 
     if(SetEndOfFile(hFile) == 0) 
      ; // handle error 
     // Success! 
    } 
    // else the file didn't end in a newline 

    CloseHandle(hFile); // and we're done 
#else // POSIX case; the non-Windows, non-POSIX case is left as an exercise 
    int fd = open(filename, O_RDWR); 
    if(fd == -1) 
     ; // handle error 

    off_t fileSizeMinus1 = lseek(fd, -1, SEEK_END); 
    if(fileSizeMinus1 == (off_t)-1) 
     ; // handle error 

    // We're assuming that a newline is a bare LF '\n' here. The CRLF case 
    // is left as an exercise (hint: see the Windows case above) 
    char lastChar; 
    if(read(fd, &lastChar, 1) != 1) 
     ; // handle error 

    if(lastChar == '\n') 
    { 
     if(ftruncate(fd, fileSizeMinus1) == -1) 
      ; // handle error 
     // else success! 
    } 
    // else the file does not end in a newline 

    close(fd); // and we're done 
#endif 
} 
Questions connexes