c - 如何使用 C 在 Postgres 中写入和读取字节
问题描述
我用函数写到postgresBYTE*
中的bytea
字段,它返回bytea:
...
PG_RETURN_BYTEA_P(pbBuffer);
这些字节在文件中看起来像:
稍后我尝试读取此bytea
字段并使用其他函数写入其他文件,如下所示:
bytea* data = PG_GETARG_BYTEA_P(0);
char filePath[] = "C:\\pg\\11.txt";
HANDLE h = CreateFile(filePath, FILE_WRITE_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dw = sizeof(data);
WriteFile(h, data, dw, &dw, NULL);
CloseHandle(h);
在文件中它看起来像: 我应该怎么做才能获得与开始相同的结果?
第一个功能有效:
FILE* log = AllocateFile("C:\\pg\\log.txt", PG_BINARY_A);
char* dataToEncrypt = PG_GETARG_CSTRING(0);
FILE* tempFile = AllocateFile("C:\\pg\\openText.txt", PG_BINARY_A);
fprintf(tempFile, "%s", dataToEncrypt);
FreeFile(tempFile);
HANDLE hSourceFile = INVALID_HANDLE_VALUE;
HANDLE hDestinationFile = INVALID_HANDLE_VALUE;
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTKEY hXchgKey = NULL;
HCRYPTHASH hHash = NULL;
PBYTE pbKeyBlob = NULL;
DWORD dwKeyBlobLen;
PBYTE pbBuffer = NULL;
DWORD dwBlockLen;
DWORD dwBufferLen;
DWORD dwCount;
bool fEOF = FALSE;
char pszPassword[] = "key";
char s[] = "C:\\pg\\openText.txt";
char d[] = "C:\\pg\\cryptoText.txt";
hSourceFile = CreateFile(s, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hSourceFile)
{
fprintf(log, "%u %s\n", GetLastError(), "CreateFile s");
goto Exit_MyEncryptFile;
}
hDestinationFile = CreateFile(d, FILE_WRITE_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hDestinationFile)
{
fprintf(log, "%u %s\n", GetLastError(), "CreateFile d");
goto Exit_MyEncryptFile;
}
if (!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
fprintf(log, "%u %s\n", GetLastError(), "CryptAcquireContext");
goto Exit_MyEncryptFile;
}
if (!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
{
fprintf(log, "%u %s\n", GetLastError(), "CryptCreateHash");
goto Exit_MyEncryptFile;
}
if (!CryptHashData(hHash, (BYTE*)pszPassword, lstrlen(pszPassword), 0))
{
fprintf(log, "%u %s\n", GetLastError(), "CryptHashData");
goto Exit_MyEncryptFile;
}
if (!CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey))
{
fprintf(log, "%u %s\n", GetLastError(), "CryptDeriveKey");
goto Exit_MyEncryptFile;
}
dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
if (ENCRYPT_BLOCK_SIZE > 1)
dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
else
dwBufferLen = dwBlockLen;
pbBuffer = (BYTE*)malloc(dwBufferLen);
do
{
if (!ReadFile(hSourceFile, pbBuffer, dwBlockLen, &dwCount, NULL))
{
fprintf(log, "%u %s\n", GetLastError(), "ReadFile");
goto Exit_MyEncryptFile;
}
if (dwCount < dwBlockLen)
fEOF = TRUE;
if (!CryptEncrypt(hKey, NULL, fEOF, 0, pbBuffer, &dwCount, dwBufferLen))
{
fprintf(log, "%u %s\n", GetLastError(), "CryptEncrypt");
goto Exit_MyEncryptFile;
}
if (!WriteFile(hDestinationFile, pbBuffer, dwCount, &dwCount, NULL))
{
fprintf(log, "%u %s\n", GetLastError(), "WriteFile");
goto Exit_MyEncryptFile;
}
} while (!fEOF);
解决方案
你没有向我们展示创建它的函数bytea
,所以我不知道你是否做对了。
但你肯定搞砸了第二个功能:
Abytea
不是字符串。如果你读到src/include/fmgr.h
,
/*
* Support for fetching detoasted copies of toastable datatypes (all of
* which are varlena types). pg_detoast_datum() gives you either the input
* datum (if not toasted) or a detoasted copy allocated with palloc().
* pg_detoast_datum_copy() always gives you a palloc'd copy --- use it
* if you need a modifiable copy of the input. Caller is expected to have
* checked for null inputs first, if necessary.
*
* pg_detoast_datum_packed() will return packed (1-byte header) datums
* unmodified. It will still expand an externally toasted or compressed datum.
* The resulting datum can be accessed using VARSIZE_ANY() and VARDATA_ANY()
* (beware of multiple evaluations in those macros!)
*
* In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
* VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR(). Elsewhere, call
* PG_DETOAST_DATUM(), VARDATA() and VARSIZE(). Directly fetching an int16,
* int32 or wider field in the struct representing the datum layout requires
* aligned data. memcpy() is alignment-oblivious, as are most operations on
* datatypes, such as text, whose layout struct contains only char fields.
*
* Note: it'd be nice if these could be macros, but I see no way to do that
* without evaluating the arguments multiple times, which is NOT acceptable.
*/
现在,既然bytea
是一个varlena
类型,代码应该看起来像这样:
bytea* data = PG_GETARG_BYTEA_PP(0);
uint32 data_length = VARSIZE_ANY(data);
char *raw_data = VARDATA_ANY(data);
WriteFile(h, raw_data, data_length, &dw, NULL);
推荐阅读
- python - 如何在kivy中使画线每x秒消失一次?
- ruby - error when searching through 2d array ruby
- turn - How does Turn server actually helps clients behind NAT?
- r - 如何处理多元回归中的坐标
- angular - 带有 Angular 7 的 SVG.js 3“没有兼容的调用签名”错误
- vb.net - 为什么新选项卡文本向右对齐?
- java - ObjectInputStream 代码可在一台计算机上运行,但不能在另一台计算机上运行
- java - 有没有办法确保我的数组不返回空值,或者修复我的数组以使其不返回?
- node.js - 如何隐藏<返回
我已经转换了一个 P 标记以将其发送到我的数据库,现在从我的数据库中检索它,但节点或 ejs 没有将 p 标记呈现为 ap 或 html 标记。
我正在尝试将ckeditor作为格式化工具将textarea输出为html,但它将标签转换为<>,当我现在在nodejs中使用php时它工作得很好,它不会将它们转换回<><%= rs.comment %> //输出变量包
- c++ - 桌面上方的 X11/GLX 窗口