【问题标题】:C++ string length different than java string length. JNI AndroidC++ 字符串长度不同于 java 字符串长度。 JNI安卓
【发布时间】:2018-11-12 14:40:18
【问题描述】:

我正在处理一个使用 JNI 将 c++ 后端库集成到 Android 项目中的项目。

我正在使用 SpannableString 类并直接从 C++ 调用 setSpan() 函数来设置样式,而无需在前端用 Java 重新运行代码。

我有一个包含如下标签(如 html)的字符串:

"这是一个测试 {is} 斜体 {ie},我们用来演示应用 功能......”显然有更多的文字。

我在 c++ 中遍历所有字符串字符并保存它们的位置/然后将斜体跨度添加到我的 SpannableString。这是我的循环的样子:

        int its = 0, fns = 0, crfs = 0;
    for(int i = 0; i < buff.size(); ++i){

        if(buff[i] != '{')
            continue;

        string tmp = "";

        for(int a = i + 1; a < i + 5; ++a){
            if(buff[a] == '}')
                break;
            tmp += buff[a];
        }

        if(tmp == "is"){
            its = i;
            //start of italics.
        } else if(tmp == "ie"){
            //end of italic tag.
            if(its == 0)
                continue;

            set_spannable(spannable, new_style_obj(italic), its + 4, i);
            its = 0;
        } else if(tmp == "fn"){
            //new footnote tag.
        } else if(tmp == "cf"){
            //new cross reference tag.
        }

    }

代码编译和运行完美,但斜体的位置与 java 字符串中的位置没有直接关系。由于某种原因,它会继续增加,直到我的斜体字离它们应该在的位置不远。

我在 java 中运行了相同的循环,它运行良好:

        String buff = sp.toString();
    int its = 0;
    for(int i = 0; i < buff.length(); ++i){

        if(buff.charAt(i) != '{')
            continue;

        String tmp = "";

        for(int a = i + 1; a < i + 5; ++a){
            if(buff.charAt(a) == '}')
                break;
            tmp += buff.charAt(a);
        }

        System.out.println(tmp);

        if(tmp.equals("is")){
            its = i;
        } else if(tmp.equals("ie")){
            if(its == 0)
                continue;
            System.out.println("Span from " + its + " to " + i);// + //buff.substr(its + 4, (i-4) -its) + "))";
            sp.setSpan(new StyleSpan(1), its + 4, i, 1);


            // set_spannable(spannable, new_style_obj(italic), its, i);
            its = 0;
        }

    }
    tv.setText(sp);

有趣的是java中的字符串长度总是大于c++中的字符串长度。

我已经使用 strlen(string.c_str()) 和 string.size(); 对其进行了测试。两者都不会返回与 java 调用 string.length 相同的长度。

有人知道造成这种差异的原因以及如何解决吗?是否有在 java 中读取而不是在 c++ 中读取的字符?

提前感谢您的帮助!

更新 1:这是标签位置数据 >>

C++
    Span from 26 to 36
     Span from 146 to 152
     Span from 466 to 473
     Span from 1438 to 1445
     Span from 1726 to 1733
     Span from 1913 to 1920
     Span from 2157 to 2167
     Span from 2228 to 2239
     Span from 2289 to 2299
     Span from 2544 to 2555
     Span from 2827 to 2834
     Span from 2965 to 2972
     Span from 3293 to 3300
     Span from 3913 to 3920
     Span from 4016 to 4023
     Span from 4378 to 4385
     Span from 4467 to 4474
     Span from 5179 to 5195
     Span from 5337 to 5344

Java
    Span from 26 to 36
    Span from 146 to 152
    Span from 462 to 469
    Span from 1426 to 1433
    Span from 1710 to 1717
    Span from 1897 to 1904
    Span from 2139 to 2149
    Span from 2208 to 2219
    Span from 2269 to 2279
    Span from 2520 to 2531
    Span from 2803 to 2810
    Span from 2939 to 2946
    Span from 3265 to 3272
    Span from 3877 to 3884
    Span from 3980 to 3987
    Span from 4340 to 4347
    Span from 4427 to 4434
    Span from 5129 to 5145
    Span from 5285 to 5292

【问题讨论】:

  • c_str() 会将字符串计为 C 字符串,因此在第一个 \0 处停止。 size() 将返回正确的 C++ 大小。 C++ 和 JNI 字符串是否一致? (显示相同)
  • 字符串与我在 c++ 中创建 SpannableString 对象时使用 c++ 字符串设置 java 字符串相同(然后通过 JNI 返回给 Java)。
  • 你能检查一下 C++ 中字符串的编码吗?除非您另有说明,否则这些字符串在 java 中存储为 UTF-16。所以也许问题是你的 C++ 字符串每个字符占用一个字节,而在 java 中它需要两个。
  • 作为一个快速测试,尝试在 C++ 中使用 std::wstring 看看它是否能解决您的问题。
  • @AdamZahran 在进一步测试中,u16string 解决了我的问题!感谢您的回答。如果你发布它,我会正确标记它。

标签: java android c++ java-native-interface


【解决方案1】:

更新后的表格与您的字符串偶尔包含非 ascii 字符的假设一致,这些字符在 C++ 中用多个字符表示。

对此没有简单的解决方法。 minimalistic approach 将在计数时跳过所有具有 utf8 连续位(10 的前两位)的字节,即 0x800xbf 之间的字节。

或者,您可以使用两字节 UCS-16 字符串,我们从 JNI 函数 GetStringChars() 获得,它完全再现了 Java 表示(即长度在 Java 和 C++ 中是相同的),但是库很差支持(没有函数或 std::string 提供帮助)。

或者您可以使用 codecvt_utf8() 将您的 utf8 字符串转换为 wchar_t

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-19
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    相关资源
    最近更新 更多