什么是C函数fread的Common Lisp等价物?

时间:2015-05-20 23:47:06

标签: c opengl common-lisp fread sbcl

我试图将一些C代码移植到Common Lisp(细节可能无关紧要,但我试图将rgb图像文件读入内存块以绑定纹理以便与cl-opengl一起使用)。我试图做的C版本是:

void * data;
FILE * file;
int bytecount = width * height * 3;
file = fopen ( rgbfilepath, "rb" );
data = malloc( bytecount );
fread( data, bytecount, file);
fclose( file );
//do stuff with data...

我这样做已经有几年了,但是我对这段代码的理解是,它正在从文件中读取一堆字节到malloc内存中而没有对内容进行任何关注那些字节。

经过一些谷歌搜索,我发现http://rosettacode.org/wiki/Read_entire_file#Common_Lisphttp://www.codecodex.com/wiki/Read_a_file_into_a_byte_array#Common_Lisp非常相似。我的版本看起来像

(with-open-file (stream rgb-file-path)
  (let ((data (make-string (file-length stream)))
    (read-sequence data stream)
    ;;do stuff with data...

当我在rgb文件上运行此内容时,我收到SBCL的以下投诉:

debugger invoked on a SB-INT:STREAM-DECODING-ERROR in thread
#<THREAD "main thread" RUNNING {10055E6EA3}>:
  :UTF-8 stream decoding error on
  #<SB-SYS:FD-STREAM
  for "file /home/john/code/lisp/commonlisp/opengl-practice/wall.rgb"
    {1005A8EB53}>:

    the octet sequence #(218 0) cannot be decoded.

我对此的推测性解释是make-string的使用期望字节是字符,而我加载的rgb文件只有一堆字节,不一定是有效的ASCII或预期的任何字符集。但我可能会离开。有关如何复制fread()的内容的任何建议吗?

提前致谢!

2 个答案:

答案 0 :(得分:0)

如果你真的想要这样做,你需要指定element-typeopen(或with-open-file)这是integer的子类型(很可能是某种东西)与'(unsigned-byte 8)类似,因此它被读作八位字节而不是字符。

但是,我会使用库来读取图像。我过去使用过opticl,它非常简单,使用二维或三维简单数组来表示图像数据(两个维度加一个颜色)。

答案 1 :(得分:0)

非常感谢Svante带领我朝着正确的方向前进。这是有用的:

(setf mystream (open rgb-file-name :direction :input :element-type '(unsigned-byte 8)))
(setf data (make-array (file-length mystream) :element-type '(unsigned-byte 8)))
(read-sequence data mystream)
(close mystream)