1

WARC 文件来自 Common Crawl。一个样品:

WARC-Type: response
WARC-Date: 2018-12-09T20:26:32Z
WARC-Record-ID: <urn:uuid:5e578aa4-4ec1-4b48-a3ff-cc0a154660f8>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<meta http-equiv="Content

环境:我在 Windows 的 VS 2019 上使用 C++。我不喜欢使用特殊的库。我查看了将文件映射到内存中,但有人说当您只是按顺序解析文件时它并没有那么快。因为我在 Windows 中,所以我得到了一个很好的 GUI,但我也得到了所有 Unicode 的混乱。

解析的期望输出:我有一个输出文件,我想在其中保存大部分文本和一些标签。我将丢弃大部分输入。一些warc标签向解析器发出信号,它可以向前跳过500个字符。例如,除“WARC-Type: response”之外的任何“WARC-Type”都可以向前跳过已知数量。

我尝试过:将文件读入堆缓冲区,然后使用滑动窗口对缓冲区进行切片。根据窗口内容跳过/保存。能够捕获跨越缓冲区的标签。最终,我将使用 regex 和 string::find 之类的东西来匹配标签和文本。

最大的问题:Unicode。该文件是 UTF-8 格式,包含您可以想象的各种有趣的字符。我使用 MultiByteToWideChar。如果我只转换窗口,我不会使用太多内存,但会遇到文本排列问题。UTF-8 的 15 个字符不会产生 ANSI 的 15 个字符。根据我的 multibtyetowidechar 标志、大小等。我会跳过文本、解码错误等。如果我转换整个缓冲区然后切片到一个窗口中,我使用的内存是原来的两倍。没什么大不了的,但似乎效率低下。

BOOL pageActive = FALSE;
BOOL xml = FALSE;
#define MAXBUFFERSIZE 1024
#define MAXTAGSIZE 64
DWORD windowStart = 0; DWORD windowEnd = 15; DWORD windowSize = 15;
DWORD bufferSize = MAXBUFFERSIZE;
_int64 fileRemaining;

HANDLE hFile;
DWORD  dwBytesRead = 0;
LARGE_INTEGER dwPosition;
TCHAR* buffer;

hFile = CreateFile(
        inputFilePath,         // file to open
        GENERIC_READ,          // open for reading
        FILE_SHARE_READ,       // share for reading
        NULL,                  // default security
        OPEN_EXISTING,         // existing file only
        FILE_ATTRIBUTE_NORMAL, // normal file    | FILE_FLAG_OVERLAPPED
        NULL);                 // no attr. template

if (hFile == INVALID_HANDLE_VALUE)
    {
        DisplayErrorBox((LPWSTR)L"CreateFile");
        return 0;
    }

LARGE_INTEGER size;
GetFileSizeEx(hFile, &size);

_int64 fileSize = (__int64)size.QuadPart;

if(fileSize > MAXBUFFERSIZE){buffer = new TCHAR[MAXBUFFERSIZE];}
else{buffer = new TCHAR[fileSize];}

fileRemaining = fileSize;

while (fileRemaining)                                       // outer loop
{

if (bufferSize > fileRemaining)
     bufferSize = fileRemaining;

if (FALSE == ReadFile(hFile, buffer, bufferSize -1, &dwBytesRead, NULL))
    {
     sendToReportWindow(L"file read failed\n");
     CloseHandle(hFile);
     return 0;
     }

fileRemaining -= bufferSize;

while (windowEnd < bufferSize)              //inner loop. while unused data remains in buffer   
    {
    windowSize = windowEnd - windowStart;
    wstring str;

    for (int i = windowStart; i <= windowEnd; i++) {
      str.append(&buffer[i]);
      }
    str[windowEnd] = '\0';

    TCHAR converted[MAXTAGSIZE] = { 0 };
    MultiByteToWideChar(CP_ACP, MB_COMPOSITE, (LPCCH)str.c_str(), -1, converted, MAXTAGSIZE);
    sendToReportWindow(L"windowStart:%d windowEnd:%d converted:%s\n", windowStart, windowEnd, converted);

    // skip these sections and continue to build the window unless there are sufficient characters in the window to make it worth checking its content.

    // to do: WARC page state (use regex and string::find)
    // allow skipping ~500 chars in some cases

    // to do: XML tags/text
    // keep track of tags that span multiple buffers

    windowStart = windowEnd;
    windowEnd++;
    }    // inner loop

delete [] buffer;
}    // outer loop
4

0 回答 0