每1个字节向文件缓冲区添加4个字节



当它将文件读取到缓冲区时,我想每4个字节添加一个字节。一旦我使用我的代码,它就会将字节添加到文件的末尾,而不是每4个字节。我遇到麻烦了,现在我需要帮助,所以我来了。感谢您对阅读我的帖子感兴趣。

这是我的代码:

BYTE* ReadFileToMem(WCHAR* szFileName, DWORD& dwSize)
{
HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return 0;
dwSize = GetFileSize(hFile, NULL);
if (!dwSize)
return 0;
BYTE* pFileBuffer = (BYTE*)VirtualAlloc(NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!pFileBuffer)
return 0;
DWORD dwRead = 0;
ReadFile(hFile, pFileBuffer, dwSize, &dwRead, NULL);
CloseHandle(hFile);

int allocSize{};
for (int i = 0; i < dwSize; i++)
{
if (i % 4) continue;
allocSize++;
}
int afterSize = allocSize + dwSize;
BYTE* pFileBufferB = (BYTE*)VirtualAlloc(NULL, afterSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
LPBYTE p = pFileBuffer;
for (int i = 0; i < dwSize; i++)
{
if (i % 4) continue;
*pFileBufferB = *p;
pFileBufferB++;
p++;
}
cout << allocSize;
return pFileBufferB;
}

这是修改流上的本地对象以修改输入流的完美情况。

您想要做的是创建std::codecvt方面,并将其添加到本地,并将该本地注入文件流。完成此操作后,流将自动每隔四个元素添加一个空格,并且使用流的代码将不需要执行任何操作。

#include <locale>
#include <fstream>
#include <iostream>
// 
class AddSpaceEveryFourthCharacter: public std::codecvt<char,char,mbstate_t>
{
public:
using MyType        = std::codecvt<char,char,mbstate_t>;
using state_type    = MyType::state_type;
using intern_type   = MyType::intern_type;
using extern_type   = MyType::extern_type;
using result        = MyType::result;
// This indicates that we are converting the input.
// Thus forcing a call to do_in()
virtual bool do_always_noconv() const throw()   {return false;}
// As the buffer is read we read data from "from" and place it
// into "to". As long as we have at least 4 characters in "from"
// and at least 5 characters on the "to" we can copy data (and add
// the extra byte).
virtual result do_in(state_type& state,
const extern_type* from, const extern_type* from_end, const extern_type*& from_next,
intern_type*       to,   intern_type*       to_end,   intern_type*&       to_next
) const
{
std::size_t fromLen = from_end - from;
std::size_t toLen   = to_end - to;
// extract the state of any partial conversions (see below)
int leftOver = *reinterpret_cast<char*>(&state);
while(fromLen >= 4 && toLen >= 5) {
for(int loop = leftOver; loop < 4; ++loop) {
*to++ = *from++;
}
*to++ = '-';  // You did not specify what the extra byte
// was so I guessed at a 'dash'.
fromLen -= 4;
toLen   -= 5;
leftOver = 0;
}
// Copy any remaining characters that will fit from "from"
while(fromLen > 0 && toLen > 0) {
*to++ = *from++;
--fromLen;
--toLen;
++leftOver;
}
// Keep track of any partial conversions.
(*reinterpret_cast<char*>(&state))    = static_cast<char>(leftOver);
// When we have converted as much as possible update the
// output parameters to show where you got to.
from_next = from;
to_next   = to;
// return the appropriate values.
return (fromLen == 0) ? ok : partial;
}
};
int main()
{
// construct a custom filter locale and add it to a local.
const std::locale filterLocale(std::cout.getloc(), new AddSpaceEveryFourthCharacter());
// Create a file, imbue a local and then open the file.
std::ifstream   file;
file.imbue(filterLocale);
file.open("test.data");
// Now simply use the file as you would normally.
std::string line;
while (std::getline(file, line)) {
std::cout << line << "n";
}
}

当我运行这个时,我得到:

> cat test.data
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled it to make a type specimen book.

> ./a.out
Lore-m Ip-sum -is s-impl-y du-mmy -text- of -the -prin-ting- and- typ-eset-ting- ind-ustr-y.
L-orem- Ips-um h-as b-een -the -indu-stry-'s s-tand-ard -dumm-y te-xt e-ver -sinc-e th-e 15-00s,-
whe-n an- unk-nown- pri-nter- too-k a -gall-ey o-f ty-pe a-nd s-cram-bled- it -to m-ake -a ty-pe s-peci-men -book-.

确保将指针的增量放入循环中,您还需要避免内存泄漏:

#include <windows.h>
#include <iostream>
BYTE* ReadFileToMem(WCHAR* szFileName, DWORD& dwSize,DWORD& ByteSize)
{
HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return 0;
dwSize = GetFileSize(hFile, NULL);
if (!dwSize)
return 0;
BYTE* pFileBuffer = (BYTE*)VirtualAlloc(NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!pFileBuffer)
return 0;
DWORD dwRead = 0;
ReadFile(hFile, pFileBuffer, dwSize, &dwRead, NULL);
CloseHandle(hFile);

int allocSize{};
for (int i = 1; i <= dwSize; i++)
{
if (i % 4) continue;
allocSize++;
}
ByteSize = allocSize + dwSize;
BYTE* pFileBufferB = (BYTE*)VirtualAlloc(NULL, ByteSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
BYTE* pp = pFileBufferB;
LPBYTE p = pFileBuffer;
for (int i = 1; i <= dwSize; i++, p++, pp++)
{
*pp = *p;
if (i % 4 == 0)
{
pp++;
*pp = '*';
}
}
std::cout << allocSize;
VirtualFree(pFileBuffer, dwSize, MEM_RELEASE);
return pFileBufferB;
}
int main()
{
DWORD dwSize = 0;
DWORD ByteSize = 0;
WCHAR file[] = L"test.txt";
BYTE* pFileBufferB = ReadFileToMem(file, dwSize, ByteSize);
//To Do;
VirtualFree(pFileBufferB, ByteSize, MEM_RELEASE);
return 0;
}

或者使用std::string::insert(index,std::string):

#include <windows.h>
#include <iostream>
#include <vector>
#include <string>
std::string ReadFileToMem(WCHAR* szFileName, DWORD& dwSize)
{
HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return 0;
dwSize = GetFileSize(hFile, NULL);
if (!dwSize)
return 0;
CHAR* pFileBuffer = (CHAR*)VirtualAlloc(NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!pFileBuffer)
return 0;
DWORD dwRead = 0;
ReadFile(hFile, pFileBuffer, dwSize, &dwRead, NULL);
CloseHandle(hFile);
std::string tmp = pFileBuffer;
VirtualFree(pFileBuffer, dwSize, MEM_RELEASE);
for (int i = dwSize; i > 0; i--)
{
if (i % 4) continue;
tmp.insert(i,"*");
}
return tmp;
}
int main()
{
DWORD dwSize = 0;
DWORD ByteSize = 0;
WCHAR file[] = L"test.txt";
std::string pFileBufferB = ReadFileToMem(file, dwSize, ByteSize);
std::cout << pFileBufferB;
return 0;
}

您只需要为保持结果分配缓冲区((file_size + 3) >> 2 ) * 5。然后将数据从最后移动到开始-在这种情况下,我们可以在一个缓冲区中完成所有操作,而无需额外分配

void ModifyBuffer(PULONG puFrom, ULONG NumberOfBytes /* != 0*/, UCHAR ExtraByte = 0)
{
NumberOfBytes = (NumberOfBytes + 3) >> 2;
union {
PBYTE pbTo;
PULONG puTo;
};
puFrom += NumberOfBytes, pbTo = (PBYTE)puFrom + NumberOfBytes;
do 
{
*--pbTo = ExtraByte;
*--puTo = *--puFrom;
} while (--NumberOfBytes);
}

所有代码:

inline ULONG BOOL_TO_ERROR(BOOL f)
{
return f ? NOERROR : GetLastError();
}
ULONG ReadFileToMem(PCWSTR szFileName)
{
HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
FILE_STANDARD_INFO fsi;
ULONG dwError = BOOL_TO_ERROR(GetFileInformationByHandleEx(hFile, FileStandardInfo, &fsi, sizeof(fsi)));
if (dwError == NOERROR)
{
ULONG64 dwRequiredSize = ((fsi.EndOfFile.QuadPart + 3) >> 2 ) * 5;
if (!fsi.EndOfFile.QuadPart)
{
dwError = ERROR_BUFFER_ALL_ZEROS;
}
else if (dwRequiredSize > MAXULONG)
{
dwError = ERROR_FILE_TOO_LARGE;
}
else
{
if (PVOID buf = LocalAlloc(0, (size_t)dwRequiredSize))
{
ULONG NumberOfBytes;
dwError = BOOL_TO_ERROR(ReadFile(hFile, buf, fsi.EndOfFile.LowPart, &NumberOfBytes, 0));
if (NOERROR == dwError)
{
if (NumberOfBytes)
{
ModifyBuffer((PULONG)buf, NumberOfBytes);
}
else
{
dwError = ERROR_BUFFER_ALL_ZEROS;
}
}
LocalFree(buf);
}
else
{
dwError = GetLastError();
}
}
}
CloseHandle(hFile);
return dwError;
}

最新更新