C ++ удалить завершающую новую строку из текстового файла - PullRequest
2 голосов
/ 12 октября 2010

Есть ли способ в C ++ удалить / обрезать завершающую новую строку из текстового файла?

Например

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

Ответы [ 5 ]

2 голосов
/ 12 октября 2010
* 1000 Конечно *! Один из способов сделать это - прочитать файл в 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>());

, а затем используйте любой из методов, описанных здесь:

C ++ Удалить новую строку из многострочной строки

тогда вы можете перезаписать файл новым результатом. Конечно, этот подход не практичен при работе с очень большими файлами (скажем, 2 ГБ), но это не является ограничением в соответствии с вашим первоначальным вопросом.

Эта нить также имеет большой материал для обнаружения новых строк.

2 голосов
/ 12 октября 2010
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;
}
1 голос
/ 12 октября 2010

Самый эффективный способ - поиск конца файла и перемещение указателя конца файла назад.К сожалению, это не переносимо, потому что в стандартных библиотеках C или C ++ не существует стандартного способа установки указателя конца файла.Вам необходимо использовать платформо-зависимую функцию, например SetEndOfFile в Windows или ftruncate в POSIX.Например:

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
}
0 голосов
/ 12 октября 2010

Вы можете создать простой фильтр, примененный как:

remove_empty_last_line < input.txt > output.txt

Или вы можете создать свой собственный поток ввода файлов ala:

#include <fstream>

std::ifstream myin(filename);

Тогда код будет похож (не проверен) ...

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;

(Если хотите, замените myin на cin, затем myin.close ()). Нет необходимости использовать std :: strings для чего-то такого простого: они просто все замедляют. Одной из сильных сторон C (и, следовательно, C ++) является способность эффективно обрабатывать данные персонажа за один раз.

0 голосов
/ 12 октября 2010

Вам необходимо прочитать все содержимое из файла и снова записать содержимое таким образом, чтобы не было пустой строки, или так, как вы хотите.

...