2009-06-09 11 views
23

निकटतम दावेदार जिन्हें मैं अब तक पा सकता हूं वे हैं YEnc (2%) और ASCII85 (25% ओवरहेड)। मुख्य रूप से इस तथ्य के आसपास YEnc के आसपास कुछ समस्याएं प्रतीत होती हैं कि यह 8-बिट वर्ण सेट का उपयोग करती है। जो एक और विचार की ओर जाता है: क्या यूटीएफ -8 चरित्र सेट के आधार पर टेक्स्ट एन्कोडिंग के लिए बाइनरी है?टेक्स्ट एन्कोडिंग के लिए सबसे कुशल बाइनरी क्या है?

+2

ध्यान दें कि yEnc पाठ में द्विआधारी परिवर्तित नहीं करता है, यह कुछ है कि समाचार प्रोटोकॉल (NNTP) है, जो जरूरी नहीं कि कोई वर्ण सेट आवश्यकताओं को पूरा नहीं करता है, अकेले है कि यह सभी प्रिंट करने योग्य हो जाएगा के साथ संगत है के लिए द्विआधारी धर्मान्तरित पाठ। –

उत्तर

0

प्रेरणा के लिए, आप the Twitter Image Encoding Challenge आउट करना चाहेंगे। यह 140 यूनिकोड वर्णों में जितना संभव हो उतना छवि जानकारी एन्कोडिंग के बारे में है। यह अनिवार्य रूप से आपके प्रश्न का एक हानिकारक संस्करण है जो विशेष रूप से छवि डेटा से जुड़ा हुआ है।

12

यह वास्तव में बाइनरी डेटा की प्रकृति, और आपके आउटपुट पर "टेक्स्ट" स्थानों की बाधाओं पर निर्भर करता है।

सबसे पहले, यदि आपका बाइनरी डेटा संपीड़ित नहीं है, तो एन्कोडिंग से पहले संपीड़न करने का प्रयास करें। हम तब मान सकते हैं कि 1/0 या व्यक्तिगत बाइट्स का वितरण कम या ज्यादा यादृच्छिक है।

अब: आपको टेक्स्ट की आवश्यकता क्यों है? आम तौर पर, ऐसा इसलिए होता है क्योंकि संचार चैनल सभी पात्रों को समान रूप से पारित नहीं करता है। जैसे आपको शुद्ध ASCII पाठ की आवश्यकता हो सकती है, जिसका प्रिंट करने योग्य वर्ण 0x20-0x7E से हैं। आपके पास खेलने के लिए 9 5 वर्ण हैं। प्रत्येक चरित्र सैद्धांतिक रूप से log2 (95) ~ = 6.57 बिट प्रति चरित्र एन्कोड कर सकते हैं। एक रूपांतरण को परिभाषित करना आसान है जो बहुत करीब आता है।

लेकिन: अगर आपको विभाजक चरित्र की आवश्यकता है तो क्या होगा? अब आपके पास केवल 94 वर्ण हैं, इसलिए एन्कोडिंग की पसंद वास्तव में आपकी आवश्यकताओं पर निर्भर करती है।

एक बेहद बेवकूफ उदाहरण लेने के लिए: यदि आपका चैनल बिना किसी समस्या के सभी 256 वर्णों को पास करता है, और आपको किसी भी विभाजक की आवश्यकता नहीं है, तो आप एक मामूली परिवर्तन लिख सकते हैं जो 100% दक्षता प्राप्त करता है। :-) पाठक के लिए अभ्यास के रूप में ऐसा कैसे किया जाता है।

यूटीएफ -8 मनमाने ढंग से एन्कोडेड बाइनरी डेटा के लिए एक अच्छा परिवहन नहीं है। यह केवल 14% ओवरहेड के साथ 0x01-0x7F मानों को परिवहन करने में सक्षम है। मुझे यकीन नहीं है कि 0x00 कानूनी है; संभावना नहीं है। लेकिन 0x80 से ऊपर कुछ भी यूटीएफ -8 में एकाधिक बाइट्स तक फैलता है। मैं यूटीएफ -8 को एक बाधित चैनल के रूप में मानता हूं जो 0x01-0x7F, या 126 अद्वितीय वर्णों को पास करता है। यदि आपको डिलीमीटर की आवश्यकता नहीं है तो आप प्रति चरित्र 6.98 बिट्स प्रेषित कर सकते हैं।

इस समस्या का एक सामान्य समाधान: एन अक्षरों का वर्णमाला मानें जिनके बाइनरी एन्कोडिंग 0 से एन -1 हैं। (यदि एन्कोडिंग के रूप में नहीं माना जाता है, तो हमारे इंटरमीडिएट 0..एन -1 प्रतिनिधित्व और जो आप वास्तव में भेजते हैं और प्राप्त करते हैं, उसके बीच अनुवाद करने के लिए एक लुकअप टेबल का उपयोग करें।)

वर्णमाला में 95 वर्ण मानें। अब: इनमें से कुछ प्रतीक 6 बिट्स का प्रतिनिधित्व करेंगे, और कुछ 7 बिट्स का प्रतिनिधित्व करेंगे। अगर हमारे पास 6-बिट प्रतीक और बी 7-बिट प्रतीकों हैं, तो:

ए + बी = 9 5 (प्रतीकों की कुल संख्या) 2 ए + बी = 128 (7-बिट उपसर्गों की कुल संख्या आप 6-बिट प्रतीक के साथ 2 उपसर्गों को शुरू कर सकते हैं, या 7-बिट प्रतीक वाला एक।)

सिस्टम को हल करना, आपको मिलता है: ए = 33, बी = 62। अब आप प्रतीकों की एक तालिका बनाते हैं:

 
Raw  Encoded 
000000 0000000 
000001 0000001 
... 
100000 0100000 
1000010 0100001 
1000011 0100010 
... 
1111110 1011101 
1111111 1011110 

एन्कोड करने के लिए, पहले इनपुट के 6 बिट्स को बंद करें। यदि उन छह बिट्स 100001 के बराबर या बराबर हैं तो एक और बिट बदलें। फिर संबंधित 7-बिट आउटपुट कोड देखें, आउटपुट स्पेस में फिट करने के लिए अनुवाद करें और भेजें। आप प्रत्येक पुनरावृत्ति इनपुट के 6 या 7 बिट्स स्थानांतरित करेंगे।

डीकोड करने के लिए, बाइट स्वीकार करें और कच्चे आउटपुट कोड में अनुवाद करें। यदि कच्चा कोड 0100001 से कम है तो अपने आउटपुट पर संबंधित 6 बिट्स को स्थानांतरित करें। अन्यथा अपने आउटपुट पर संबंधित 7 बिट्स को स्थानांतरित करें।आप प्रत्येक पुनरावृत्ति के उत्पादन के 6-7 बिट उत्पन्न करेंगे।

समान रूप से वितरित डेटा के लिए मुझे लगता है कि यह इष्टतम है। यदि आप जानते हैं कि आपके स्रोत में आपके से अधिक शून्य हैं, तो आप अंतरिक्ष की शुरुआत में 7-बिट कोड मैप करना चाहेंगे ताकि यह अधिक संभावना हो कि आप 7-बिट कोड का उपयोग कर सकें।

1

लगता है जैसे आपके पास पहले से ही जवाब है, मार्क। यूटीएफ -8 एक बाइनरी एन्कोडिंग के रूप में उपयोगी नहीं है क्योंकि किसी भी यूटीएफ -8 वर्ण में एक बाइट से बड़ा 25% ओवरहेड होता है, यहां तक ​​कि टेक्स्ट (2 या अधिक बिट्स प्रति बाइट) स्टोर करने के लिए भी। Base64 एन्कोडिंग पहले से ही बेहतर हैं।

+1

बेस 64 एन्कोडिंग ASCII के साथ संगत है, और यूटीएफ -8 मानचित्रों को '7 एफ' हेक्स के तहत किसी भी चरित्र के लिए ASCII के लिए, यूटीएफ -8 में कम से कम * आधार 64 के समान घनत्व है। उसने कहा, वास्तव में घने एन्कोडिंग के लिए, 8 बिट एन्कोडिंग जैसे कि [विंडोज -1252] (http://en.wikipedia.org/wiki/Windows-1252) एक बेहतर विचार हो सकता है। –

+0

यहां तक ​​कि विंडोज़ -1252 या आईएसओ -885 9 -1 एन्कोडिंग को कई परिस्थितियों में यूटीएफ -8 में परिवर्तित किया जाएगा, जिससे डेटा बढ़ रहा है। एक कुशल यूटीएफ -8 एन्कोडिंग को यूटीएफ -8 चरित्र प्रति एकाधिक बाइट्स का प्रतिनिधित्व करना होगा। [बेस 32768] (https://github.com/qntm/base32768) इस पर एक प्रयास है। – bryc

+0

स्पष्ट रूप से मेरा बिंदु, मार्टिन, यह है कि आप ** multibyte ** UTF-8 एन्कोडिंग की तुलना में बेस 64 का उपयोग करना बेहतर कर रहे हैं। अगर मैं एएससीआईआईआई के बारे में बात कर रहा था तो मैंने ** एएससीआईआई ** कहा होगा। यह सुझाव देने के लिए कि मैं गलत हूं क्योंकि बेस 64 यूटीएफ -8 का उप-समूह केवल व्यर्थ बाइकिंग है। – Qwertie

6

Wikipedia के अनुसार, "। basE91 संकुचित 8 बिट द्विआधारी इनपुट के लिए कम से कम सादे ASCII उत्पादन का उत्पादन"

+0

बेसई 9 1 बेस 64 और जेड 85 से अधिक कुशल है। लेकिन एचटीएमएल में अपना आउटपुट प्रदर्शित करते समय सावधान रहें। यह वर्णों का उपयोग करता है (<, >, और) जो बच जाना चाहिए (Z85 भी इस समस्या है)। – bryc

1

अगला Wikipedia पर सूचीबद्ध करने के लिए, वहाँ Bommanews है:

बी न्यूज (या बॉम्मन्यूज) को यूएनएनकोड और बेस 64 एन्कोडिंग के निहित ओवरहेड के वजन को उठाने के लिए विकसित किया गया था: यह टेक्स्ट संदेशों में बाइनरी डेटा को भरने के लिए एक नई एन्कोडिंग विधि का उपयोग करता है। यह विधि अधिक CPU संसाधनों को खाती है, लेकिन यह यूएनएनकोड के लिए लगभग 40% से हानि को कम करने का प्रबंधन करती है 3.5% (उन अंकों के बीच दशमलव बिंदु आपके मॉनिटर पर गंदगी नहीं है), जबकि संदेश में एएनएसआई नियंत्रण कोड के उपयोग से बचते हुए तन।

यह yEnc करने के लिए तुलनीय है: source

yEnc बी समाचार से भी कम समय CPU- सघन है और भूमि के ऊपर का एक ही निम्न स्तर के बारे में पहुंचता है, लेकिन यह सब नियंत्रण कोड के उपयोग से बचने नहीं करता है , यह उन लोगों को छोड़ देता है जो (प्रयोगात्मक) कुछ सर्वरों पर अवांछित प्रभाव डालने के लिए मनाए गए थे, जिसका अर्थ है कि यह बी-न्यूज की तुलना में कुछ कम आरएफसी अनुपालन करता है।

+1

बोमैन्यूज़ के एफएक्यू में नहीं जाते हैं कि किस चरित्र-एन्कोडिंग का समर्थन किया जाता है। मैं सबसे 8 बिट कोड पेज मानता हूं, हालांकि '7 एफ' मौजूद हो सकता है, और * यह एक नियंत्रण कोड * है उदा। आईबीएम OEM चरित्र सेट में। विंडोज कोड पेजों में भी '81',' 8 डी', '8 एफ', '9 0', और' 9 डी 'नियंत्रण वर्ण हैं। इस स्टफ को प्रिंट करते समय सावधान रहें, क्योंकि डेटा * खो जाएगा। –

+0

@ मार्टन: बी-न्यूज़ ने 0x20 - 0xFF वर्णों का उपयोग किया। प्रत्येक चरित्र आधार -224 संख्या का एक अंक था, 0x20 द्वारा ऑफ़सेट किया गया था। "टेक्स्ट" की प्रत्येक पंक्ति एक बड़ी संख्या थी जिसे डीकोडिंग और एन्कोडिंग प्रक्रिया में बाइनरी से परिवर्तित किया गया था। येनक लगभग 0x00 से 0xFF रेंज का उपयोग करता है, बाइनरी इनपुट में प्रत्येक बाइट केवल टेक्स्ट आउटपुट में कॉपी किया जाता है, केवल 0x00, 0x0A और 0x0D से बचता है (और बचने वाला चरित्र स्वयं, जो मुझे बिल्कुल याद नहीं है)। –

+0

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

8

संक्षिप्त उत्तर होगा: नहीं, अभी भी नहीं है।

मैं जेएसओएन स्ट्रिंग में जितनी अधिक जानकारी एन्कोडिंग के साथ समस्या में भाग गया, जिसका मतलब यूटीएफ -8 नियंत्रण वर्णों, बैकस्लैश और उद्धरण के बिना है।

मैं बाहर गया और शोध किया कि आप वैध यूटीएफ -8 बाइट्स में कितनी बिट निचोड़ सकते हैं। मैं जवाब देने से असहमत हूं कि यूटीएफ -8 बहुत ज्यादा उपर लाता है। यह सच नहीं है।

यदि आप केवल एक-बाइट अनुक्रमों को ध्यान में रखते हैं, तो यह मानक ASCII के रूप में शक्तिशाली है। मतलब बाइट प्रति 7 बिट्स। लेकिन अगर आप सभी विशेष पात्रों को काटते हैं तो आपको Ascii85 जैसे कुछ के साथ छोड़ा जाएगा।

लेकिन उच्च विमानों में कम नियंत्रण वर्ण हैं। तो यदि आप 6-बाइट भाग का उपयोग करते हैं तो आप 5 बाइट प्रति खंड को एन्कोड करने में सक्षम होंगे। आउटपुट में आपको किसी भी लंबाई (1 से 6 बाइट्स के लिए) के यूटीएफ -8 अक्षरों का कोई संयोजन मिलेगा।

यह आपको 4/5 के बजाय Ascii85: 5/6, 80% की बजाय 83% दक्षता से बेहतर परिणाम देगा। सिद्धांत रूप में यह उच्च चंक लंबाई के साथ भी बेहतर होगा: लगभग 84% 1 9-बाइट भागों में।

मेरी राय में एन्कोडिंग प्रक्रिया बहुत जटिल हो जाती है जबकि यह बहुत कम लाभ प्रदान करती है। तो Ascii85 या इसके कुछ संशोधित संस्करण (मैं अब Z85 देख रहा हूं) बेहतर होगा।

6

मैंने पिछले साल टेक्स्ट एन्कोडिंग के लिए सबसे कुशल बाइनरी की खोज की थी। मुझे अपने लिए एहसास हुआ कि कॉम्पैक्टनेस एकमात्र मानदंड नहीं है। सबसे महत्वपूर्ण यह है कि आप एन्कोडेड स्ट्रिंग का उपयोग करने में सक्षम हैं। उदाहरण के लिए, yEnc में 2% ओवरहेड है, लेकिन यह 8-बिट एन्कोडिंग है, इसलिए इसका उपयोग बहुत सीमित है।

मेरी पसंद Z85 है। इसमें 25% ओवरहेड स्वीकार्य है, और एन्कोडेड स्ट्रिंग का लगभग हर जगह उपयोग किया जा सकता है: एक्सएमएल, जेएसओएन, सोर्स कोड इत्यादि। विवरण के लिए Z85 specification देखें।

अंत में, मैंने सी/सी ++ में Z85 library लिखा है और इसे उत्पादन में उपयोग किया है।

-1

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

//buff is a unsigned character array containing the binary data 
//N is the number of bytes to be encoded 
string simple_encode(unsigned char *buff, int N) 
{ 
    string sEncode = ""; 
    for(int i = 0; i<N; i++) 
    { 
     sEncode += (97 + (buff[i] >> 4)); 
     sEncode += (97 + (buff[i] & 0x0F)); 
    } 
    return sEncode; 
} 

//sbuff is a string containing the encoded ascii data 
//szDecoded is an unsigned char array that has been allocated to 1/2 
//the length of sbuff 
//N is an integer pointer and returns the number of converted bytes 
void simple_decode(string sbuff, unsigned char *szDecode, int *N) 
{ 
    *N = sbuff.length()/2; 
    for(int i=0; i < *N; i++) 
    { 
     szDecode[i] = ((sbuff.at(2*i)-97) << 4) + (sbuff.at(2*i+1)-97); 
    } 
} 
+0

सवाल कम से कम ओवरहेड के साथ कुछ प्रस्तुत करना था। आपका एन्कोडिंग, जो मूल रूप से एक अलग वर्णमाला वाले हेक्साडेसिमल है, में 100% का ओवरहेड होता है। टेबल लुकअप या अतिरिक्त ब्रांचिंग स्टेटमेंट के बिना हेक्साडेसिमल एन्कोडिंग करना भी संभव है।ठीक है, यह नरक के रूप में बदसूरत है, लेकिन यह कम से कम एक मानक का पालन करता है। –

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