2009-03-01 12 views
19

मैं एक मजेदार एपीआई कॉल कर रहा हूं जो बाइट सरणी देता है, लेकिन मुझे एक टेक्स्ट स्ट्रीम चाहिए। क्या बाइट सरणी से टेक्स्ट स्ट्रीम प्राप्त करने का कोई आसान तरीका है? अभी के लिए मैं सिर्फ एक साथ फेंक दिया:सामान्य लिस्प में स्ट्रिंग से बाइट सरणी को कैसे परिवर्तित करें?

(defun bytearray-to-string (bytes) 
    (let ((str (make-string (length bytes)))) 
    (loop for byte across bytes 
     for i from 0 
     do (setf (aref str i) (code-char byte))) 
    str)) 

और उसके बाद में परिणाम लपेट के साथ-इनपुट-से-स्ट्रिंग, लेकिन यह सबसे अच्छा तरीका है नहीं हो सकता। (इसके अलावा, यह बेहद अक्षम है।)

इस मामले में, मुझे पता है कि यह हमेशा ASCII है, इसलिए इसे एएससीआईआई या यूटीएफ -8 के रूप में व्याख्या करना ठीक होगा। मैं यूनिकोड-जागरूक एसबीसीएल का उपयोग कर रहा हूं, लेकिन मैं एक एसबीसीएल-यूनिकोड-विशिष्ट एक के लिए एक पोर्टेबल (यहां तक ​​कि ASCII- केवल) समाधान पसंद करूंगा।

उत्तर

27

फ्लेक्सी-स्ट्रीम (http://weitz.de/flexi-streams/) पोर्टेबल रूपांतरण समारोह

(flexi-streams:octets-to-string #(72 101 108 108 111) :external-format :utf-8) 

=> 

"Hello" 

है या, यदि आप एक धारा हैं:

(flexi-streams:make-flexi-stream 
    (flexi-streams:make-in-memory-input-stream 
     #(72 101 108 108 111)) 
    :external-format :utf-8) 

एक धारा है कि बाइट-वेक्टर से पाठ पढ़ता वापस आ जाएगी

0

FORMAT फ़ंक्शन का प्रयास करें। (FORMAT NIL ...) परिणाम को स्ट्रिंग के रूप में लौटाता है।

+0

यह सच है, लेकिन यह अभी भी एक बनाने होगी मध्यवर्ती स्ट्रिंग। मैं ऐसे समाधान की उम्मीद कर रहा हूं जो ओ (एन) अधिक स्टोरेज के बिना स्ट्रीम में मौजूदा बाइट सरणी को लपेट सके। मुझे लगता है कि मेरा शीर्षक बहुत अच्छा नहीं था। :-) – Ken

4

एसबीसीएल तथाकथित Gray Streams का समर्थन करता है। ये सीएलओएस कक्षाओं और जेनेरिक कार्यों के आधार पर एक्स्टेंसिबल स्ट्रीम हैं। आप एक टेक्स्ट स्ट्रीम सबक्लास बना सकते हैं जो बाइट सरणी से वर्ण प्राप्त करता है।

23

इस रूपांतरण के लिए दो पोर्टेबल पुस्तकालय हैं:

  • flexi-streams, पहले से ही किसी अन्य उत्तर में वर्णित है।

    यह लाइब्रेरी पुरानी है और विशेष रूप से एक्स्टेंसिबल स्ट्रीम में अधिक सुविधाएं हैं।

  • Babel, चरित्र एन्कोडिंग और डिकोडिंग

    के लिए specificially एक पुस्तकालय फ्लेक्सी-धाराओं से अधिक कोलाहल का मुख्य लाभ यह गति है।

सर्वोत्तम प्रदर्शन के लिए, यदि आपके पास आवश्यक सुविधाएं हैं, तो बैबेल का उपयोग करें और अन्यथा flexi-streams पर वापस आ जाएं। गति अंतर को चित्रित करने वाला एक (कठोर अवैज्ञानिक) माइक्रोबेंमार्क नीचे।

इस परीक्षण के मामले में, बेबेल 337 गुना तेज और 200 गुना कम स्मृति की आवश्यकता है।

(asdf:operate 'asdf:load-op :flexi-streams) 
(asdf:operate 'asdf:load-op :babel) 

(defun flexi-streams-test (bytes n) 
    (loop 
    repeat n 
    collect (flexi-streams:octets-to-string bytes :external-format :utf-8))) 

(defun babel-test (bytes n) 
    (loop 
    repeat n 
    collect (babel:octets-to-string bytes :encoding :utf-8))) 

(defun test (&optional (data #(72 101 108 108 111)) 
         (n 10000)) 
    (let* ((ub8-vector (coerce data '(simple-array (unsigned-byte 8) (*)))) 
     (result1 (time (flexi-streams-test ub8-vector n))) 
     (result2 (time (babel-test ub8-vector n)))) 
    (assert (equal result1 result2)))) 

#| 
CL-USER> (test) 
Evaluation took: 
    1.348 seconds of real time 
    1.328083 seconds of user run time 
    0.020002 seconds of system run time 
    [Run times include 0.12 seconds GC run time.] 
    0 calls to %EVAL 
    0 page faults and 
    126,402,160 bytes consed. 
Evaluation took: 
    0.004 seconds of real time 
    0.004 seconds of user run time 
    0.0 seconds of system run time 
    0 calls to %EVAL 
    0 page faults and 
    635,232 bytes consed. 
|# 
14

आप के बारे में UTF-8 एन्कोडिंग (जो अनिवार्य रूप से, "बस सादे ASCII" का अर्थ है) चिंता करने की ज़रूरत नहीं है, तो आप नक्शे उपयोग करने में सक्षम हो सकता है:

(नक्शा 'स्ट्रिंग # 'कोड-चार # (72 101 108 108 111))
+2

अच्छा समाधान जो आउट-ऑफ-द-बॉक्स कॉमन लिस्प पर काम करता है :) – Olie

+0

आपके लिस्प सिस्टम के यूटीएफ -8 समर्थन के आधार पर, यह यूटीएफ -8 के लिए भी काम कर सकता है। उदाहरण के लिए, एसबीसीएल और सीसीएल समर्थन utf-8 अब। पोर्टेबिलिटी एक और मामला है ... – vancan1ty

+2

@ vancan1ty नहीं, यह यूटीएफ -8 के लिए काम नहीं करता है। उदाहरण के लिए, '206 177' यूटीएफ -8 में' α "' एन्कोड करता है, लेकिन '(प्रिंस (नक्शा 'स्ट्रिंग #' कोड-चार # (206 177))) एसबीसीएल में' returns ± "' रिटर्न '। –

4

मैं प्रस्तावित फ्लेक्सिस्ट्रीम या बेबेल समाधान के साथ जाता हूं।

लेकिन अभी पूर्णता और भविष्य इस पेज पर पहुंचने Googlers मैं SBCL के अपने sb-ext उल्लेख करना चाहते हैं के लाभ के लिए: ओक्टेट्स-से-स्ट्रिंग:

SB-EXT:OCTETS-TO-STRING is an external symbol in #<PACKAGE "SB-EXT">. 
    Function: #<FUNCTION SB-EXT:OCTETS-TO-STRING> 
    Its associated name (as in FUNCTION-LAMBDA-EXPRESSION) is 
    SB-EXT:OCTETS-TO-STRING. 
    The function's arguments are: (VECTOR &KEY (EXTERNAL-FORMAT DEFAULT) (START 0) 
              END) 
    Its defined argument types are: 
    ((VECTOR (UNSIGNED-BYTE 8)) &KEY (:EXTERNAL-FORMAT T) (:START T) (:END T)) 
    Its result type is: 
    * 
+0

"भविष्य के googlers का लाभ": आठ साल बाद यहां भविष्य लाभार्थी। (डकडकगो, लेकिन हे) –

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