与 c 中使用 _wpopen 的管道的字节顺序不同

loa*_*per 5 c unicode winapi hex wchar

我编写了这个函数,它打开一个管道并将命令传递到要执行的管道,在检查缓冲区时,我注意到有些命令占用 1 个字节,其他命令占用 2 个字节,据说尝试将缓冲区输出到屏幕会导致一些要输出为 Mojibake 的命令

\n
#include <io.h>\n#include <fcntl.h>\n#include <stdio.h>\n#include <stdlib.h>\n\nint test(wchar_t * command)\n{\n    int i =0;\n    wchar_t  psBuffer[128];\n    FILE   *pPipe;\n\n    if( (pPipe = _wpopen( command, L"rb" )) == NULL )\n      exit( 1 );\n\n    wchar_t c;\n    while ( (c = fgetwc(pPipe)) != WEOF && i < 128)\n    {\n        psBuffer[i] = c;\n        wprintf(L"%04X ",c);\n        i++;\n    }\n    psBuffer[i] = L'\\0';\n    wprintf(L"\\n%S", psBuffer);\n    if (feof( pPipe))\n        _pclose( pPipe );\n    return 0;\n}\n\nint main()\n{\n    _setmode(fileno(stdout), _O_U8TEXT);\n    test(L"C:\\\\Windows\\\\System32\\\\cmd.exe  /u /c dir /b");\n    wprintf(L"\\n");\n    test(L"C:\\\\Windows\\\\System32\\\\cmd.exe  /u /c getmac ");\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

输出

\n
0061 002E 0065 0078 0065 000D 000A 006D 0061 0069 006E 002E 0063 000D 000A 043F 0440 0438 0432 0435 0442 000D 000A\na.exe\nmain.c\n\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82\n\n0A0D 6850 7379 6369 6C61 4120 6464 6572 7373 2020 2020 7254 6E61 7073 726F 2074 614E 656D 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 0A0D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 203D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 0A0D 3235 352D 2D34 3030 382D 2D41 4433 382D 2036 2020 445C 7665 6369 5C65 6354 6970 5F70 377B 3344 3135 3441 2D34 3342 3834 342D 3330 2D44 3438 4431 462D 3733 3634 4146 3037 3743 7D33 2020 2020 2020 0A0D 3235 352D 2D34 3030 342D 2D30 3430\n\xe0\xa8\x8d\xe6\xa1\x90\xe7\x8d\xb9\xe6\x8d\xa9\xe6\xb1\xa1\xe4\x84\xa0\xe6\x91\xa4\xe6\x95\xb2\xe7\x8d\xb3\xe2\x80\xa0\xe2\x80\xa0\xe7\x89\x94\xe6\xb9\xa1\xe7\x81\xb3\xe7\x89\xaf\xe2\x81\xb4\xe6\x85\x8e\xe6\x95\xad\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe0\xa8\x8d\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe2\x80\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe0\xa8\x8d\xe3\x88\xb5\xe3\x94\xad\xe2\xb4\xb4\xe3\x80\xb0\xe3\xa0\xad\xe2\xb5\x81\xe4\x90\xb3\xe3\xa0\xad\xe2\x80\xb6\xe2\x80\xa0\xe4\x91\x9c\xe7\x99\xa5\xe6\x8d\xa9\xe5\xb1\xa5\xe6\x8d\x94\xe6\xa5\xb0\xe5\xbd\xb0\xe3\x9d\xbb\xe3\x8d\x84\xe3\x84\xb5\xe3\x91\x81\xe2\xb4\xb4\xe3\x8d\x82\xe3\xa0\xb4\xe3\x90\xad\xe3\x8c\xb0\xe2\xb5\x84\xe3\x90\xb8\xe4\x90\xb1\xe4\x98\xad\xe3\x9c\xb3\xe3\x98\xb4\xe4\x85\x86\xe3\x80\xb7\xe3\x9d\x83\xe7\xb4\xb3\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe0\xa8\x8d\n\xe3\x88\xb5\xe3\x94\xad\xe2\xb4\xb4\xe3\x80\xb0\xe3\x90\xad\xe2\xb4\xb0\xe3\x90\xb0\n
Run Code Online (Sandbox Code Playgroud)\n

正如您所看到的,第一个命令输出中的每个字母/数字均输出为 4 位十六进制值,而第二个命令将两个字母/数字的十六进制值分组为 4 位十六进制值,这导致文本成为 Mojibake

\n

如何解决这个问题,使第二个命令缓冲区看起来像第一个命令缓冲区

\n

更新

\n
int test(wchar_t * command)\n{\n    int i =0, k=0;\n    wchar_t  psBuffer[64];\n    FILE   *fd;\n    if( (fd = _wpopen( command, L"rt" )) == NULL )\n      exit( 1 );\n\n    _setmode(fileno(fd), _O_TEXT);\n    int x = fread(psBuffer, sizeof(wchar_t), 64, fd);\n    for ( i =0; i < x; i++)\n    {\n        wprintf(L"%02X ", psBuffer[i]);\n    }\n    psBuffer[x] = L'\\0';\n    wprintf(L"%S\\n", psBuffer);\n    if (feof(fd))\n        _pclose(fd);\n    return 0;\n}\n\nint main()\n{\n    _setmode(fileno(stdout), _O_U16TEXT);\n    test(L"C:\\\\Windows\\\\System32\\\\cmd.exe  /u /c dir /b");\n    wprintf(L"\\n");\n    test(L"C:\\\\Windows\\\\System32\\\\cmd.exe  /u /c getmac ");\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

从流中读取模式设置为文本的文本并_O_TEXT不能解决问题,因为第二个命令的输出仍然是结果字符串中每两个字母的 4 位十六进制值,而且十六进制值的顺序是向后的,其中P=在=50之前LF0A

\n
61 2E 65 78 65 0D 0A 6D 61 69 6E 2E 63 0D 0A 6D 61 69 6E 32 2E 63 0D 0A 43F 440 438 432 435 442 0D 0A \na.exe\nmain.c\nmain2.c\n\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82\n\n\n500A 7968 6973 6163 206C 6441 7264 7365 2073 2020 5420 6172 736E 6F70 7472 4E20 6D61 2065 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 A20 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 203D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D 3D3D\n\xe5\x80\x8a\xe7\xa5\xa8\xe6\xa5\xb3\xe6\x85\xa3\xe2\x81\xac\xe6\x91\x81\xe7\x89\xa4\xe7\x8d\xa5\xe2\x81\xb3\xe2\x80\xa0\xe5\x90\xa0\xe6\x85\xb2\xe7\x8d\xae\xe6\xbd\xb0\xe7\x91\xb2\xe4\xb8\xa0\xe6\xb5\xa1\xe2\x81\xa5\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe2\x80\xa0\xe0\xa8\xa0\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe2\x80\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\xe3\xb4\xbd\n
Run Code Online (Sandbox Code Playgroud)\n