【问题标题】:get length of string in UTF8获取 UTF8 字符串的长度
【发布时间】:2016-01-22 16:09:32
【问题描述】:

如何获取 UTF-8 编码形式(PHP 的 mb_strlen(.., 'UTF-8') 等效形式)字符串的长度(不是字节数)?

我尝试了string.characters.count,但它没有为某些字符(如表情符号)返回正确的长度。

例子:

let s = "✌????️"
print(s.characters.count) // prints 2, but should print 3.

【问题讨论】:

  • 您能否给出一些输入/输出组合,例如“abc”-> 3、“someUtf-8String”-> 123 来验证我们的解决方案!?
  • 您可以使用 string.utf8.count 获取 UTF-8 计数。您可以使用以下方法获取 UTF-8 代码单元数组:Array(string.utf8)。
  • @luk2302 添加了一个示例。
  • 请参阅developer.apple.com/swift/blog/?id=30,了解字符、Unicode 标量、UTF-16 和 UTF-8。

标签: ios swift


【解决方案1】:

您可以使用.utf8 属性访问字符串的UTF-8 编码。使用count 获取字符串中UTF-8 代码单元的数量:

let string = "\u{1f603}" // One of the smiley face emojis...

print(string.utf8.count) // prints "4"

根据您编辑的问题,您可能正在寻找的是用于编码字符串的UnicodeScalars 的数量。您可以使用 unicodeScalars 属性访问它:

let s = "✌?️"
print(s.unicodeScalars.count) // prints 3

每个人都感到困惑的原因是因为您最初的问题要求提供 UTF-8 编码形式的字符串长度。您真正想要的答案与 UTF-8 编码形式的字符串长度无关。

我认为您对 Unicode“扩展字形簇”、Unicode 代码点和可用于对 Unicode 代码点进行编码的各种编码(如 UTF-8)之间的区别感到困惑。

Swift 中的Character 表示 Unicode 所称的“扩展字形簇”。也就是说,它是一个单一的视觉字符,即使它是由多个 Unicode 码位组成的。

Unicode 代码点是一个单一的语言符号,它被赋予一个 32 位的值。两个或多个 Unicode 代码点可以组合创建一个 Character。在 Swift 中,Unicode 代码点由 UnicodeScalar 类型表示。

当需要存储字符串、通过 Internet 发送或将其转换为以字节表示的数据时,您必须决定如何对其进行编码。编码有很多种,最常见的可能是UTF-8,它将字符串编码为一系列UInt8值。

这只是三个概念之间差异的简要说明。这实际上是一个非常有趣的主题,如果您搜索其中一些术语,您会发现更多有用的信息。

【讨论】:

  • 我认为您误解了我的问题。我已经编辑了一个示例。
  • 您询问了如何获取 UTF-8 编码形式的字符串的长度。这与用于对其进行编码的字节数相同。如果这不是您要问的,请编辑您的问题。
  • 跟UTF-8没关系吧?我很困惑。我实际上正在寻找 PHP 的 mb_strlen(.., 'UTF-8') 等价物。
【解决方案2】:
let str = "ačŘ"
print("str has \(str.characters.count) characters") // 3
print("and \(str.utf8.count) bytes as encoded in UTF-8") // 5

更新(根据你的笔记)

let s = "✌?️"

let arr:[UInt8] = [226, 156, 140, 240, 159, 143, 191, 239, 184, 143]
var arrCchar = arr.map { (uint8) -> Int8 in
    Int8(bitPattern: uint8)
}
arrCchar += [0] // to be null terminated

let str = String.fromCString(&arrCchar)
print(str) // Optional("✌?️")
s == str // TRUE !!!!

按字符

s.characters.forEach { (c) -> () in
    let str = String(c)
    print(str.utf8.map{$0}, "which represents character: ", c)
    str.unicodeScalars.forEach({ (u) -> () in
        print("composed from unicode scalar(s): ", u.debugDescription)
    })
}
/*
[226, 156, 140] which represents character:  ✌
composed from unicode scalar(s):  "\u{270C}"
[240, 159, 143, 191, 239, 184, 143] which represents character:  ?️
composed from unicode scalar(s):  "\u{0001F3FF}"
composed from unicode scalar(s):  "\u{FE0F}"
*/ 

Unicode 中的每个字符都可以由一个或多个 Unicode 标量表示。 unicode 标量是字符或修饰符的唯一 21 位数字(和名称),例如 U+0061 表示小写拉丁字母 A("a"),或 U+1F425 表示正面小鸡 ("\U0001f425 ”)。 当将 Unicode 字符串写入文本文件或其他存储时,这些 un​​icode 标量会以几种 Unicode 定义的格式之一进行编码。每种格式都将字符串编码为称为代码单元的小块。其中包括 UTF-8 格式(将字符串编码为 8 位代码单元)和 UTF-16 格式(将字符串编码为 16 位代码单元)。

//复制自 Apple Developer swift 编程指南

【讨论】:

  • 我认为您误解了我的问题。我已经编辑了一个示例。
  • 让 s = "✌?️"; print(s.characters.count) // 2 ???至少在我的电脑上。试试 s.characters.forEach{ print($0) }。顺便说一下,如果用 UTF-8 编码,您的 s 有 10 个字节
  • 我不明白你在说什么。我知道它是 10 个字节。 .characters.count 打印 2 但我想要的值是 3。
  • 如果有 2 个字符,为什么要 3 个? :-)
  • 见罗马的回答!!! s.unicodeScalars.count 并查看有关字符、unicode 标量和字节之间区别的文档:-)
猜你喜欢
  • 1970-01-01
  • 2018-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多