2011-07-16 12 views
21

मैं अमेज़ॅन एस 3 अपलोड के साथ काम कर रहा हूं और मुझे बहुत लंबे समय तक महत्वपूर्ण नामों में परेशानी हो रही है। एस 3 कुंजी की लंबाई को बाइट्स से सीमित करता है, न कि अक्षर।मैं पायथन में एक यूटीएफ -8 एन्कोडेड स्ट्रिंग की बाइट लंबाई कैसे निर्धारित कर सकता हूं?

डॉक्स से

:

एक प्रमुख के लिए नाम जिसका UTF-8 एन्कोडिंग 1024 बाइट्स लंबे ज्यादा से ज्यादा है यूनिकोड वर्णों का एक क्रम है।

मैं भी फ़ाइल के नाम में मेटाडेटा को एम्बेड करने का प्रयास है, इसलिए मैं (स्ट्रिंग अजगर का उपयोग कर यह सुनिश्चित करना की वर्तमान बाइट अवधि की गणना करने में सक्षम होना चाहिए मेटाडाटा कुंजी बहुत लंबी नहीं है जो मामले में मुझे एक अलग मेटाडाटा फ़ाइल का उपयोग करना होगा)।

मैं कैसे utf-8 इनकोडिंग स्ट्रिंग के बाइट लंबाई निर्धारित कर सकते हैं? दोबारा, मुझे चरित्र की लंबाई में दिलचस्पी नहीं है ... बल्कि वास्तविक बाइट लंबाई स्ट्रिंग को स्टोर करने के लिए उपयोग की जाती है। अजगर 2 में

उत्तर

36
def utf8len(s): 
    return len(s.encode('utf-8')) 

वर्क्स ठीक है और 3.

+1

धन्यवाद। http://rosettacode.org/wiki/String_length#Byte_Length_49 – user319862

8

स्ट्रिंग 'एनकोड' विधि का उपयोग करें एक चरित्र स्ट्रिंग से एक बाइट-स्ट्रिंग में बदलने के लिए है, तो सामान्य की तरह लेन() का उपयोग करें:

>>> s = u"¡Hola, mundo!"              
>>> len(s)                  
13 # characters                    
>>> len(s.encode('utf-8')) 
14 # bytes 
+0

बहुत सराहना की – user319862

+6

कृपया का उपयोग नहीं करते 'एक चर नाम के रूप में str': मैं भी एक वेबसाइट से पता चलता है कि आप यहाँ कई भाषाओं में यह करने के लिए कैसे मिल गया! इससे दुःख का कोई अंत नहीं होगा। –

4

स्ट्रिंग एन्कोडिंग और परिणाम पर len का उपयोग कर अच्छा काम करता है, के रूप में अन्य उत्तर से पता चला है। इस इष्टतम नहीं हो सकता है अगर आप बहुत बड़ी तार के साथ काम कर रहे हैं (मैं बड़े हालांकि 1024 बाइट्स पर विचार नहीं करते) - यह तार का एक थ्रो-दूर प्रतिलिपि का निर्माण करने की आवश्यकता है। यूटीएफ -8 की संरचना आपको प्रत्येक चरित्र की लंबाई को आसानी से एन्कोड किए बिना आसानी से प्राप्त करने की अनुमति देती है, हालांकि यह एक वर्ण को एन्कोड करना अभी भी आसान हो सकता है। मैं यहां दोनों विधियों को प्रस्तुत करता हूं, उन्हें एक ही परिणाम देना चाहिए।

def utf8_char_len_1(c): 
    codepoint = ord(c) 
    if codepoint <= 0x7f: 
     return 1 
    if codepoint <= 0x7ff: 
     return 2 
    if codepoint <= 0xffff: 
     return 3 
    if codepoint <= 0x10ffff: 
     return 4 
    raise ValueError('Invalid Unicode character: ' + hex(codepoint)) 

def utf8_char_len_2(c): 
    return len(c.encode('utf-8')) 

utf8_char_len = utf8_char_len_1 

def utf8len(s): 
    return sum(utf8_char_len(c) for c in s) 
+1

नोट 1000 UTF8 वर्णों की स्ट्रिंग पर 'के रूप में LEN (s.encode ('UTF8'))', कम से कम मेरे अजगर 3.3.2 पर एक प्रति इस रूप में लंबे समय 180X के बारे में लेता है नहीं कर के बदले में [उत्पन्न यहां कोड से] (http://stackoverflow.com/a/1477572/344821)। (यदि आप सी में वही एल्गोरिदम लिखा है तो यह तुलनीय गति का होगा।) – Dougal

+0

@Dougal, परीक्षण चलाने के लिए धन्यवाद। संभावित समाधान का मूल्यांकन करने के लिए यह उपयोगी जानकारी है। मुझे लगा कि यह धीमा हो सकता है, लेकिन परिमाण को नहीं पता था। क्या आपने दोनों संस्करणों को आजमाया? –

+1

'utf8_char_len_2' वाला संस्करण 'utf8_char_len_1' से धीमा 1.5x है। बेशक, हम हर मामले में एक मिलीसेकंड के तहत बात कर रहे हैं, इसलिए यदि आप इसे कुछ बार कर रहे हैं तो इससे कोई फर्क नहीं पड़ता: 2 μs/375 μs/600 μs। उस ने कहा, 1 किलो स्मृति की प्रतिलिपि भी किसी भी मायने रखती है। :) – Dougal

संबंधित मुद्दे