英语轻松读发新版了,欢迎下载、更新

请教下swift中读取C函数返回值的中文问题

surefire 发布于 2015年12月15日
无人欣赏。

我在做数据库客户端时遇到了一个问题,场景就是swift中调用C函数,这个C函数返回的是char *类型,我用swift中的String.fromCString方法把char *转成swift里的字符串,一直用得好好的没什么问题,后来发现客户端在查询数据时会偶然崩溃,也不知道是什么原因,后来发现查询数据中有中文时就会奔溃,没中文就没事,我估计应该是编码问题,但是没有找到swift中String类如何处理中文的,哪位有遇到过这种情况吗?谢谢!

共13条回复
tinyfool 回复于 2015年12月15日

你把你用的代码贴出来,这样方便大家帮助你

surefire 回复于 2015年12月15日

1楼 @tinyfool 好吧,就那句String.fromCString(PQgetvalue(result, Int32(row), Int32(col)))!引发异常。PQgetvalue(result, Int32(row), Int32(col))函数从result结果中读取数据,返回char *

        self.numberOfRows = Int(PQntuples(result))
        for var row = 0; row < self.numberOfRows; row++ {
            let rowrecord = NSMutableDictionary()
            for var col = 0; col < self.numberOfColumns; col++ {
                if PQgetisnull(result, Int32(row), Int32(col)) == 1 {
                    rowrecord.setObject("", forKey:self.fields[col] as! String)
                }else {
                    let key = self.fields[col] as! String
                    let val = String.fromCString(PQgetvalue(result, Int32(row), Int32(col)))!

                    rowrecord.setObject(val, forKey:key)
                }
            }
            tuples.addObject(rowrecord)
        }
tinyfool 回复于 2015年12月15日

2楼 @surefire 我实验了如下代码,没有出现问题,所以我估计问题不在中文上,你最好把问题隔离清楚去测试,比如自己构建一个中文字符串

let test1 = "This is a simple string"
let test2 = "我们是少先队员"

let result = String.fromCString(strstr(test1,"is"))

let result2 = String.fromCString(strstr(test2,"队员"))
surefire 回复于 2015年12月15日

3楼 @tinyfool 也许吧,不过你这个场景跟我的还是有不一样。我那个中文字符是从数据库里捞出来的,而且是PostgreSQL数据库的C函数传过来的char*类型,不知道这个会不会有什么区别。因为确实现象就是查英文的没事,查中文的就熄火了。

windgo 回复于 2015年12月15日

是不是和编码有关系,Xcode里面一般是utf8的编码。

surefire 回复于 2015年12月15日

5楼 @windgo 猜测也是编码,但是String这个函数不清楚如何设置编码

tinyfool 回复于 2015年12月15日

4楼 @surefire 我们没有你的环境,所以你要自己去构建环境啊

比如,你把传出来的内容和自己构建的CString做比较啊,看看是不是一样啊

或者你把断点设在 PQgetvalue(result, Int32(row), Int32(col)),然后看看内容是啥啊

学习调试的方法比学会一个具体的知识更加重要

surefire 回复于 2015年12月15日

7楼 @tinyfool

Xcode设断点提示这个:

Thread 14:EXCBADINSTRUCTION(code=EXCI386INVOP,subcode=0x0) 我也看不懂,下面的信息是线程14调用栈吧

0x100391253 <+35>: callq 0x1003de270 ; function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded> of Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt) -> ()).(closure #2) -> 0x100391258 <+40>: ud2
0x10039125a <+42>: movq $0x0, -0x10(%rbp)

另外更正一下,如tiny叔所说,不是中文引起的,因为我查另外一个数据库的中文信息能正确显示,这种现象是不是因为编码不同或者这个数据库的数据本身就有问题——不过我用其他数据库客户端是可以查出数据,不会报错。

tinyfool 回复于 2015年12月15日

8楼 @surefire 这个数据库本身的信息,你可以获取么?比如编码之类的。

你遇到多线程不好加断点的情况,可以自己做一些log输出到终端上帮助自己分析

关键是先弄清楚问题,然后才是解决问题

surefire 回复于 2015年12月15日

拖到下面又发现这样一些信息: 0x100391340 <+272>: leaq 0xdbc0d(%rip), %rdi ; "fatal error" 0x100391347 <+279>: leaq 0xdc892(%rip), %rcx ; "high- and low-surrogate code points are not valid Unicode scalar values"

0x1003913ea <+442>: leaq 0xdbb63(%rip), %rdi ; "fatal error" 0x1003913f1 <+449>: leaq 0xdbcf8(%rip), %rcx ; "shift amount is larger than type size in bits"

0x100391413 <+483>: leaq 0xdbb3a(%rip), %rdi ; "fatal error" 0x10039141a <+490>: leaq 0xdc80f(%rip), %rcx ; "value is outside of Unicode codespace" 0x100391421 <+497>: movl $0xb, %esi

猜测还是数据本身的编码问题

surefire 回复于 2015年12月15日

9楼 @tinyfool 这个数据库的编码是utf-8

jokester 回复于 2016年03月02日

不要强行解optional, 把出错时char*的内容dump出来看看(存到NSData然后NSLog那个NSData)

surefire 回复于 2016年03月03日

12楼 @jokester 后来我发现那些字段从数据库读出的是一个nil,我在程序里判断了一下,避免了程序奔溃,但还是没能解决这种中文为何读不出数据,可能还是某种神秘编码,没深入研究了

本帖有13个回复,因为您没有注册或者登录本站,所以,只能看到本帖的10条回复。如果想看到全部回复,请注册或者登录本站。

登录 或者 注册
[顶 楼]
|
|
[底 楼]
|
|
[首 页]