c++ - 从 txt 文件中读取并删除第一行(或最后一行)而不复制

标签 c++ fstream getline stdstring boost-interprocess

我想读取并删除 txt 文件的第一行(不复制,这是一个巨大的文件)。
我已经阅读了网络,但每个人都只是将所需的内容复制到一个新文件中。我不能那样做。

低于第一次尝试。由于没有删除任何行,此代码将陷入循环。如果代码在每次打开时删除文件的第一行,代码就会到达结尾。

#include <iostream>
#include <string>
#include <fstream>
#include <boost/interprocess/sync/file_lock.hpp>

int main() {
    std::string line;
    std::fstream file;
    boost::interprocess::file_lock lock("test.lock");
    while (true) {
        std::cout << "locking\n";
        lock.lock();
        file.open("test.txt", std::fstream::in|std::fstream::out);
        if (!file.is_open()) {
            std::cout << "can't open file\n";
            file.close();
            lock.unlock();
            break;
        }
        else if (!std::getline(file,line)) {
            std::cout << "empty file\n"; //
            file.close();                // never
            lock.unlock();               // reached
            break;                       //
        }
        else {
            // remove first line
            file.close();
            lock.unlock();
            // do something with line
        }
    }
}

最佳答案

这是一个用 C 语言为 Windows 编写的解决方案。 它将立即执行并完成 700,000 行、245MB 的文件。 (0.14 秒)

基本上,我对文件进行内存映射,这样我就可以使用用于原始内存访问的函数来访问内容。映射文件后,我只需使用 strchr 函数来查找用于在 Windows 中表示 EOL 的一对符号中的一个的位置(\n 和\r)——这告诉我们第一行的字节长度.

从这里开始,我只是从第二行的第一个字节 memcpy 回到内存映射区域的开头(基本上是文件中的第一个字节)。

完成此操作后,文件将取消映射,内存映射文件的句柄将关闭,然后我们使用 SetEndOfFile 函数将文件的长度减少第一行的长度。当我们关闭文件时,它缩小了这个长度并且第一行消失了。

自从我刚刚创建并写入文件以来,文件就已经在内存中,这显然会稍微改变执行时间,但 Windows 缓存机制是这里的“罪魁祸首”——我们正在利用的机制来进行操作很快完成。

测试数据为程序源复制10万次保存为testInput2.txt(粘贴10次,全选,复制,粘贴10次——替换原来的10次,共100次——重复直到输出足够大。我在这里停了下来,因为更多似乎让 Notepad++ 有点不开心)

此程序中几乎不存在错误检查,预计输入不是 UNICODE,即 - 输入为每个字符 1 个字节。 EOL序列为0x0D,0x0A(\r,\n)

代码:

#include <stdio.h>
#include <windows.h>

void testFunc(const char inputFilename[] )
{
    int lineLength;

    HANDLE fileHandle = CreateFile(
                                    inputFilename,
                                    GENERIC_READ | GENERIC_WRITE,
                                    0,
                                    NULL,
                                    OPEN_EXISTING,
                                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
                                    NULL
                                    );

    if (fileHandle != INVALID_HANDLE_VALUE)
    {
        printf("File opened okay\n");

        DWORD fileSizeHi, fileSizeLo = GetFileSize(fileHandle, &fileSizeHi);

        HANDLE memMappedHandle = CreateFileMapping(
                                                    fileHandle,
                                                    NULL,
                                                    PAGE_READWRITE | SEC_COMMIT,
                                                    0,
                                                    0,
                                                    NULL
                                                );
        if (memMappedHandle)
        {
            printf("File mapping success\n");
            LPVOID memPtr = MapViewOfFile(
                                            memMappedHandle,
                                            FILE_MAP_ALL_ACCESS,
                                            0,
                                            0,
                                            0
                                          );
            if (memPtr != NULL)
            {
                printf("view of file successfully created");
                printf("File size is: 0x%04X%04X\n", fileSizeHi, fileSizeLo);

                LPVOID eolPos = strchr((char*)memPtr, '\r');    // windows EOL sequence is \r\n
                lineLength = (char*)eolPos-(char*)memPtr;
                printf("Length of first line is: %ld\n", lineLength);

                memcpy(memPtr, eolPos+2, fileSizeLo-lineLength);
                UnmapViewOfFile(memPtr);
            }

            CloseHandle(memMappedHandle);
        }
        SetFilePointer(fileHandle, -(lineLength+2), 0, FILE_END);
        SetEndOfFile(fileHandle);
        CloseHandle(fileHandle);
    }
}

int main()
{
    const char inputFilename[] = "testInput2.txt";
    testFunc(inputFilename);
    return 0;
}

关于c++ - 从 txt 文件中读取并删除第一行(或最后一行)而不复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35723574/

相关文章:

图像文件的C++ ifstream

c++ - 使用 getline() 后的错误空间

c++ - 读取由换行符分隔的文本文件。 Unix 上的 C++

c++ - 如果在多个共享库中调用并且启用了libstdc++静态链接,则C++流变得很糟糕

c++ - cin.getline 将字符串的开头设置为 '\0'

c++ - C++ 中的 getline - 需要帮助

c++ - 关于用括号括起来的声明类型是什么的问题

c++ - Hexfloat 机械手和精度

c++ - 非类型模板数组?

c++ - Imread & argv 图片位置?