我正在尝试使用Mac上的popen()命令在文件上执行程序。为此,我创建了<path-to_executable> <path-to-file>
形式的命令,然后在此命令上调用popen()。现在,这两个组件都在char *中声明。我需要读取命令的输出,所以我需要popen()给出的管道。
现在事实证明,路径到文件可以包含中文,日文,俄文和几乎任何其他字符。为此,我可以将路径到文件表示为wchar_t *。但这对popen()不起作用,因为显然Mac / Linux没有像Windows这样的宽_wpopen()。
有没有其他方法可以让我的工作?我从一个只能给我wchar_t *的数据结构中获取路径到文件,所以我必须从那里获取并根据需要适当地转换它。
提前致谢。
修改
似乎有一天你最后拔头发。
所以我尝试使用wcstombs,但是对于“C.UTF-8”及其任何排列,setlocale调用都失败了。不出所料,wcstombs调用失败后返回-1。
然后我尝试根据在Google上搜索的一些示例代码编写自己的iconv实现。我想出了这个,顽固地拒绝工作:
iconv_t cd = iconv_open("UTF-8", "WCHAR_T");
// error checking here
wchar_t* inbuf = ...; // get wchar_t* here
char outbuf[<size-of-inbuf>*4+1];
size_t inlen = <size-of-inbuf>;
size_t outlen = <size-of-inbuf>*4+1;
char* c_inbuf = (char*) inbuf;
char* c_outbuf = outbuf;
int ret = iconv(cd, &c_inbuf, &inlen, &c_outbuf, &outlen);
// more error checking here
iconv始终返回-1,并且errno设置为EINVAL。我已验证<size-of-len>
已正确设置。我不知道为什么这段代码现在失败了。
编辑2:
iconv失败了因为我没有正确设置输入缓冲区长度。此外,Mac似乎不支持“WCHAR_T”编码,因此我将其更改为UTF-16。现在我已经更正了长度并更改了编码,但iconv只返回而没有转换任何字符。它只返回0.
要调试此问题,我甚至将输入字符串更改为临时字符串并适当设置输入长度。即使这个iconv调用只返回0.我的代码现在看起来像:
iconv_t cd = iconv_open("UTF-8", "UTF-16");
// error checking here
wchar_t* inbuf = ...; // get wchar_t* here - guaranteed to be UTF-16
char outbuf[<size-of-inbuf>*4+1];
size_t inlen = <size-of-inbuf>;
size_t outlen = <size-of-inbuf>*4+1;
char* c_inbuf = "abc"; // (char*) inbuf;
inlen = 4;
char* c_outbuf = outbuf;
int ret = iconv(cd, &c_inbuf, &inlen, &c_outbuf, &outlen);
// more error checking here
我已确认转换器描述符正在正确打开。从编码是正确的。输入缓冲区包含一些简单字符。一切都是硬编码的,而且,iconv不会转换任何字符,只返回0并且outbuf仍为空。
完全失去警惕!
答案 0 :(得分:1)
您需要popen
的UTF-8字符串。为此,您可以使用iconv
在不同的编码之间进行转换,包括从本地wchar_t
编码到UTF-8。 (请注意,在我的Mac OS安装中,wchar_t
实际上是32位,而不是16位。)
编辑以下是适用于OS X Lion的示例。使用wchar_t
编码时没有遇到任何问题(iconv
手册页中对此进行了记录)。
#include <sys/param.h>
#include <string.h>
#include <iconv.h>
#include <stdio.h>
#include <errno.h>
char* utf8path(const wchar_t* wchar, size_t utf32_bytes)
{
char result_buffer[MAXPATHLEN];
iconv_t converter = iconv_open("UTF-8", "wchar_t");
char* result = result_buffer;
char* input = (char*)wchar;
size_t output_available_size = sizeof result_buffer;
size_t input_available_size = utf32_bytes;
size_t result_code = iconv(converter, &input, &input_available_size, &result, &output_available_size);
if (result_code == -1)
{
perror("iconv");
return NULL;
}
iconv_close(converter);
return strdup(result_buffer);
}
int main()
{
wchar_t hello_world[] = L"/éè/path/to/hello/world.txt";
char* utf8 = utf8path(hello_world, sizeof hello_world);
printf("%s\n", utf8);
free(utf8);
return 0;
}
utf8_hello_world
函数接受{<1}}字符串,其字节长度,并返回等效的UTF-8字符串。如果您处理指向wchar_t
而不是wchar_t
数组的指针,则您需要使用wchar_t
代替(wcslen(ptr) + 1) * sizeof(wchar_t)
。
答案 1 :(得分:0)
Mac OS X使用UTF-8,因此您需要将宽字符串转换为UTF-8。如果您首先切换到UTF-8语言环境,则可以使用wcstombs
执行此操作。例如:
// Do this once at program startup
setlocale(LC_ALL, "en_US.UTF-8");
...
// Error checking omitted for expository purposes
wchar_t *wideFilename = ...; // This comes from wherever
char filename[256]; // Make sure this buffer is big enough!
wcstombs(filename, wideFilename, sizeof(filename));
// Construct popen command using the UTF-8 filename
如果您不想更改程序的区域设置,也可以使用libiconv为您执行UTF-16到UTF-8转换;你也可以推出自己的实现,因为转换并不是那么复杂。