无法使用具有 n 大小块的 Windows 文件映射顺序处理大于 250kb 的文件

Unable to sequentially process a file > 250kb using Windows file mapping with n-sized chunks

我正在尝试制作一个软件,它接受一个 txt 文件,并且每 4 个字节与一个预定义的数字进行异或运算。
我正在这样做映射内存中的文件并使用大小为 n 的 MapViewOfFile 打开文件块。
我附加的算法适用于小于 250 kb 的 txt 文件。但是对于大于 250kb 的文件,它只会对文件的某些部分进行异或,我不明白为什么以及如何解决这个问题。
有人能帮我吗?

#include "stdafx.h"
#include "Windows.h"
#include <stdio.h>
#include <stdint.h>
#include <iso646.h>
#include <math.h>

unsigned int strToUl(char *s)
{
    int size = 4;
    unsigned int ul = 0;
    memcpy(&ul, (unsigned int *)s, size);
    return ul;
}

char *ulToStr(unsigned int *ul)
{
    int size = 4;
    char *tch = (char *)calloc(size, sizeof(char *));
    memcpy(tch, (char *)ul, size);
    return tch;
}

unsigned int uixor(unsigned int n, unsigned int seed)
{
    srand(seed);
    unsigned int mask = rand();
    char ch[5] = { 0 };
    strcpy_s(ch, 5, ulToStr(&n));
    for (int j = 0; j < 5; j++)
    {
        ch[j] = ch[j] ^ mask;
    }
    return strToUl(ch);
}

BOOL mapWriteChunk(PHANDLE phFile, DWORD dwFileSize, int start, int buffsize, uint32_t xork)
{
    DWORD offset = start;// / 4;// / sizeof(DWORD);
    SYSTEM_INFO SysInfo;
    GetSystemInfo(&SysInfo);
    DWORD dwSysGran = SysInfo.dwAllocationGranularity;
    DWORD dwFileMapStart = (offset/dwSysGran) * dwSysGran;
    DWORD dwMapViewSize = (offset % dwSysGran) + buffsize;
    DWORD dwFileMapSize = offset + buffsize;

    unsigned int *ulMVBuffer = (unsigned int *)MapViewOfFile(*phFile, FILE_MAP_ALL_ACCESS, 0, dwFileMapStart, 0);
    if (ulMVBuffer == NULL)
    {
        printf("ulMVBuffer = NULL\n");
    }

    int iViewDelta = offset - dwFileMapStart;

    for (int i = 0; i < buffsize; i++)
    {
        unsigned int *u = (unsigned int *)ulMVBuffer + (iViewDelta + i);
        unsigned int u1 = *u;
        unsigned int u2 = uixor(u1, xork);
        *u = u2;
        printf("write on %d -> ", iViewDelta);
    }

    UnmapViewOfFile(ulMVBuffer);

    return TRUE;
}

int main()
{
    char name[] = "test.txt";

    OFSTRUCT tOfStrIn;
    tOfStrIn.cBytes = sizeof tOfStrIn;
    HANDLE hFile = (HANDLE)OpenFile(name, &tOfStrIn, OF_READWRITE);
    DWORD dwFileSize = GetFileSize(hFile, NULL);

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


    int pos = 0;
    int chunk = 4;
    int bSize = dwFileSize / sizeof(DWORD);
    int rseed = 10;

    for (pos = 0; pos < bSize; pos+=chunk)
    {
        mapWriteChunk(&hFileMap, dwFileSize, pos, chunk, rseed);
    }

    CloseHandle(hFile);
    CloseHandle(hFileMap);
    system("PAUSE");
    return 0;
}

好的,我发现了问题,我写在这里是为了让遇到同样问题的人知道问题出在哪里。 话不多说,我给你看代码(然后我会解释):

char *ulMVBuffer = (char *)MapViewOfFile(phFile, FILE_MAP_ALL_ACCESS, 0, dwFileMapStart, 0);
if (ulMVBuffer == NULL)
{
    printf("ulMVBuffer = NULL\n");
}

int iViewDelta = offset - dwFileMapStart;

unsigned int mask = myrand(xork);
for(int i = 0; i < buffsize; i++)
{
    unsigned int c = ulMVBuffer[iViewDelta + i] ^ mask;
    ulMVBuffer[iViewDelta + i] = c;
}

所以你必须使用 char 指针映射内存,然后,当你像这样使用 XOR 运算符时:

unsigned int c = ulMVBuffer[iViewDelta + i] ^ mask;

您获得了应用于一组 4 个字节的异或,而不仅仅是 1 个字节,因为 - 据我所知玩弄 - char(1 字节)和 unsigned int(4 bytes) 强制运算符从内存中再选择 3 个字节并将其用于按位运算。 使用指向 unsigned int 的指针是行不通的,因为我猜,它以不同的方式存储内存中的字节(可能是 OS 或依赖于机器?)所以你每次只能异或 1 个字节4 个而不是 4 个字节的组。

如果有人对此有更好的理解或想对此解决方案添加更多内容,我将非常乐意阅读!