2012-11-15 5 views
2

객체 내에 종료되고, 그래서 코드 작성 :입력 스트림은 내가 플랫 파일의 행 수를 계산하려면

*** - READ: input stream 
     #<INPUT BUFFERED FILE-STREAM CHARACTER #P"/home/lambda/Documents/flatfile" 
     @4> 
     ends within an object 

월 :

(defun ff-rows (dir file) 
    (with-open-file (str (make-pathname :name file 
             :directory dir) 
             :direction :input) 
    (let ((rownum 0)) 
     (do ((line (read-line str file nil 'eof) 
       (read-line str file nil 'eof))) 
      ((eql line 'eof) rownum) 
     (incf rownum))))) 

그러나 나는 오류를 문제가 무엇인지 묻습니다. 나는 행 수를 세어 보았습니다. 이 작업은 괜찮습니다.

참고 : 여기 기능을 테스트하는 데 사용되는 플랫 파일의 내용입니다 : 당신은 그때 내가 더 현학적 인 경우 물론 지금

2 3 4 6 2 
1 2 3 1 2 
2 3 4 1 6 

답변

4

조금 짧습니다.

(defun ff-rows (dir file) 
    (with-open-file (stream (make-pathname :name file 
             :directory dir) 
          :direction :input) 
    (loop for line = (read-line stream nil nil) 
      while line count line))) 

READ-LINE에 대한 인수가 필요합니다. 첫 번째는 스트림입니다. 파일은 매개 변수 목록에 포함되어 있지 않습니다.

일반적으로 일반적인 Lisp 함수에 경로 이름 처리를 혼합하는 것은 좋지 않습니다.

(defun ff-rows (pathname) 
    (with-open-file (stream pathname :direction :input) 
    (loop for line = (read-line stream nil nil) 
      while line count line))) 

다른 기능 또는 다른 코드에서 경로 이름 처리를 수행하십시오. 경로명 구성 요소를 함수에 전달하는 것은 일반적으로 잘못된 설계입니다. 완전한 경로 이름을 전달하십시오.

는 LispWorks 파일 선택기를 사용하여 모든 기본 I/O 기능이 경로 이름을 스트림 작업, 그리고 때

CL-USER 2 > (ff-rows (capi:prompt-for-file "some file")) 
27955 

더 나은

이다. 따라서 네트워크 스트림, 직렬 회선 또는 다른 스트림에서 회선을 셀 수 있습니다.

+0

대단히 감사합니다. 경로 이름을 별도로 처리해야합니다. – category

+0

파일과 디렉토리를'ff-rows'에 전달하는 것이 더 깔끔해 보입니다. 사용자가 자연스럽게 그러한 함수에 전달할 것이기 때문입니다. 그러나 이것이 잘못된 설계 인 것을 볼 수 있습니다.내가 잘못된 디자인처럼 보이는 경로 이름을 생성하도록 사용자에게 요청하면. 그래서 pathname을 만들고'ff-rows'를 실행하는 함수를 정의 할 수 있습니다. 그런 다음 다른 함수에서 pathname 컴포넌트를 처리 할 차례입니다. – category

1
(defun ff-rows (dir file) 
    (with-open-file 
     (str (make-pathname :name file :directory dir) 
      :direction :input) 
    (let ((result 0)) 
     (handler-case 
      (loop (progn (incf result) (read-line str))) 
     (end-of-file() (1- result)) 
     (error() result))))) 

을, 당신은 지정한 수 있는지 일종의 오류를 정확하게 처리하고 싶지만, 간단한 예를 들어 설명하면됩니다.

EDIT : @Moritz가 질문에 더 잘 대답했다고 생각하지만, 여전히이를 피하려고하는 대신 read-line이 던진 오류를 사용하는 방법의 예가 될 수 있습니다.

+0

감사합니다. 특히, 'handler-case'및'end-of-file '함수를 살펴 보겠습니다. – category

+0

이 경우 조건 처리가 매우 좋은 생각이라고 생각하지 않습니다. –

4

내가 말할 수있는 한 문제는 (read-line ...) 호출에서 "파일"입니다. hyperspec 기준

판독 라인의 서명은 다음

read-line &optional input-stream eof-error-p eof-value recursive-p 
=> line, missing-newline-p 

... "파일"EOF "로서 EOF 값 전무, EOF 오류-P로 해석되는 것을 의미 재귀 적 p로서. 말할 필요도없이 문제가 발생합니다. 읽음 통화 (예 : (read-line str nil :eof))에서 '파일'을 삭제하면 코드가 내 컴퓨터 (AllegroCL & LispWorks)에서 추가 수정없이 정상적으로 실행됩니다.

+0

고마워, 나는 내가 틀린 장소에서 그것을 타이프하고 있었다라고 생각한다 - 나는 다음 시간에 더주의 할 것이다. – category

관련 문제