كيفية تحويل صفيف بايت إلى سلسلة من القواسم المشتركة Lisp ؟

StackOverflow https://stackoverflow.com/questions/600070

  •  03-07-2019
  •  | 
  •  

سؤال

أنا أتصل مضحك API التي تقوم بإرجاع صفيف بايت, ولكن أريد نص تيار.هل هناك طريقة سهلة للحصول على نص تيار من صفيف بايت?الآن أنا فقط رمى معا:

(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 ، لذلك تفسير ذلك إما ASCII أو UTF-8 سيكون على ما يرام.أنا باستخدام Unicode-علم SBCL لكني أفضل محمول (حتى ASCII-فقط) حل SBCL-Unicode-واحدة محددة.

هل كانت مفيدة؟

المحلول

المرن-تيارات (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)

سيعود تيار أن يقرأ النص من البايت ناقلات

نصائح أخرى

هناك نوعان من المكتبات المحمولة لهذا التحويل:

  • المرن-تيارات سبق ذكرها في جواب آخر.

    هذه المكتبة هي أكبر و المزيد من الميزات, ولا سيما الموسعة تيارات.

  • بابل, مكتبة specificially على حرف ترميز وفك ترميز

    والميزة الرئيسية بابل على المرن تيارات السرعة.

للحصول على أفضل أداء ، استخدم بابل إذا كان لديه الميزات التي تحتاج إليها ، و العودة إلى المرن-تيارات خلاف ذلك.أقل من (slighly علمي) microbenchmark يوضح فرق السرعة.

هذه حالة اختبار ، بابل 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.
|#

إذا لم يكن لديك ما يدعو للقلق حول ترميز UTF-8 (أن, أساسا, يعني "عادي فقط ASCII") ، قد تكون قادرا على استخدام الخريطة:

(خريطة 'سلسلة #'رمز-شار #(72 101 108 108 111))

أقول اذهب مع المقترح flexistream أو بابل الحلول.

ولكن فقط للتأكد من اكتمالها و الاستفادة المستقبلية من قوقل وصوله الى هذه الصفحة أريد أن أذكر 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:
     *

SBCL يدعم ما يسمى الرمادي تيارات.هذه هي الموسعة تيارات على أساس كلوس دروس عامة وظائف.يمكنك إنشاء نص تيار فرعية أن يحصل الشخصيات من صفيف بايت.

حاول FORMAT وظيفة. (FORMAT NIL ...) إرجاع نتائج كسلسلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top