分享

No2:luacom中文内容输出BUG及修正

 quasiceo 2014-01-03
2012-03-05 18:33 764人阅读 评论(9) 收藏 举报

    使用cell.Value2输出中文内容时总是乱码。怀疑是utf-8的原因,转换后结果仍然是乱码。自己再写个转换的再测试,依然是乱码,莫非有BUG!?

下个LUACOM的源码,查看函数tLuaCOMTypeHandler::com2luatStringBuffer tUtil::bstr2string。整个过程看起来都OK,但再测试发现,结果字符串少了一个bytes。

    在tLuaCOMTypeHandler::com2lua VT_BSTR分支中返回结果恰好是减去1,将其修改

lua_pushlstring(L, str, str.getSize()-1);修改为lua_pushlstring(L, str, str.getSize());

    重新编译LUACOM,再看cell.Value2输出结果,终于正确了。由于没进行全面测试,不知道其此修改会不会引入错误。资源里有个已经编译好的。

--lc是从网上抄来的unicode utf-8 ansi相互转换的函数

  1. package.cpath=[[C:\Program Files\Lua\5.1\clibs\?.dll;d:\loonlib\sample\lc\?.dll]]  
  2. require "luacom"  
  3. require "lc"  
  4.   
  5. function print_table(t) for k,v in pairs(t) do print(k,v) end end  
  6. excel = luacom.CreateObject("Excel.Application")  
  7. excel.Visible = true  
  8. excel.Workbooks:Add();  
  9. --luacom.ViewTypeLib(excel);  
  10. sheet=excel.Sheets(1);  
  11. local r=sheet:Range("E6");  
  12.   
  13. local s = "严中";  
  14. ws, s2=lc.a2w(s); --0x25 0x4e 0x2d 0x4e 0x00 0x00 6  
  15. print("unicode : " .. lc.bstr(ws, s2));  
  16. us, s2=lc.w2u(ws, s2); --0xe4 0xb8 0xa5 0xe4 0xb8 0xad 0x00 0x00 8  
  17. print("utf8 : " .. lc.bstr(us, s2));  
  18.   
  19. r.Value2=us;  
  20. ws, s2=lc.u2w(r.Value2, s2);  
  21. print("unicode : " .. lc.bstr(ws, s2));  
  22. as, s2=lc.w2a(ws, s2);  
  23. print("ansi : " .. lc.bstr(as, s2));  
  24. print(as);  

lc.def

  1. LIBRARY "lc"  
  2.   
  3. EXPORTS  
  4.     luaopen_lc  


lc.h

  1. extern "C" {  
  2. #include "lua.h"  
  3. #include "lualib.h"   
  4. #include "lauxlib.h"  
  5. int luaopen_local(lua_State* L);  
  6. }  
  7.   
  8. #include <locale.h>  
  9. #include <cstring>  
  10. #ifdef WIN32  
  11. #include <windows.h>  
  12. #include <winnls.h>  
  13. #else  
  14. #include <cstdlib>  
  15. #endif  
  16.   
  17.   
  18. #define LN_lc "lc"  
  19. int lua_a2w(lua_State* L);  
  20. int lua_u2w(lua_State* L);  
  21. int lua_w2a(lua_State* L);  
  22. int lua_w2u(lua_State* L);  
  23. int lua_u2a(lua_State* L);  
  24. int lua_a2u(lua_State* L);  
  25. int lua_bstr(lua_State* L);  
  26.   
  27. int lua_help(lua_State* L);  
  28. wchar_t* mb2wc(const char* mbstr, int& s2, int cp);  
  29. char* wc2mb(const wchar_t* wcstr, int& s2, int cp);  


lc.cpp

  1. #include "lc.h"  
  2. //g++ -shared -s -o lc.dll -O3 lc.cpp lc.def -llua5.1 -DWIN32 -I%loon%/lua/src -L%loon%/lib/gcc_dll/debug -Wl,--out-implib,liblc.a   
  3.   
  4. int lua_bstr(lua_State* L) {  
  5.     const char* s = luaL_optstring(L, 1, "");  
  6.     int len = luaL_optnumber(L, 2, 0);  
  7.     if (strcmp(s, "")==0 || 0==len) {  
  8.         lua_pushstring(L, s);  
  9.     } else {  
  10.         luaL_Buffer b;  
  11.         luaL_buffinit(L, &b);  
  12.         char* byte = (char*)malloc(64);  
  13.         for (int i=0; i<len; ++i) {  
  14.             sprintf(byte, "0x%02x ", (unsigned char)*s++);  
  15.             luaL_addstring(&b, byte);  
  16.         }  
  17.         free(byte);  
  18.         luaL_pushresult(&b);  
  19.     }  
  20.     return 1;  
  21. }  
  22.   
  23. int lua_u2w(lua_State* L) {  
  24.     int result = 0;  
  25.     size_t len = 0;  
  26.     const char* mbstr = lua_tolstring(L, 1, &len);  
  27.     if (mbstr && len>0) {  
  28.         int s2 = 0;  
  29.         wchar_t* wcstr = mb2wc(mbstr, s2, CP_UTF8);  
  30.         if (wcstr) {  
  31.             lua_pushlstring(L, (const char*)wcstr, s2);  
  32.             lua_pushnumber(L, s2);  
  33.             delete[] wcstr;  
  34.             result = 2;  
  35.         }  
  36.     }  
  37.     return result;  
  38. }  
  39.   
  40. int lua_a2w(lua_State* L) {  
  41.     int result = 0;  
  42.     size_t len = 0;  
  43.     const char* mbstr = lua_tolstring(L, 1, &len);  
  44.     if (mbstr && len>0) {  
  45.         int s2 = 0;  
  46.         wchar_t* wcstr = mb2wc(mbstr, s2, CP_ACP);  
  47.         if (wcstr) {  
  48.             lua_pushlstring(L, (const char*)wcstr, s2);  
  49.             lua_pushnumber(L, s2);  
  50.             delete[] wcstr;  
  51.             result = 2;  
  52.         }  
  53.     }  
  54.     return result;  
  55. }  
  56.   
  57. int lua_w2a(lua_State* L) {  
  58.     int result = 0;  
  59.     size_t len = 0;  
  60.     const char* wcstr = lua_tolstring(L, 1, &len);  
  61.     if (wcstr && len>0) {  
  62.         int s2 = 0;  
  63.         char* mbstr = wc2mb((wchar_t*)wcstr, s2, CP_ACP);  
  64.         if (mbstr) {  
  65.             lua_pushlstring(L, mbstr, s2);  
  66.             lua_pushnumber(L, s2);  
  67.             delete[] mbstr;  
  68.             result = 2;  
  69.         }  
  70.     }  
  71.     return result;  
  72. }  
  73.   
  74. int lua_w2u(lua_State* L) {  
  75.     int result = 0;  
  76.     size_t len = 0;  
  77.     const char* wcstr = lua_tolstring(L, 1, &len);  
  78.     if (wcstr && len>0) {  
  79.         int s2 = 0;  
  80.         char* mbstr = wc2mb((wchar_t*)wcstr, s2, CP_UTF8);  
  81.         if (mbstr) {  
  82.             lua_pushlstring(L, mbstr, s2);  
  83.             lua_pushnumber(L, s2);  
  84.             delete[] mbstr;  
  85.             result = 2;  
  86.         }  
  87.     }  
  88.     return result;  
  89. }  
  90.   
  91. int lua_u2a(lua_State* L) {  
  92.     int result = 0;  
  93.     size_t len = 0;  
  94.     const char* mbstr = lua_tolstring(L, 1, &len);  
  95.     if (mbstr && len>0) {  
  96.         int s2 = 0;  
  97.         wchar_t* wcstr = mb2wc(mbstr, s2, CP_UTF8);  
  98.         if (wcstr) {  
  99.             char* nmbstr = wc2mb(wcstr, s2, CP_ACP);  
  100.             if (nmbstr) {  
  101.                 lua_pushlstring(L, nmbstr, s2);  
  102.                 lua_pushnumber(L, s2);  
  103.                 result = 2;  
  104.                 delete[] nmbstr;  
  105.             }  
  106.             delete[] wcstr;  
  107.         }  
  108.     }  
  109.     return result;  
  110. }  
  111.   
  112. int lua_a2u(lua_State* L) {  
  113.     int result = 0;  
  114.     size_t len = 0;  
  115.     const char* mbstr = lua_tolstring(L, 1, &len);  
  116.     if (mbstr && len>0) {  
  117.         int s2 = 0;  
  118.         wchar_t* wcstr = mb2wc(mbstr, s2, CP_ACP);  
  119.         if (wcstr) {  
  120.             char* nmbstr = wc2mb(wcstr, s2, CP_UTF8);  
  121.             if (nmbstr) {  
  122.                 lua_pushlstring(L, nmbstr, s2);  
  123.                 lua_pushnumber(L, s2);  
  124.                 result = 2;  
  125.                 delete[] nmbstr;  
  126.             }  
  127.             delete[] wcstr;  
  128.         }  
  129.     }  
  130.     return result;  
  131. }  
  132.   
  133. wchar_t* mb2wc(const char* mbstr, int& s2, int cp) {  
  134.     wchar_t* wcstr = NULL;  
  135. #ifdef WIN32  
  136.     int size = MultiByteToWideChar(cp, 0, mbstr, -1, NULL, 0);  
  137. #else  
  138.     size_t size = mbstowcs(NULL, mbstr, 0);  
  139. #endif  
  140.     wcstr = new wchar_t[size];  
  141.     if (wcstr) {  
  142.         memset(wcstr, 0, size * sizeof(wchar_t));  
  143. #ifdef WIN32  
  144.         int ret = MultiByteToWideChar(cp, 0, mbstr, -1, wcstr, size);  
  145.         if (ret == 0) { // MultiByteToWideChar returns 0 if it does not succeed.  
  146. #else  
  147.         size_t ret = mbstowcs(wcstr, mbstr, size+1);  
  148.         if (ret == -1) {  
  149. #endif  
  150.             delete[] wcstr;  
  151.             wcstr = NULL;  
  152.         }  
  153.         s2 = 2*size;  
  154.     }  
  155.     return wcstr;  
  156. }  
  157.   
  158. char* wc2mb(const wchar_t* wcstr, int& s2, int cp) {  
  159.     char* mbstr = NULL;  
  160. #ifdef WIN32  
  161.     int size = WideCharToMultiByte(cp, 0, wcstr, -1, NULL, 0, NULL, NULL);  
  162. #else  
  163.     size_t size = wcstombs(NULL, wcstr, 0);  
  164. #endif  
  165.     mbstr = new char[size];  
  166.     if (mbstr) {  
  167.         memset(mbstr, 0, size * sizeof(char));  
  168. #ifdef WIN32  
  169.         int ret = WideCharToMultiByte(cp, 0, wcstr, -1, mbstr, size, NULL, NULL);  
  170.         if (ret == 0) { // MultiByteToWideChar returns 0 if it does not succeed.  
  171. #else  
  172.         size_t ret = wcstombs(mbstr, wcstr, size+1);  
  173.         if (ret == -1) {  
  174. #endif  
  175.             delete[] mbstr;  
  176.             mbstr = NULL;  
  177.         }  
  178.         s2 = size;  
  179.     }  
  180.     return mbstr;  
  181. }  
  182.   
  183. int lua_help(lua_State* L) {  
  184.     const char* s=   
  185.         "Simple Characters Transformation\n"  
  186.         "  a2w(ansi to unicode)\n"  
  187.         "  u2w(utf8 to unicode)\n"  
  188.         "  w2a(unicode to ansi)\n"  
  189.         "  w2u(unicode to utf8)\n"  
  190.         "  u2a(utf8 to ansi)\n"  
  191.         "  a2u(ansi to utf8)\n"  
  192.         "  bstr(bytes of str)\n"  
  193.         "  help(show this)\n\n"  
  194.         "  example :\n"  
  195.         "    local s = \"I like lua\"\n"  
  196.         "    print(lc.bstr(s, string.len(s)+1))\n"  
  197.         "    local ws, s2 = lc.a2w(s)\n"  
  198.         "wunoman@qq.com 2012/03/06\n"  
  199.         ;  
  200.     lua_pushstring(L, s);  
  201.   
  202.     return 1;  
  203. }  
  204.   
  205. luaL_reg lrg_lc[] = {  
  206.     {"a2w", lua_a2w},  
  207.     {"u2w", lua_u2w},  
  208.     {"w2a", lua_w2a},  
  209.     {"w2u", lua_w2u},  
  210.     {"u2a", lua_u2a},  
  211.     {"a2u", lua_a2u},  
  212.     {"bstr", lua_bstr},  
  213.     {"help", lua_help},  
  214.     {NULL, NULL}  
  215. };  
  216.   
  217. extern "C" int luaopen_lc(lua_State* L) {  
  218.     luaL_register(L, LN_lc, lrg_lc);  
  219.     return 1;  
  220. }  



更多 0
查看评论
4楼 windtailljj 2012-05-12 22:19发表 [回复]
我看了下你说的那个函数,貌似没有问题,因为上面的bstr2string()函数有一个默认参数是nullterminated=true,返回的字符串中带有一个'\0',而他使用的pushlstring(而不是pushstring),确实应该 -1 的啊,你这个修改应该是碰巧解决了问题吧。
Re: alga_1 2012-06-02 14:52发表 [回复]
回复windtailljj:很可能是巧合。
3楼 danninggao 2012-04-24 14:44发表 [回复]
虽然不知道是什么原因 但是胡乱尝试下好像解决问题了,再获得EXCEL表中值时 local sRet = oExcel.Activesheet.Cells(Row, Column).Value2 ,些时为UTF-8,然后将字符串长度减2,local nTemp = string.sub(nRet,1,string.len(nRet)-2),再将utf-8转为gbk,这时后就正常了
2楼 danninggao 2012-04-18 14:41发表 [回复]
测试了下 发现当从EXCEL中读的汉字为4个的时候 显示有点不正常
Re: alga_1 2012-04-22 10:54发表 [回复]
回复danninggao:出现乱码?之前试了一下姓名都是三个字以下的。
Re: danninggao 2012-04-24 12:24发表 [回复]
回复alga_1:又试了下 比如EXCEL中四个汉字"朋友朋友" local sRet = oExcel.Activesheet.Cells(Row, Column).Value2 获取到值后,然后通过函数conver将utf-8转成gbk,print(conver(sRet)) 输出结果为“朋友朋友 4” 如果我加个赋值过程local temp = conver(sRet) print(temp) 然后输出就正常。还发现一个新问题,读取temp的值为"朋友" string.len(temp) 长度为6,而实际上长度为4 ,就导致读出来的变量无法进行操作,如print(temp.."测试") 输出结果还是为"朋友"
Re: alga_1 2012-04-30 20:29发表 [回复]
回复danninggao:我是这样试的:
package.cpath=[[?.dll]]
require "luacom"
require "lc"

function print_table(t) for k,v in pairs(t) do print(k,v) end end
excel = luacom.CreateObject("Excel.Application")
excel.Visible = true
excel.Workbooks:Add();
sheet=excel.Sheets(1);
local r=sheet:Range("E6");
local s = "严中严中";
ws, s2=lc.a2w(s);
print("unicode : " .. lc.bstr(ws, s2));
us, s2=lc.w2u(ws, s2);
print("utf8 : " .. lc.bstr(us, s2));
r.Value2=us;
ws, s2=lc.u2w(r.Value2, s2);
print("unicode : " .. lc.bstr(ws, s2));
as, s2=lc.w2a(ws, s2);
print("ansi : " .. lc.bstr(as, s2));
print(as);
输出结果:
C:\WINDOWS\system32\cmd.exe /c lua libexcel.lua
unicode : 0x25 0x4e 0x2d 0x4e 0x25 0x4e 0x2d 0x4e 0x00 0x00
utf8 : 0xe4 0xb8 0xa5 0xe4 0xb8 0xad 0xe4 0xb8 0xa5 0xe4 0xb8 0xad 0x00
unicode : 0x25 0x4e 0x2d 0x4e 0x25 0x4e 0x2d 0x4e 0x00 0x00
ansi : 0xd1 0xcf 0xd6 0xd0 0xd1 0xcf 0xd6 0xd0 0x00
严中严中
Hit any key to close this window...
输入是4个汉字,数了一下,输出为9个byte,其中包含了结束符0x00,结果算是正确的。
1楼 quosin 2012-03-21 18:08发表 [回复]
你好,我也遇到这个问题,急需解决,可不可以把你改好的库给我用一下!qq号 674438136 拜托啦
Re: alga_1 2012-04-21 20:07发表 [回复]
回复qushiheng:改好的库放在链接里,上面“资源”点一下

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约