C++ 如何从文本文件中删除末尾的换行符

4
有没有办法在C++中从文本文件中删除/修剪尾随的换行符?
例如:
content content
content content
content content
<- this line in the text file is empty and needs to go ->

是的,但我建议使用更高级别的语言。也许是Python,这将使它变得非常容易。需要处理多少个文件? - JoshD
2
你确定该行实际存在,而不是编辑器的产物吗?如果最后一行有内容被终止符 '\n' 结束,则即使该行不包含任何数据,编辑器也可能显示为空白。 - Martin York
我甚至没有想到使用 '\n'。我一直在使用 endl。 - NateTheGreatt
6个回答

3
当然!一种方法是将文件读入到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++ 删除多行字符串中的换行符

然后,您可以使用新结果覆盖文件。当然,当处理非常大的文件(比如,2GB)时,这种方法不太实用,但根据您的原始问题,这样的事情并不是限制。

线程还具有检测换行符的优秀材料。


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

1
最有效的方法是寻找文件末尾并将文件指针向后移动。不幸的是,这种方法不可移植,因为在C或C++标准库中没有设置文件指针的标准方式。您需要使用特定于平台的函数,例如Windows上的SetEndOfFile或POSIX上的ftruncate。例如:
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
}

1

C++11或更高版本-删除尾随的空格(换行符,制表符,空格,...):

std::string readAndTrimTrailingSpaces(std::string const & filePath)
{
    std::ifstream file(filePath);
    std::string   buffer(std::istreambuf_iterator<char>{file}, {});

    while (!buffer.empty() && std::isspace(buffer.back()))
        buffer.pop_back();

    return buffer;
}

1
显然,std::string的第二个参数可以缩短为{} - ggorlen

0

您可以创建一个简单的过滤器,应用如下:

remove_empty_last_line < input.txt > output.txt

或者,你可以自己创建文件输入流,如下:

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

(如果需要,可以将cin替换为myin,然后关闭myin。)对于如此简单的事情,没有必要使用std :: strings:它们只会减慢一切速度。 C(因此也是C ++)的伟大优势之一是能够高效地逐个字符处理数据。

0
你需要从文件中读取所有内容,然后以你想要的方式重新写入内容,使得不存在空行。

没错,那就是我想的。我该怎么做呢? - NateTheGreatt
在我知道确切的文件格式之前,我无法告诉你。请参阅C++ fstream文档:http://www.cplusplus.com/reference/iostream/fstream/ - Donotalo
文件格式与上述完全相同,只是包含更多行的内容更加多样化。 - NateTheGreatt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接