【问题标题】:How to shorten QString in a way, that when converted to UTF-8 it is shorter than certain length?如何以某种方式缩短 QString,当转换为 UTF-8 时它比一定长度短?
【发布时间】:2014-10-29 11:39:19
【问题描述】:

我正在尝试创建一种有效的算法来缩短 QString,因此当转换为 UTF-8 时,它会比定义的长度短,并且仍然是有效的 UTF-8。

  • 输入
    • QString 文本 - 包含所有可能字符的字符串 - 未指定最大长度
    • int 限制 - 以 utf-8 编码的输出的最大长度
  • 输出
    • QByteArray 输出 - utf-8 格式的原始文本比限制短。
  • 示例 1:
    • text = "你好吗?"
    • 限制 = 5
    • 输出 = “怎么样”
  • 示例 2:
    • text = "Как дела?"
    • 限制 = 5
    • 输出 = "Ка"
      • d0 9a d0 b0 - 包括“к”已经超过限制,包括 d0 会导致无效的 utf-8 字符串。

首先我们从下面的代码开始,但这可能会在中间切掉 UTF-8 字符,这是不可接受的:

QByteArray output = text.toUtf8().left(limit);

我们开发了正确的算法,该算法有效,但非常丑陋且效率不高:

QString tmp = input;
while (tmp.toUtf8().size() > limit)
    tmp.chop(1);
QByteArray output = tmp.toUtf8();
  • 有没有更好的方法,怎么做?
    • 如果是,请分享代码?
    • 如果不是,为什么?

【问题讨论】:

    标签: utf-8 qstring


    【解决方案1】:

    除非您想编写自己的 UTF-8 转换例程,否则以下方法应该是最佳的。它依赖于 UTF-8 序列中的连续字节在 0x80-0xBF 范围内的事实。从限制后退,它会尝试找到第一个起始字节,在该起始字节处可以安全地拆分字符串。

    QByteArray output = tmp.toUtf8();
    if (output.size() > limit) {
        int truncateAt = 0;
        for (int i = limit; i > 0; i--) {
            if ((output[i] & 0xC0) != 0x80) {
                truncateAt = i;
                break;
            }
        }
        output.truncate(truncateAt);
    }
    

    由于 UTF-8 字节序列不超过 4 个字节,因此不应该花费超过 4 次循环迭代来找到正确的位置。

    【讨论】:

    • 您确定您的假设:“所有 UTF-8 字符都以 0-127 范围内的字节开头”。根据utf8-chartable.de/unicode-utf8-table.pl?start=1024,所有俄语字符都以 0xd0 开头,所以对于“Как дела?”和 5 你的算法将返回空字符串。
    • @RadekDostal 对不起,那是错误的。我编辑了答案。
    • 感谢您的信息。可惜没有直接的qt函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 2020-01-08
    • 2015-07-31
    • 2015-07-19
    相关资源
    最近更新 更多