मुझे लगता है कि मैं कुछ है कि काम करता है पाया।
def limit_bytesize(str, size)
str.encoding.name == 'UTF-8' or raise ArgumentError, "str must have UTF-8 encoding"
# Change to canonical unicode form (compose any decomposed characters).
# Works only if you're using active_support
str = str.mb_chars.compose.to_s if str.respond_to?(:mb_chars)
# Start with a string of the correct byte size, but
# with a possibly incomplete char at the end.
new_str = str.byteslice(0, size)
# We need to force_encoding from utf-8 to utf-8 so ruby will re-validate
# (idea from halfelf).
until new_str[-1].force_encoding('utf-8').valid_encoding?
# remove the invalid char
new_str = new_str.slice(0..-2)
end
new_str
end
उपयोग:
>> limit_bytesize("abc\u2014d", 4)
=> "abc"
>> limit_bytesize("abc\u2014d", 5)
=> "abc"
>> limit_bytesize("abc\u2014d", 6)
=> "abc—"
>> limit_bytesize("abc\u2014d", 7)
=> "abc—d"
अद्यतन ...
active_support बिना
विघटित व्यवहार:
>> limit_bytesize("abc\u0065\u0301d", 4)
=> "abce"
>> limit_bytesize("abc\u0065\u0301d", 5)
=> "abce"
>> limit_bytesize("abc\u0065\u0301d", 6)
=> "abcé"
>> limit_bytesize("abc\u0065\u0301d", 7)
=> "abcéd"
active_support साथ विघटित व्यवहार:
>> limit_bytesize("abc\u0065\u0301d", 4)
=> "abc"
>> limit_bytesize("abc\u0065\u0301d", 5)
=> "abcé"
>> limit_bytesize("abc\u0065\u0301d", 6)
=> "abcéd"
यह काम करता है, लेकिन क्या हुआ अगर स्ट्रिंग बहुत बड़ा है? एक समय में एक utf-8 char को हटाने के लिए यह बहुत अक्षम हो सकता है। – Kelvin
@ केल्विन उत्तर संपादित किया गया है। यह अब बहुत बेहतर होना चाहिए।चूंकि utf-8 char 6 बाइट से अधिक नहीं होगा, लूप जल्द ही समाप्त हो जाएगा। – halfelf
अपूर्ण लगता है - 's' नहीं बदला है। क्या आपको नई स्ट्रिंग प्राप्त करने के लिए 's2' पैक करना होगा? याद रखें कि आउटपुट भी utf-8 होना चाहिए। – Kelvin