공통 LISP에서 바이트 배열을 문자열로 변환하는 방법은 무엇입니까?
-
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 ...)
결과를 문자열로 반환합니다.