繁体   English   中英

如何使用 C 在 Postgres 中写入和读取字节

[英]How to write and read bytes in Postgres with C

我使用 function 将BYTE*写入 postgres 中的bytea字段,返回 bytea:

...
PG_RETURN_BYTEA_P(pbBuffer);

这些字节在文件中看起来像: 在此处输入图像描述 后来我尝试读取这个bytea字段并使用其他 function 写入其他文件,如下所示:

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);

在文件中它看起来像: 在此处输入图像描述 我应该怎么做才能得到与开始相同的结果?

第一个 function 作品:

    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的 function ,所以我不知道您是否做对了。

但你肯定搞砸了第二个 function:

bytea不是字符串。 如果您阅读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.
 */

现在,由于byteavarlena类型,代码应该看起来像这样:

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM