프로그래밍 세계에서 스트림은 무엇입니까? 왜 필요한가요?
가능하면 유추의 도움으로 친절하게 설명하십시오.
답변
스트림은 일련의 객체 (일반적으로 바이트는 아니지만 반드시 순서는 아님)를 나타내며 순차적으로 액세스 할 수 있습니다. 스트림에서의 일반적인 작업 :
- 1 바이트를 읽습니다. 다음에 읽을 때 다음 바이트를 얻습니다.
- 스트림에서 배열로 몇 바이트를 읽습니다.
- 찾기 (다음에 읽을 때 새 위치에서 바이트를 얻도록 스트림에서 현재 위치를 이동하십시오)
- 1 바이트 쓰기
- 배열에서 스트림으로 몇 바이트 쓰기
- 스트림에서 바이트를 건너 뜁니다 (이것은 읽기와 같지만 데이터를 무시합니다. 또는 원하는 경우 탐색과 같지만 앞으로 만 갈 수 있습니다.)
- 바이트를 입력 스트림으로 푸시 백합니다 (이것은 읽기를 위해 “실행 취소”와 같습니다). 스트림을 몇 바이트 백업하면 다음에 읽을 때 볼 수 있습니다. 때때로 파서에 유용합니다 :
- 엿보기 (읽지 않고 바이트를보고 나중에 읽을 수 있도록 스트림에 여전히 있음)
특정 스트림은 읽기 (이 경우 “입력 스트림”), 쓰기 ( “출력 스트림”) 또는 둘 다를 지원할 수 있습니다. 모든 스트림을 검색 할 수있는 것은 아닙니다.
푸시 백은 매우 드물지만 내부 버퍼를 보유하는 다른 입력 스트림에 실제 입력 스트림을 래핑하여 스트림에 추가 할 수 있습니다. 버퍼에서 읽기가 이루어지고 뒤로 밀면 데이터가 버퍼에 배치됩니다. 버퍼에 아무것도 없으면 푸시 백 스트림은 실제 스트림에서 읽습니다. 이것은 “스트림 어댑터”의 간단한 예입니다. 입력 스트림의 “끝”에 있고 입력 스트림 자체이며 원래 스트림이하지 않은 추가 작업을 수행합니다.
스트림은 파일 (실제로 배열이므로 탐색이 간단 함)을 설명 할 수 있기 때문에 터미널 입력 / 출력 (버퍼링되지 않으면 탐색 할 수 없음), 소켓, 직렬 포트 등을 설명 할 수 있기 때문에 유용한 추상화입니다. “일부 데이터를 원하며 데이터가 어디에서 왔는지 또는 어떻게 가져 왔는지 상관하지 않습니다.”또는 “데이터를 생성 할 것입니다. 전적으로 발신자에게 달려 있습니다.” 전자는 입력 스트림 매개 변수를 사용하고 후자는 출력 스트림 매개 변수를 사용합니다.
내가 생각할 수있는 가장 좋은 비유는 스트림이 컨베이어 벨트가 당신을 향하거나 당신에게서 멀어지는 것 (또는 때로는 둘 다)이라는 것입니다. 입력 스트림에서 물건을 꺼내고 출력 스트림에 물건을 놓습니다. 벽에있는 구멍에서 나온 것으로 생각할 수있는 일부 컨베이어는 찾을 수 없거나 읽거나 쓰는 것이 일회성입니다. 일부 컨베이어는 당신 앞에 배치되며, 당신은 읽고 / 쓰기하려는 스트림의 위치를 선택하여 이동할 수 있습니다.
그러나 IRBMe가 말했듯이 물리적 비유보다는 제공하는 작업 (구현에 따라 다르지만 공통점이 많이 있음) 측면에서 스트림을 생각하는 것이 가장 좋습니다. 스트림은 “읽거나 쓸 수있는 것”입니다. 스트림 어댑터 연결을 시작하면 다른 스트림에 연결하는 컨베이어 입력 및 컨베이어 출력이있는 상자로 생각할 수 있습니다. 그런 다음 상자에서 데이터에 대한 변환 (지핑 또는 UNIX 줄 바꿈 변경)을 수행합니다. DOS에, 또는 무엇이든). 파이프는 은유에 대한 또 하나의 철저한 테스트입니다. 여기서 하나의 스트림에 스트림을 작성하여 하나의 스트림에 쓰면 무엇이든 읽을 수 있습니다. 벌레 구멍을 생각하십시오 🙂
답변
스트림은 이미 은유이며 유추이므로 다른 스트림을 povide 할 필요가 없습니다. 기본적으로 물이 실제로 데이터이고 파이프가 스트림 인 물 흐름이있는 파이프로 생각할 수 있습니다. 스트림이 양방향이라면 일종의 양방향 파이프라고 가정합니다. 기본적으로 한 방향 또는 두 방향으로 데이터 흐름 또는 순서가있는 곳에 배치되는 일반적인 추상화입니다.
C #, VB.Net, C ++, Java 등과 같은 언어에서는 스트림 메타포가 여러 가지 용도로 사용됩니다. 파일 스트림은 파일을 열고 스트림에서 읽거나 연속적으로 쓸 수있는 파일 스트림입니다. 스트림에서 읽고 쓰는 네트워크 스트림은 기본 설정된 네트워크 연결에서 읽고 씁니다. 쓰기 전용 스트림은 일반적 으로이 예제와 같이 출력 스트림이라고 하며, 마찬가지로 읽기 전용 스트림은 이 예제 와 같이 입력 스트림이라고합니다 .
스트림은 데이터의 변환 또는 인코딩을 수행 할 수 있습니다 ( 예 : .Net 의 SslStream 은 SSL 협상 데이터를 가져 와서 숨길 것입니다. TelnetStream은 Telnet 협상을 숨기고 데이터에 액세스 할 수는 있음) Java의 ZipOutputStream 을 사용하면 zip 파일 형식의 내부에 대해 걱정할 필요없이 zip 아카이브의 파일에 쓸 수 있습니다.
또 다른 일반적인 발견은 바이트 대신 문자열을 작성할 수있는 텍스트 스트림이거나 일부 언어는 기본 유형을 작성할 수있는 2 진 스트림을 제공합니다. 텍스트 스트림에서 흔히 볼 수있는 것은 인코딩해야 할 문자 인코딩입니다.
이 예 에서처럼 일부 스트림은 임의 액세스도 지원 합니다. 반면 네트워크 스트림은 명백한 이유가 없습니다.
- MSDN 은 .Net의 스트림에 대한 좋은 개요를 제공합니다.
- 또한 Sun은 일반 OutputStream 클래스 및 InputStream 클래스에 대한 개요를 제공합니다 .
- C ++에서 istream (입력 스트림), ostream (출력 스트림) 및 iostream (양방향 스트림) 문서는 다음과 같습니다.
UNIX와 같은 운영 체제도 여기에 설명 된대로 프로그램 입력 및 출력과 함께 스트림 모델을 지원합니다 .
답변
지금까지 주어진 답변은 훌륭합니다. 나는 개념이 보편적이기 때문에 스트림이 일련의 바이트가 아니거나 프로그래밍 언어에 국한되지 않는다는 것을 강조하기 위해 다른 것을 제공하고 있습니다 (구현은 독창적 일 수 있습니다). 필자는 종종 SQL, C 또는 Java와 관련하여 온라인에서 많은 설명을 보았습니다. 이는 파일 스트림이 메모리 위치 및 저수준 작업을 처리하는 데 적합합니다. 그러나 종종 스트림의 개념을 논의하기보다는 파일 스트림을 작성하고 주어진 언어로 잠재적 파일을 조작하는 방법을 다룹니다.
은유
언급했듯이 a stream
는 더 복잡한 무언가의 은유입니다. 상상력을 발휘하기 위해 다른 은유를 제공합니다.
- 빈 수영장에 물을 채우려 고합니다. 이를 달성하는 한 가지 방법은 마개에 호스를 부착하고 호스의 끝을 수영장에 놓고 물을 켜는 것입니다.
호스는 시내입니다
- 마찬가지로 자동차에 가스를 채우려면 가스 펌프로 가서 노즐을 가스 탱크에 넣고 잠금 레버를 꽉 쥐어 밸브를여십시오.
가스가 탱크로 유입되도록하는 호스, 노즐 및 관련 메커니즘
- 출근해야하는 경우 고속도로를 사용하여 집에서 사무실로 운전을 시작합니다.
고속도로는 개울입니다
- 누군가와 대화하고 싶다면 귀로 듣고 입으로 말하십시오.
당신의 귀와 눈은 개울입니다
이 예제에서 스트림 은유는 무언가가 그것을 통해 (또는 고속도로의 경우 그것에) 여행 할 수 있도록 존재하며 항상 자신이 전달하는 것을 포즈로 제시하지는 않습니다. 중요한 차이점. 우리는 귀를 일련의 단어로 언급하지 않습니다. 물이 흐르지 않으면 호스는 여전히 호스이지만, 올바르게 작동하려면 마개에 연결해야합니다. 자동차는 고속도로를 통과 할 수있는 유일한 ‘종류’의 차량이 아닙니다.
따라서 데이터 가 파일에 연결되어 있으면 데이터가 전송되지 않는 스트림이 존재할 수 있습니다 .
추상화 제거
다음으로 몇 가지 질문에 대답해야합니다. 스트림을 설명하기 위해 파일을 사용할 것입니다 … 파일이란 무엇입니까? 그리고 우리는 파일을 어떻게 읽습니까? 필자는 불필요한 복잡성을 피하기 위해 특정 추상화 수준을 유지하면서 이에 응답하려고 시도하고 단순성과 접근성으로 인해 Linux 운영 체제와 관련된 파일 개념을 사용합니다.
파일이란 무엇입니까?
파일은 추상화입니다 🙂
또는 간단히 설명 할 수 있듯이 파일은 파일을 설명하는 한 부분 데이터 구조이고 실제 내용 인 한 부분 데이터입니다.
데이터 구조 부분 (UNIX / 리눅스 시스템에서 inode라고 함)은 컨텐츠에 대한 중요한 정보를 식별하지만 컨텐츠 자체 (또는 해당 파일의 이름)는 포함하지 않습니다. 그것이 유지하는 정보 중 하나는 컨텐츠가 시작되는 메모리 주소입니다. 따라서 파일 이름 (또는 리눅스의 하드 링크), 파일 설명자 (운영 체제가 관심을 갖는 숫자 파일 이름) 및 메모리의 시작 위치를 사용하면 파일이라고 할 수 있습니다.
(키 테이크 아웃은 ‘파일’은 운영 체제에 의해 정의되며 궁극적으로 파일 을 처리 해야하는 OS이므로 파일 은 훨씬 더 복잡합니다).
여태까지는 그런대로 잘됐다. 그러나 파일의 내용을 어떻게 얻습니까, 연애 편지를 말하면 어떻게 인쇄 할 수 있습니까?
파일 읽기
결과에서 시작하여 뒤로 이동하면 컴퓨터에서 파일을 열면 전체 내용이 화면에 튀겨 져 읽을 수 있습니다. 그러나 어떻게? 매우 체계적으로 답변입니다. 파일 자체의 내용은 또 다른 데이터 구조입니다. 문자 배열을 가정하십시오. 이것을 문자열로 생각할 수도 있습니다.
그렇다면이 문자열을 어떻게 ‘읽을’까요? 메모리에서 해당 위치를 찾고 파일 문자의 끝에 도달 할 때까지 한 번에 한 문자 씩 문자 배열을 반복합니다. 다시 말해 프로그램입니다.
스트림은 프로그램이 호출 될 때 ‘생성’되며 연결 하거나 연결할 메모리 위치가 있습니다 . 워터 호스의 예와 마찬가지로 호스가 스피 곳에 연결되어 있지 않으면 비 효과적입니다. 스트림의 경우 파일에 연결되어 있어야합니다.
스트림은 예를 들어 입력을 수신하는 스트림 또는 파일 내용을 표준 출력으로 전송하는 스트림을 더 세분화 할 수있다. UNIX / linux는 bat, stdin (표준 입력), stdout (표준 출력) 및 stderr (표준 오류)에서 바로 3 개의 파일 스트림을 연결하고 유지합니다. 스트림은 데이터 구조 자체 또는 객체로 구축 될 수 있으며,이를 통해 스트림 열기, 스트림 닫기 또는 스트림이 연결된 파일의 오류 확인과 같이 데이터를 스트리밍하는보다 복잡한 데이터 작업을 수행 할 수 있습니다. C ++ cin
는 스트림 객체의 예입니다.
확실히, 당신이 그렇게 선택한다면, 당신은 당신의 자신의 스트림을 작성할 수 있습니다.
정의
스트림은 재사용 가능한 코드로, 데이터를 처리하는 데 유용한 작업을 제공하면서 데이터 처리의 복잡성을 추상화합니다.
답변
위에서 언급 한 것 외에도 Scheme 또는 Haskell과 같은 기능적 프로그래밍 언어로 정의 된 다른 종류의 스트림이 있습니다.
답변
또 다른 비유 : 스트림에 대해 수영 할 수 없으므로 이미 읽은 데이터가 삭제되는 동안 스트림에서 다음 비트, 바이트, 문자열 또는 객체를 가져올 수 있습니다. 단방향 티켓 또는 기본적으로 지속성을 저장하지 않는 대기열 .
큐가 필요한가요? 당신이 결정합니다.
답변
“스트림”이라는 단어는 (실제로) 사용할 때 전달하고자하는 것과 매우 유사한 의미를 나타 내기 때문에 선택되었습니다.
물 흐름과의 비유에 대해 생각하기 시작하십시오. 물이 강에 지속적으로 흐르는 것처럼 연속적인 데이터 흐름을받습니다. 데이터가 어디에서 오는지 반드시 알 필요는 없으며 대부분의 경우 필요하지 않습니다. 파일, 소켓 또는 다른 소스에서 가져온 것이 든 실제로 중요하지는 않습니다. 이것은 물의 흐름을받는 것과 매우 유사하므로 물의 출처를 알 필요가 없습니다. 호수, 분수대 또는 기타 다른 곳에서 가져 오더라도 실제로 중요하지 않습니다. 출처