Swift文字列から最大255個のUTF8コード単位の有効な部分文字列を取得しようとしています(データベースVARCHAR(255)
フィールドを格納できるという考えです)。データベース内のスウィフト文字列を合わせるVARCHAR(255)
部分文字列を取得する標準的な方法はこれです:
let string: String = "Hello world!"
let startIndex = string.startIndex
let endIndex = string.startIndex.advancedBy(255, limit: string.endIndex)
let databaseSubstring1 = string[startIndex..<endIndex]
しかし、明らかにそれは私のUTF8表現に255を超えるバイトが必要な場合があり、255文字の文字列を与えるだろう。
UTF8のために私はこれを書くことができます:
let utf8StartIndex = string.utf8.startIndex
let utf8EndIndex = utf8StartIndex.advancedBy(255, limit: string.utf8.endIndex)
let databaseSubstringUTF8View = name.utf8[utf8StartIndex..<utf8EndIndex]
let databaseSubstring2 = String(databaseSubstringUTF8View)
しかし、私は私のUTF8Viewが有効なUTF8シーケンスではないでしょう意味末尾の半分の文字を、持つことのリスクを実行します。 そして、databaseSubstring2
は、イニシャライザが失敗する可能性がある(public init?(_ utf8: String.UTF8View)
と定義されているため)オプションの文字列です。
最後に無効なUTF8コードポイントを取り除く方法が必要です。可能であれば、私がここでやろうとしていることをやり遂げる方法が必要です。
EDIT
は、データベースが文字を理解していることが判明したので、私はUTF8コード単位をカウントしようとしてはならないのではなく、データベースは(おそらく、データベースに依存します)私の文字列にカウントされますどのように多くの文字。
@OOPerによると、MySQLは文字をUTF-16コード単位としてカウントします。アイデアは(つまり、スウィフトが文字が何であるかを考えるものです)UTF-16コード単位を数えるが、最後から文字を削除することです
private func databaseStringForString(string: String, maxLength: Int = 255) -> String
{
// Start by clipping to 255 characters
let startIndex = string.startIndex
let endIndex = startIndex.advancedBy(maxLength, limit: string.endIndex)
var string = string[startIndex..<endIndex]
// Remove characters from the end one by one until we have less than
// the maximum number of UTF-16 code units
while (string.utf16.count > maxLength) {
let startIndex = string.startIndex
let endIndex = string.endIndex.advancedBy(-1, limit: startIndex)
string = string[startIndex..<endIndex]
}
return string
}
:私は、次の実装が出ています。
EDIT 2
それでも@OOPerによると、Posgresqlは、Unicodeスカラーなどの文字を数えるので、これはおそらく動作するはずです:私は私のコメントで書いたよう
private func databaseStringForString(string: String, maxLength: Int = 255) -> String
{
// Start by clipping to 255 characters
let startIndex = string.startIndex
let endIndex = startIndex.advancedBy(maxLength, limit: string.endIndex)
var string = string[startIndex..<endIndex]
// Remove characters from the end one by one until we have less than
// the maximum number of Unicode Scalars
while (string.unicodeScalars.count > maxLength) {
let startIndex = string.startIndex
let endIndex = string.endIndex.advancedBy(-1, limit: startIndex)
string = string[startIndex..<endIndex]
}
return string
}
を私は混乱している...あなたは結果が255 *文字になりたいん*、または255 *バイト*? – deceze
結果を 'VARCHAR(255)'に格納したいので、最大255バイトです。しかし、私は有効なUTF8シーケンスが欲しいので、それを少なくする必要があります。 – deadbeef
あなたはどのデータベースを使用していますか? MySQLの 'VARCHAR(255)'は、列のエンコーディングで255 *文字*を意味します。これは255バイトを超えることがあります。 – deceze