- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个非常大的文件,我需要分成小块读取它,然后处理每一 block 。我正在使用 MapViewOfFile 函数在内存中映射一 block ,但在阅读第一部分后我无法阅读第二部分。当我尝试映射它时它会抛出。
char *tmp_buffer = new char[bufferSize];
LPCWSTR input = L"input";
OFSTRUCT tOfStr;
tOfStr.cBytes = sizeof tOfStr;
HANDLE inputFile = (HANDLE)OpenFile(inputFileName, &tOfStr, OF_READ);
HANDLE fileMap = CreateFileMapping(inputFile, NULL, PAGE_READONLY, 0, 0, input);
while (offset < fileSize)
{
long k = 0;
bool cutted = false;
offset -= tempBufferSize;
if (fileSize - offset <= bufferSize)
{
bufferSize = fileSize - offset;
}
char *buffer = new char[bufferSize + tempBufferSize];
for(int i = 0; i < tempBufferSize; i++)
{
buffer[i] = tempBuffer[i];
}
char *tmp_buffer = new char[bufferSize];
LPCWSTR input = L"input";
HANDLE inputFile;
OFSTRUCT tOfStr;
tOfStr.cBytes = sizeof tOfStr;
long long offsetHigh = ((offset >> 32) & 0xFFFFFFFF);
long long offsetLow = (offset & 0xFFFFFFFF);
tmp_buffer = (char *)MapViewOfFile(fileMap, FILE_MAP_READ, (int)offsetHigh, (int)offsetLow, bufferSize);
memcpy(&buffer[tempBufferSize], &tmp_buffer[0], bufferSize);
UnmapViewOfFile(tmp_buffer);
offset += bufferSize;
offsetHigh = ((offset >> 32) & 0xFFFFFFFF);
offsetLow = (offset & 0xFFFFFFFF);
if (offset < fileSize)
{
char *next;
next = (char *)MapViewOfFile(fileMap, FILE_MAP_READ, (int)offsetHigh, (int)offsetLow, 1);
if (next[0] >= '0' && next[0] <= '9')
{
cutted = true;
}
UnmapViewOfFile(next);
}
ostringstream path_stream;
path_stream << tempPath << splitNum;
ProcessChunk(buffer, path_stream.str(), cutted, bufferSize);
delete buffer;
cout << (splitNum + 1) << " file(s) sorted" << endl;
splitNum++;
}
最佳答案
一种可能是您使用的偏移量不是分配粒度的倍数。来自 MSDN:
The combination of the high and low offsets must specify an offset within the file mapping. They must also match the memory allocation granularity of the system. That is, the offset must be a multiple of the allocation granularity. To obtain the memory allocation granularity of the system, use the GetSystemInfo function, which fills in the members of a SYSTEM_INFO structure.
如果您尝试在分配粒度的倍数之外进行映射,则映射将失败并且 GetLastError
将返回 ERROR_MAPPED_ALIGNMENT
。
除此之外,代码示例中还有很多问题,使您很难看出您正在尝试做什么以及哪里出错了。至少,您需要解决内存泄漏问题。您似乎正在分配然后泄漏完全不必要的缓冲区。给它们起更好的名字可以清楚它们的实际用途。
然后我建议在对 MapViewOfFile 的调用上放置一个断点,然后检查您传递的所有参数值以确保它们看起来正确。一开始,在第二次调用时,您希望 offsetHigh 为 0,offsetLow 为 bufferSize。
一些可疑的事情:
HANDLE inputFile = (HANDLE)OpenFile(inputFileName, &tOfStr, OF_READ);
每个 Actor 都应该让你怀疑。有时它们是必要的,但请确保您了解原因。此时您应该问问自己,为什么您使用的所有其他文件 API 都需要一个 HANDLE
而这个函数返回一个 HFILE
。如果你检查 OpenFile documentation ,您会看到“此函数功能有限,不推荐使用。对于新的应用程序开发,请使用 CreateFile 函数。”我知道这听起来令人困惑,因为您想打开一个现有文件,但 CreateFile 可以做到这一点,并且它返回正确的类型。
long long offsetHigh = ((offset >> 32) & 0xFFFFFFFF);
offset
是什么类型?您可能想确保它是 unsigned long long
或等效的。当位移位时,尤其是向右位移时,您几乎总是希望使用无符号类型来避免符号扩展。您还必须确保它是一种比您要移动的位数更多的类型——将 32 位值移动 32(或更多)位实际上在 C 和 C++ 中是未定义的,这允许编译器进行某些类型的优化。
long long offsetLow = (offset & 0xFFFFFFFF);
在这两个语句中,您必须注意 0xFFFFFFFF
值。由于您没有转换它或给它后缀,因此很难预测编译器会将其视为 int 还是 unsigned int。在这种情况下, 它将是一个 unsigned int,但这对很多人来说并不明显。实际上, 我第一次写这个答案时弄错了。 [本段于 2017 年 5 月 16 日更正] 对于按位运算,您几乎总是希望确保使用的是无符号值。
tmp_buffer = (char *)MapViewOfFile(fileMap, FILE_MAP_READ, (int)offsetHigh, (int)offsetLow, bufferSize);
您正在将 offsetHigh
和 offsetLow
转换为 int
,它们是有符号的值。 API 实际上需要 DWORD
,它们是无符号值。我不会在调用中进行强制转换,而是将 offsetHigh
和 offsetLow
声明为 DWORD
并在初始化中进行强制转换,如下所示:
DWORD offsetHigh = static_cast<DWORD>((offset >> 32) & 0xFFFFFFFFul);
DWORD offsetLow = static_cast<DWORD>( offset & 0xFFFFFFFFul);
tmp_buffer = reinterpret_cast<const char *>(MapViewOfFile(fileMap, FILE_MAP_READ, offsetHigh, offsetLow, bufferSize));
这些修复可能会也可能不会解决您的问题。很难从不完整的代码示例中判断出发生了什么。
这是一个您可以比较的工作示例:
// Calls ProcessChunk with each chunk of the file.
void ReadInChunks(const WCHAR *pszFileName) {
// Offsets must be a multiple of the system's allocation granularity. We
// guarantee this by making our view size equal to the allocation granularity.
SYSTEM_INFO sysinfo = {0};
::GetSystemInfo(&sysinfo);
DWORD cbView = sysinfo.dwAllocationGranularity;
HANDLE hfile = ::CreateFileW(pszFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (hfile != INVALID_HANDLE_VALUE) {
LARGE_INTEGER file_size = {0};
::GetFileSizeEx(hfile, &file_size);
const unsigned long long cbFile =
static_cast<unsigned long long>(file_size.QuadPart);
HANDLE hmap = ::CreateFileMappingW(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hmap != NULL) {
for (unsigned long long offset = 0; offset < cbFile; offset += cbView) {
DWORD high = static_cast<DWORD>((offset >> 32) & 0xFFFFFFFFul);
DWORD low = static_cast<DWORD>( offset & 0xFFFFFFFFul);
// The last view may be shorter.
if (offset + cbView > cbFile) {
cbView = static_cast<int>(cbFile - offset);
}
const char *pView = static_cast<const char *>(
::MapViewOfFile(hmap, FILE_MAP_READ, high, low, cbView));
if (pView != NULL) {
ProcessChunk(pView, cbView);
}
}
::CloseHandle(hmap);
}
::CloseHandle(hfile);
}
}
关于c++ - 使用 MapViewOfFile 映射大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9889557/
如果我在同一进程中为同一文件创建 2 个单独的映射,指针是否会共享? 换句话说: LPCTSTR filename = //... HANDLE file1 = CreateFile(filename
如果我在同一进程中为同一文件创建 2 个单独的映射,指针是否会共享? 换句话说: LPCTSTR filename = //... HANDLE file1 = CreateFile(filename
所以我试图将一个整数 a =3 从服务器端传递到客户端。问题是,当我在客户端执行消息 printf 时,显示的值不是 3,而是一个随机数(某些值)就像 19923)。我试图在服务器端通过值(&a)传递
我正在尝试使用 VS2010 在 Windows 上对文件进行内存映射。我在 DLL 中执行此操作。DLL 的第一个实例可以很好地映射文件。同一进程中的第二个实例导致 *ppvData = ::Map
我正在尝试通过共享内存为学校作业实现 IPC。我创建了一个名为 SharedMemoryBuffer 的类来处理创建文件映射和 View 。 我的 Init() 函数如下所示: BYTE * Shar
使用 win32api,我希望下面的程序创建两个进程并创建一个文件映射。 (使用 C++) 我不知道我应该在 Handle CreateFileMapping(....我试过: PROCCESS_IN
早上好,MapViewOfFile 有可能返回同一个地址两次吗?但是,UnmapViewOfFile 在必须取消映射同一地址两次时会出现错误。我们收到错误 487:地址无效。下面是一些伪代码,展示了我
我有一些使用 MapViewOfFile 共享数据的程序,但我遇到了奇怪的访问冲突,这似乎是由于访问映射文件数据造成的。 一些共享数据有指针,但是这些指针只被一个进程设置和使用,而是由进程内的多个线程
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Why won't the loader load at the desired location “Map
我基本上试图将我的结构转换或复制到我的其他进程部分 View ,但我不断收到错误 C2760: syntax error: unexpected token 'identifier', expecte
我想将 MapViewOfFile 的返回值(据我所知是指向 void 的指针)“强制转换”到我自己的类,以便我能够使用该对象。我知道内存的结构。 headerSize 位于字节号 4 到字节号 8,
如何使用 CreateFileMapping 和 MapViewOfFile 将共享内存分配给静态缓冲区,如下所示。 #pragma data_seg(".ABC") __declspec (dlle
我正在尝试使用需要 DWORD 的函数。 这些是规范: dwFileOffsetHigh [in] A high-order DWORD of the file offset where the vi
您好 StackOverflow 的用户。 我一直在使用 C++ 中 Win32 API 的 MapViewOfFile,我是它的新手,但我一直在尝试为 mapview 文件创建一个信号量,所以一个实
下午好,众所周知,在处理大文件时无法映射到 Win32 中的一个 View ,创建仔细映射的代码并根据需要取消映射文件区域。 pastebin 网址是: 我创建并测试了一个处理大文件的 cMemory
``我正在努力做我的家庭作业,但我无法继续,需要你的帮助。我有两个使用相同文件 (log.txt) 的进程。当我尝试同时写一些东西时,它会覆盖并且只有一个进程写入 txt。 这是我的创作过程, ent
开发游戏(PT 中的“jogo”), 服务器最多可以同时运行 5 个游戏, 客户端将通过映射内存访问。 这就是我所拥有的: 服务器: #define MAX_JOGOS 5 typedef struc
以下代码是否会将文件中的数据加载到系统内存中,以便访问结果指针永远不会阻塞线程? auto ptr = VirtualLock(MapViewOfFile(file_map, FILE_MAP_REA
我有一个非常大的文件,我需要分成小块读取它,然后处理每一 block 。我正在使用 MapViewOfFile 函数在内存中映射一 block ,但在阅读第一部分后我无法阅读第二部分。当我尝试映射它时
只是想知道我是否正在像这样在 Windows 平台上创建共享内存阵列: HANDLE hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAG
我是一名优秀的程序员,十分优秀!