首页
社区
课程
招聘
未解决 [求助]这个功能可以用C++的流做到吗
发表于: 2019-8-3 04:58 2551

未解决 [求助]这个功能可以用C++的流做到吗

2019-8-3 04:58
2551
原始文件01有4G多,补丁文件02是200MB。我想把200MB的补丁插入到文件01偏移400MB的位置。
如果能够实现的能否贴一下关键地方的代码,谢谢!

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 9626
活跃值: (1826)
能力值: ( LV5,RANK:73 )
在线值:
发帖
回帖
粉丝
2
映射操作
2019-8-3 06:08
0
雪    币: 320
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
#include <stdio.h>
#include <windows.h>
#include <ctime>

BOOL GetFileMapHandle(_In_ PWCHAR pFilePath, _Out_ HANDLE& hFileMap, _Out_ DWORD& dwFileSize)
{
    HANDLE hFile = CreateFile(pFilePath,
                              GENERIC_READ | GENERIC_WRITE,
                              FILE_SHARE_READ | FILE_SHARE_WRITE,
                              NULL,
                              OPEN_EXISTING,
                              FILE_FLAG_OVERLAPPED,
                              NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("CreateFile Failed\n");
        return FALSE;
    }

    dwFileSize = GetFileSize(hFile, NULL);

    hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize, NULL);
    if (hFileMap == NULL) {
        printf("CreateFileMapping Failed\n");
    }
    CloseHandle(hFile);

    return hFileMap != NULL;
}

int main()
{
    WCHAR filePathA[] = L"D:\\a.data"; // 512M 源文件
    WCHAR filePathB[] = L"D:\\b.data"; // 130M 更新文件

    DWORD dwFileSizeA = 0;
    DWORD dwFileSizeB = 0;

    HANDLE hFileMapA = NULL;
    HANDLE hFileMapB = NULL;

    DWORD start       = 1024 * 1024 * 240; // 开始位置
    DWORD end         = dwFileSizeB;       // 结束位置
    DWORD dwFileBlock = 1024 * 1024 * 33;  // 每次更新
    
    clock_t startTime, endTime;
    startTime = clock();

    if (!GetFileMapHandle(filePathA, hFileMapA, dwFileSizeA)) {
        goto exit;
    }
    printf("%p\t%d\n", hFileMapA, dwFileSizeA);

    if (!GetFileMapHandle(filePathB, hFileMapB, dwFileSizeB)) {
        goto exit;
    }
    printf("%p\t%d\n", hFileMapB, dwFileSizeB);

    if (start > dwFileSizeA || dwFileSizeA - start < dwFileSizeB) {
        goto exit;
    }

    for (DWORD i = 0; i < dwFileSizeB; i += dwFileBlock) {
        if (i + dwFileBlock > dwFileSizeB) {
            end = dwFileSizeB - i;
        } else {
            end = dwFileBlock;
        }

        LPVOID pFileBlockA = MapViewOfFile(hFileMapA, FILE_MAP_ALL_ACCESS, 0, start + i, end);
        if (pFileBlockA == NULL) {
            printf("MapViewOfFile Failed\n");
            goto exit;
        }

        LPVOID pFileBlockB = MapViewOfFile(hFileMapB, FILE_MAP_ALL_ACCESS, 0, i, end);
        if (pFileBlockA == NULL) {
            printf("MapViewOfFile Failed\n");
            UnmapViewOfFile(pFileBlockA);
            goto exit;
        }

#ifdef _DEBUG
        printf("%p\t%p\n", pFileBlockA, pFileBlockB);
        for (DWORD j = 1; j < end; j*=2) { // 抽查看下
            printf("%c\t%c\n", *((unsigned char*)pFileBlockA + j), *((unsigned char*)pFileBlockB + j));
        } 
#endif // __DEBUG

        memcpy(pFileBlockA, pFileBlockB, end);

        UnmapViewOfFile(pFileBlockA);
        UnmapViewOfFile(pFileBlockB);
    }

exit:
    if (hFileMapA != NULL) {
        CloseHandle(hFileMapA);
    }
    if (hFileMapB != NULL) {
        CloseHandle(hFileMapB);
    }

    endTime = clock();
    printf("The run time is: %f's", (double)(endTime - startTime) / CLOCKS_PER_SEC);
    return 0;
}
简单测试下 CreateFile /CreateFileMapping/ MapViewOfFile,逻辑应该差不多,具体参数再改改
2019-8-3 17:55
1
雪    币: 320
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
#include <ctime>
#include <ios>
#include <iostream>
#include <vector>
#include <fstream>
#include <assert.h>

int main()
{
  clock_t start = clock();

  // 512M
  std::fstream fa("d:\\a.txt", std::ios::binary|std::ios::out|std::ios::in);
  if (!fa.is_open()) {
    std::cout << "Failed to open"<<std::endl;
    return 1;
  }

  // 130M
  std::streamsize sa = fa.seekg(0, std::ios::end).tellg();
  std::cout << sa << std::endl;
  fa.close();

  std::fstream fb("d:\\b.txt", std::ios::binary|std::ios::in);
  if (!fb.is_open()) {
    std::cout << "Failed to open" << std::endl;
    fa.close();
    return 1;
  }
  std::streamsize sb = fb.seekg(0, std::ios::end).tellg();
  std::cout << sb << std::endl;

  std::streamsize begin = 1024 * 1024 * 50; // 50M

  std::vector<char> buf((unsigned int)sb);
  fb.seekg(0, std::ios::beg).read(&buf[0], sb);
  fa.seekp(begin, std::ios::beg).write(&buf[0], sa);

  clock_t end = clock();
  std::cout << "time : " << ((double)end - start) / CLOCKS_PER_SEC << "s\n";

  fa.close();
  fb.close();
  return 0;
}

测试了下512M文件a 偏移50M 位置 更新为130M文件b 大约0.6秒
你可以测试下更大的文件,如果内存不够的话可以分块来操作

2019-8-4 04:11
0
雪    币: 1540
活跃值: (2807)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好的,我可以学习一下。
2019-8-4 06:37
0
游客
登录 | 注册 方可回帖
返回
//