Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CSV defun

37 views
Skip to first unread message

Mike

unread,
May 7, 2013, 4:30:52 PM5/7/13
to
I need a CSV routine. I wrote this:

(defun csv (line)
(with-input-from-string (input-stream line)
(loop for char = (read-char input-stream nil nil nil)
with token-list = '()
with in-quote = nil
with token = '()
while char
do (cond ((and (char= char #\") (eq in-quote nil)) ; a beginning quote
(setq in-quote t)) ; turn on inside a token
((and (char= char #\") (eq in-quote t)) ; and end quote
(progn
; append the current token to the token list
(setq token-list (push (concatenate 'string (nreverse token)) token-list))
(setq token '()) ; clear the token accumulator
(setq in-quote nil))) ; not inside a token
((and (char= char #\,) (eq in-quote nil)) ; a comma not inside quotes, ignore
nil) ; do nothing
(t (setq token (push char token)))) ; append char to the current token
finally (return (nreverse token-list))))) ; return the accumulated list of tokens

I'm posting to share.

Mike

tar...@google.com

unread,
May 7, 2013, 7:24:54 PM5/7/13
to
Several quick style observations:

1) "(eq in-quote t)" should be just "in-quote"
2) "(eq in-quote nil)" should probably be "(not in-quote)"
3) PUSH has the side effect of setting the place, so
"(setq token (push char token))" should be "(push char token)"
4) COND clauses have an implicit PROGN for multiple forms, so you don't need it.
5) Many programmers put the WITH clauses ahead of the FOR clause in the loop since they are only evaluated once at the start of the form and before any iterations.

Design notes:

1) I would make the CSV function take a stream as its input rather than a string. You could then call it with more general inputs.
2) I might also call your function something like READ-CSV-LINE.
3) Do you really want commas outside of quotes do nothing? Or should then be token terminators as well?

Finally, you might also just use a CSV reader library.
http://www.cliki.net/Data%20formats has a couple of libraries listed for parsing CSV files. I think there should also be some that are available via quick-lisp.




0 new messages