공통 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으로 해석하는 것은 괜찮을 것입니다. 나는 유니 코드 인식 SBCL을 사용하고 있지만 SBCL-Unicode 특이 적 솔루션에 대한 휴대용 (ascii-only) 솔루션을 선호합니다.

도움이 되었습니까?

해결책

Flexi-streams (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)

바이트 벡터에서 텍스트를 읽는 스트림을 반환합니다.

다른 팁

이 변환을위한 두 가지 휴대용 라이브러리가 있습니다.

  • Flexi-Streams는 이미 다른 답변에서 언급되었습니다.

    이 라이브러리는 오래되었으며 더 많은 기능, 특히 확장 가능한 스트림이 있습니다.

  • 바벨, 문자 인코딩 및 디코딩을위한 도서관

    Flexi-streams보다 Babel의 주요 장점은 속도입니다.

최상의 성능을 얻으려면 필요한 기능이있는 경우 Babel을 사용하고 그렇지 않으면 Flexi-Streams로 돌아갑니다. 속도 차이를 보여주는 (비과학적인) 마이크로 렌치 마크 아래.

이 테스트 사례의 경우 Babel은입니다 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 인코딩에 대해 걱정할 필요가 없다면 (본질적으로 "Plain ASCII"를 의미 함)지도를 사용할 수 있습니다.

(Map 'String #'Code-Char #(72 101 108 108 111))))

제안 된 Flexistream 또는 Babel 솔루션과 함께 간다고 말합니다.

그러나이 페이지에 도착하는 미래의 구글러의 완전성과 이점을 위해서는 SBCL의 SB-EXT를 언급하고 싶습니다 : Octets-to-String :

   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