SqueakByExample:10.4: Difference between revisions

From 흡혈양파의 번역工房
Jump to navigation Jump to search
(SBE 파일접근을위해스트림사용하기 페이지 추가)
 
(번역숮어)
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
==파일 접근(file access)를 위해 스트림 사용하기==
==파일 접근에 대한 stream 의 활용==


여러분은 이미 구성요소들의 컬렉션들에 스트림을 시행하는 법을 보셨습니다. 여러분의 하드 디스크에 있는 파일들에, 스트림을 시행하는 것 또한 가능합니다. 스트림은 일단 만들어지면, 파일에 있는 스트림은 컬렉션에 있는 스트림과 매우 유사합니다: 여러분은 읽기, 쓰기 또는 스트림의 위치를 선정하기 위해 동일한 프토콜을 사용하실 있을 것입니다. 우리가 지금 볼 내용처럼 파일 스트림을 만드는 여러 가지 다른 방법들이 있습니다.  
컬렉션을 stream 으로 처리하는 방법은 이미 배웠습니다. 동일한 방법으로 하드디스크에 있는 파일도 stream 으로 처리할 수 있습니다. 일단 만들어지만, 파일에 대한 stream 은 콜렉션에 대한 stream 과 거의 비슷합니다: 같은 프로토콜을 이용해서 stream 에 대한 읽기, 쓰기, 위치결정 등의 작업을 할 있습니다. 가장 큰 차이는 stream 을 만드는 방법에 있습니다. 파일에 대한 stream 을 만드는 방법에 대해서, 몇가지 서로 다른 방법을 살펴보겠습니다.




===파일 스트림 만들기===


파일 스트림을 만들려면, 클래스 FileStream에 의해 제공된 다음 인스턴스 생성 메소드들 중의 하나를 사용해야만 할 것입니다:
===파일 stream 만들기===


'''fileNamed:''' 읽기와 쓰기를 위해 주어진 이름으로 파일을 엽니다. 만약 파일이 이미 존재하면, 그 파일의 이전 컨텐츠는 아마도 수정되었거나 대체되었을 것이지만, 파일은 닫을 때 불완전 형태가 되지 않을 것입니다. 만약 그 이름이(the name) 아무 디렉토리 일부를 갖고 있지 않으면, 파일은 디폴트 디렉토리에서 생성될 것입니다.
파일 stream 을 만들기 위해서는, FileStream 클래스 에서 제공되는 아래의 인스턴스 생성 메서드들 중 하나를 반드시 사용해야 합니다:


'''newFileNamed:''' 주어진 이름으로 새로운 파일을 만들고, 그 파일에 쓰기를 위해 열린 스트림을 답변으로 내놓습니다. 만약 파일이 이미 존재한다면, 유저에게 해야할 일을 요청합니다.  
'''fileNamed:''' 주어진 이름으로 파일을 읽기, 쓰기 작업을 위해서 open 힙니다. 만약 파일이 이미 존재하는 경우, 이전의 내용은 변경하거나 옮기는게 가능합니다만, close 하는 경우 파일이 불완전한 상태가 되지는 않습니다. 만약 인수로 받은 이름에 별도로 디렉토리에 대한 내용이 포함되어있지 않다면 파일은 기본디렉토리에서 생성됩니다.  


'''forceNewFileNamed:''' 주어진 이름으로 새로운 파일을 만들고, 그 파일에 쓰기를 위해 열린 스트림을 답변으로 내놓습니다. 만약 파일이 이미 존재한다면, 새로운 파일을 만들기 전에 요청(질문) 없이 그 파일을 지웁니다.  
'''newFileNamed:''' 주어진 이름으로 새로운 파일을 만들고, 그 파일에 대해 쓰기 작업을 위한 stream 을 반환합니다. 만약 파일이 이미 존재한다면, 유저에게 해야할 일을 요청합니다.  


'''oldFileNamed:''' 읽기와 쓰기를 위해 주어진 이름으로 파일을 엽니다. 만약 파일이 이미 존재하면, 그 파일의 이전 컨텐츠는 아마도 수정되었거나 대체되었을 것이지만, 파일은 닫을 때 불완전 형태가 되지 않을 것입니다. 만약 그 이름이(the name) 아무 디렉토리 일부를 갖고 있지 않으면, 파일은 디폴트 디렉토리에서 생성될 것입니다.  
'''forceNewFileNamed:''' 주어진 이름으로 새로운 파일을 만들고, 그 파일에 대해 쓰기 작업을 위한 stream 을 반환합니다. 만약 파일이 이미 존재한다면, 질문없이 해당파일을 삭제하고 새로운 파일을 생성합니다.  


'''readOnlyFileNamed:''' 읽기를 위해 주어진 이름으로 현존하는 파일을 엽니다.
'''oldFileNamed:''' 읽기와 쓰기 작업을 위해 주어진 이름으로 기존에 존재하는 파일을 open 합니다<ref name="역자주1">Pharo by example 일본어판 에서는 파일이 실제로 존재하지 않는경우에 대한 동작을 사용자에게 질문한다고 되어있습니다. 아마도 squeak by example 에서는 당연한 action 이라고 생각하고 언급을 안한거같기는 하군요</ref>. 만약 파일이 이미 존재하는 경우, 이전의 내용은 변경하거나 옮기는게 가능합니다만, close 하는 경우 파일이 불완전한 상태가 되지는 않습니다.  만약 인수로 받은 이름에 별도로 디렉토리에 대한 내용이 포함되어있지 않다면 파일은 기본디렉토리에서 생성됩니다.


'''readOnlyFileNamed:''' 읽기 작업만을 위해 주어진 이름으로 이미 존재하고 있는 파일을 엽니다.
open 된 파일 stream 은 꼭 닫아주어야 합니다. 이런 닫기작업에는 close 메서드를 사용합니다.


여러분은 파일에서 스트림을 열 때 마다, 그 스트림을 닫아야 만을 한다는 것을 기억하셔야 합니다. 이 닫기는 close 메소드를 사용하여 수행할 수 있습니다.
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
stream := FileStream forceNewFileNamed: 'test.txt'.
stream := FileStream forceNewFileNamed: 'test.txt'.
Line 33: Line 35:




메소드 localName은 파일 이름의 마지막 요소를 답변으로 내놓습니다.
메서드 localName 은 파일 이름의 마지막 요소를 반환합니다. 메서드 fullName 을 이용해서 전체 경로를 얻을 수도 있습니다.
 
 
아마도 당신은 머지않아 파일 stream 을 수동으로 닫는것이 꽤나 번거롭고, 에러가 발생될 수도 있다는걸 알게 될겁니다. 이런 문제때문에 FileStream 클래스는 forceNewFileNamed:do: 라는 메시지를 제공해서 작성 작업을 블록형태의 인자로 받아서 작성 작업을 끝낸후, 자동으로 stream 을 close 합니다.


여러분은 메소드 fullName을 사용하여 전체 경로(the full path name)에 접근할 수 있습니다. 여러분은 곧 파일 스트림을 수동으로 닫는 것은 고통스러우며, 실수를 유발(error-prone)한다는 것을 알아차리실 것입니다. 그 이유가 FileStream이 그 자체의 컨텐츠를 설정하는 블록을 평가한 후에 새로운 스트림을 자동으로 닫기 위해 forceNewFileNamed:do:라고 지칭되는 메시지를 제공하는 근거입니다. 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
FileStream
FileStream
Line 50: Line 54:




인수로서 블록을 취하는 스트림 생성 메소드는(the stream-creation) 첫 번째로 파일에 스트림을 만들고 그 다음 인수로서 스트림과 함께 블록을 실행한 후 마지막으로 스트림을 닫습니다. 이 메소드들은 블록에 의해 리턴된 것을 리턴하며, 그것은 블록의 마지막 표현식의 값을 말하는 셈이 됩니다. 이것은 파일의 컨텐츠를 얻고, 변수 문자열에 컨텐츠를 집어넣기 위한 이전 예시에서 사용되었습니다.
파일 stream 을 만드는 메서드중 블록을 인자로 취하는 경우는, 일단 stream 만든 후, stream 을 인자로 블록을 실행하고 마지막에 stream 을 close 합니다. 이런 종류의 메서드는 블록에서 반환되는 내용을 반환하게 되며, 이것은 곧 블록의 마지막에 있는 표현식의 값이 됩니다. 위의 예제에서는 블록의 마지막 표현식은 stream contents 를 실행해서 파일의 내용을 얻은다음, 그 내용을 string 이라는 변수에 대입하고 있습니다.




===바이너리 스트림(Binary streams)===


디폴트로, 만들어진 스트림은 여러분이 문자를 읽고 쓸 것이라는 것을 의미하는 텍스트 기반(text-based)입니다. 만약 여러분의 스트림이 반드시 바이너리가 되어야 한다면 여러분은 자신의 스트림에 메시지 binary를 반드시 발송하셔야 합니다.  
===Binary Stream===
 
기본적으로 파일 stream 은, text 기반으로서 chracter 의 읽기, 쓰기 작업용으로 만들어집니다. 만약 stream 에서 binary 데이터를 취급해야한다면, 반드시 stream 에 binary 메시지를 보내야 합니다.
 
stream 이 binary mode 인 경우, 0 에서 255(1 byte)의 값만 사용할 수 있습니다. nextPutAll: 메서드를 이용해서 한번에 2 개 이상의 값을 쓰기<sup>write</sup> 하고싶다면 이 메서드의 인자로 ByteArray 를 넘겨주어야 합니다.


여려분의 스트림이 바이너리 모드(binary mode)에 있을 때, 여러분은 0에서255(1byte)까지의 숫자만을 쓰기 할 수 있습니다. 만약 여러분이 한번에 한 개의 숫자 이상을 쓰기 위해 nextPutAll:을 사용하기 원하신다면, 인수로서 ByteArray를 패스해야만 합니다.
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
FileStream
FileStream
Line 77: Line 83:




여기에 “test.pgm” (포터블 graymap 파일 포맷)으로 작명된 파일에 그림(picture)을 만드는 다른 예시가 있습니다. 여러분은 여러분이 좋아하는 그리기 프로그램(drawing program)으로 이 파일을 열 수 있습니다.  
아래의 예제에서 "test.pgm" 이라고 하는 그림파일을 만들어 보도록 하겠습니다. 작성한 파일은 원하는 draw 프로그램으로 열 수 있습니다<ref name="역자주2">pharo by example 일본어판 에서는 PGM:Portablegraymap 이라는 내용이 있습니다. GIMP 등의 프로그램에서 이 포맷의 사용이 가능합니다.</ref>.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
FileStream
FileStream
Line 95: Line 102:




이것은 그림 10.12에 보이는 것처럼 4x4 체스판을 만듭니다.
위의 프로그램으로 그림 10.12 와 같은 4x4 체스판을 만들 수 있습니다.
 
[[image:checkerboard4x4.png|none|112px|thumb|그림 10.12: binary stream 을 사용해서 4x4 체스판을 그릴 수 있습니다.]]
 


[[image:checkerboard4x4.png|none|112px|thumb|그림 10.12: 여러분은 바이너리 스트림(binary streams)를 사용하여 4x4 체스판(checkerboard)을 그릴 수 있습니다.]]


==Notes==
==Notes==

Latest revision as of 13:17, 14 September 2013

파일 접근에 대한 stream 의 활용

컬렉션을 stream 으로 처리하는 방법은 이미 배웠습니다. 동일한 방법으로 하드디스크에 있는 파일도 stream 으로 처리할 수 있습니다. 일단 만들어지만, 파일에 대한 stream 은 콜렉션에 대한 stream 과 거의 비슷합니다: 같은 프로토콜을 이용해서 stream 에 대한 읽기, 쓰기, 위치결정 등의 작업을 할 수 있습니다. 가장 큰 차이는 stream 을 만드는 방법에 있습니다. 파일에 대한 stream 을 만드는 방법에 대해서, 몇가지 서로 다른 방법을 살펴보겠습니다.


파일 stream 만들기

파일 stream 을 만들기 위해서는, FileStream 클래스 에서 제공되는 아래의 인스턴스 생성 메서드들 중 하나를 반드시 사용해야 합니다:

fileNamed: 주어진 이름으로 파일을 읽기, 쓰기 작업을 위해서 open 힙니다. 만약 파일이 이미 존재하는 경우, 이전의 내용은 변경하거나 옮기는게 가능합니다만, close 하는 경우 파일이 불완전한 상태가 되지는 않습니다. 만약 인수로 받은 이름에 별도로 디렉토리에 대한 내용이 포함되어있지 않다면 파일은 기본디렉토리에서 생성됩니다.

newFileNamed: 주어진 이름으로 새로운 파일을 만들고, 그 파일에 대해 쓰기 작업을 위한 stream 을 반환합니다. 만약 파일이 이미 존재한다면, 유저에게 해야할 일을 요청합니다.

forceNewFileNamed: 주어진 이름으로 새로운 파일을 만들고, 그 파일에 대해 쓰기 작업을 위한 stream 을 반환합니다. 만약 파일이 이미 존재한다면, 질문없이 해당파일을 삭제하고 새로운 파일을 생성합니다.

oldFileNamed: 읽기와 쓰기 작업을 위해 주어진 이름으로 기존에 존재하는 파일을 open 합니다[1]. 만약 파일이 이미 존재하는 경우, 이전의 내용은 변경하거나 옮기는게 가능합니다만, close 하는 경우 파일이 불완전한 상태가 되지는 않습니다. 만약 인수로 받은 이름에 별도로 디렉토리에 대한 내용이 포함되어있지 않다면 파일은 기본디렉토리에서 생성됩니다.

readOnlyFileNamed: 읽기 작업만을 위해 주어진 이름으로 이미 존재하고 있는 파일을 엽니다.


open 된 파일 stream 은 꼭 닫아주어야 합니다. 이런 닫기작업에는 close 메서드를 사용합니다.

stream := FileStream forceNewFileNamed: 'test.txt'.
stream
  nextPutAll: 'This text is written in a file named ';
  print: stream localName.
stream close.

stream := FileStream readOnlyFileNamed: 'test.txt'.
stream contents.        'This text is written in a file named ''test.txt'''
stream close.


메서드 localName 은 파일 이름의 마지막 요소를 반환합니다. 메서드 fullName 을 이용해서 전체 경로를 얻을 수도 있습니다.


아마도 당신은 머지않아 파일 stream 을 수동으로 닫는것이 꽤나 번거롭고, 에러가 발생될 수도 있다는걸 알게 될겁니다. 이런 문제때문에 FileStream 클래스는 forceNewFileNamed:do: 라는 메시지를 제공해서 작성 작업을 블록형태의 인자로 받아서 작성 작업을 끝낸후, 자동으로 stream 을 close 합니다.

FileStream
  forceNewFileNamed: 'test.txt'
  do: [:stream |
    stream
      nextPutAll: 'This text is written in a file named ';
      print: stream localName].
string := FileStream
      readOnlyFileNamed: 'test.txt'
      do: [:stream | stream contents].
string        'This text is written in a file named ''test.txt'''


파일 stream 을 만드는 메서드중 블록을 인자로 취하는 경우는, 일단 stream 만든 후, stream 을 인자로 블록을 실행하고 마지막에 stream 을 close 합니다. 이런 종류의 메서드는 블록에서 반환되는 내용을 반환하게 되며, 이것은 곧 블록의 마지막에 있는 표현식의 값이 됩니다. 위의 예제에서는 블록의 마지막 표현식은 stream contents 를 실행해서 파일의 내용을 얻은다음, 그 내용을 string 이라는 변수에 대입하고 있습니다.


Binary Stream

기본적으로 파일 stream 은, text 기반으로서 chracter 의 읽기, 쓰기 작업용으로 만들어집니다. 만약 stream 에서 binary 데이터를 취급해야한다면, 반드시 stream 에 binary 메시지를 보내야 합니다.

stream 이 binary mode 인 경우, 0 에서 255(1 byte)의 값만 사용할 수 있습니다. nextPutAll: 메서드를 이용해서 한번에 2 개 이상의 값을 쓰기write 하고싶다면 이 메서드의 인자로 ByteArray 를 넘겨주어야 합니다.

FileStream
  forceNewFileNamed: 'test.bin'
  do: [:stream |
    stream
      binary;
      nextPutAll: #(145 250 139 98) asByteArray].

FileStream
  readOnlyFileNamed: 'test.bin'
  do: [:stream |
    stream binary.
    stream size.           4
    stream next.           145
    stream upToEnd.        a ByteArray(250 139 98)
  ].


아래의 예제에서 "test.pgm" 이라고 하는 그림파일을 만들어 보도록 하겠습니다. 작성한 파일은 원하는 draw 프로그램으로 열 수 있습니다[2].

FileStream
  forceNewFileNamed: 'test.pgm'
  do: [:stream |
    stream
      nextPutAll: 'P5'; cr;
      nextPutAll: '4 4'; cr;
      nextPutAll: '255'; cr;
      binary;
      nextPutAll: #(255 0 255 0) asByteArray;
      nextPutAll: #(0 255 0 255) asByteArray;
      nextPutAll: #(255 0 255 0) asByteArray;
      nextPutAll: #(0 255 0 255) asByteArray
  ]


위의 프로그램으로 그림 10.12 와 같은 4x4 의 체스판을 만들 수 있습니다.

그림 10.12: binary stream 을 사용해서 4x4 체스판을 그릴 수 있습니다.


Notes

  1. Pharo by example 일본어판 에서는 파일이 실제로 존재하지 않는경우에 대한 동작을 사용자에게 질문한다고 되어있습니다. 아마도 squeak by example 에서는 당연한 action 이라고 생각하고 언급을 안한거같기는 하군요
  2. pharo by example 일본어판 에서는 PGM:Portablegraymap 이라는 내용이 있습니다. GIMP 등의 프로그램에서 이 포맷의 사용이 가능합니다.