1 00:00:00,400 --> 00:00:05,360 Hello. In this course, I'll talk about the stream library. 2 00:00:05,520 --> 00:00:07,840 It's a basic feature of Pharo. 3 00:00:09,240 --> 00:00:13,480 We'll see what streams are, how to use them, and when they can be useful. 4 00:00:14,880 --> 00:00:16,200 What is a stream? 5 00:00:16,360 --> 00:00:17,840 It's an object 6 00:00:18,000 --> 00:00:22,200 that enables to iterate over a collection of elements, 7 00:00:22,360 --> 00:00:24,240 a sequence of elements. 8 00:00:24,400 --> 00:00:28,040 This sequence could be a collection in memory, 9 00:00:28,800 --> 00:00:34,320 a network flow, a file, etc. 10 00:00:36,120 --> 00:00:39,320 A stream keeps the current position in memory. 11 00:00:40,000 --> 00:00:44,200 As you use the stream, you can move forward or backward 12 00:00:44,360 --> 00:00:46,920 to read from or write elements to the stream. 13 00:00:47,600 --> 00:00:50,760 An overview of the streams' API. 14 00:00:50,920 --> 00:00:54,680 To create a stream, there are a few objects 15 00:00:55,520 --> 00:01:00,200 over which you can use the messages readStream and writeStream 16 00:01:01,000 --> 00:01:02,880 to create streams 17 00:01:03,040 --> 00:01:06,800 (from a file or a collection, for instance). 18 00:01:07,880 --> 00:01:10,480 You can create streams this way. 19 00:01:11,760 --> 00:01:16,560 This message, streamContents:, is sent to a collection 20 00:01:16,720 --> 00:01:19,120 and takes a block as a parameter, which receives a stream. 21 00:01:19,680 --> 00:01:23,840 The use of a stream within this block creates a collection 22 00:01:24,000 --> 00:01:27,800 the method will eventually return. 23 00:01:27,960 --> 00:01:30,400 We'll see how to use this method in the end. 24 00:01:31,440 --> 00:01:35,160 In this case, you directly ask a class, 25 00:01:35,320 --> 00:01:38,680 either readStream, writeStream, or (Read/Write)Stream, 26 00:01:38,840 --> 00:01:42,640 to create a new instance over a collection. 27 00:01:44,840 --> 00:01:50,200 These three methods can read one or several elements 28 00:01:51,240 --> 00:01:53,320 up to a point. 29 00:01:54,080 --> 00:01:56,280 These two elements 30 00:01:56,440 --> 00:02:00,640 write an element or a collection of elements to the stream. 31 00:02:00,800 --> 00:02:04,440 These are a few examples through which you can read from a stream. 32 00:02:04,600 --> 00:02:06,600 First, create a stream. 33 00:02:06,760 --> 00:02:11,640 I'm creating a readStream from a collection. 34 00:02:11,800 --> 00:02:15,760 The collection contains all letters between a and f. 35 00:02:15,920 --> 00:02:19,840 There's one character for every element in the collection. 36 00:02:20,000 --> 00:02:24,520 Create a stream over the collection. Let's look at the characters one by one. 37 00:02:25,360 --> 00:02:27,760 Once the stream is ready, 38 00:02:28,400 --> 00:02:31,040 you may start by sending the message next 39 00:02:31,200 --> 00:02:34,720 which will return an element right after the current position 40 00:02:34,880 --> 00:02:36,800 when the stream is initialized. 41 00:02:36,960 --> 00:02:40,200 The current position is 0, at the beginning of the stream. 42 00:02:40,360 --> 00:02:45,120 next returns the first element, which is a. 43 00:02:45,920 --> 00:02:47,880 If I call next at this time, 44 00:02:48,040 --> 00:02:51,800 I'll get a then b then c, one at a time. 45 00:02:51,960 --> 00:02:56,920 By calling next, the position moves by one row at a time. 46 00:02:57,760 --> 00:03:01,440 If I call next once and get a, 47 00:03:01,600 --> 00:03:06,480 I can send the message upTo: and one element. 48 00:03:06,640 --> 00:03:10,720 This method returns all the elements between the current position 49 00:03:10,880 --> 00:03:13,520 and the element I placed as parameter. 50 00:03:13,680 --> 00:03:17,040 With a, I'm in position 1. 51 00:03:17,920 --> 00:03:19,800 If I send upTO: $d, 52 00:03:19,960 --> 00:03:23,320 it returns what's between the current position and d: 53 00:03:23,480 --> 00:03:26,000 b and c. 54 00:03:26,600 --> 00:03:28,720 d is consumed by the stream. 55 00:03:28,880 --> 00:03:32,440 It means the stream is now located right after d. 56 00:03:32,600 --> 00:03:33,800 d isn't returned. 57 00:03:34,440 --> 00:03:38,760 stream position returns the current position. 58 00:03:38,920 --> 00:03:40,720 The position starts at 0. 59 00:03:40,880 --> 00:03:46,400 0 is located before the first element: 0, 1, 2, 3, 4. 60 00:03:46,560 --> 00:03:49,120 We're right before e and after d. 61 00:03:50,760 --> 00:03:55,840 Now if I send the message upToEnd to the stream, I'll get all the elements 62 00:03:56,000 --> 00:04:00,040 located between the current position and the end of the stream: 63 00:04:00,200 --> 00:04:03,400 that's e and f. 64 00:04:03,560 --> 00:04:07,520 The stream maintains a current position I can move forward 65 00:04:07,680 --> 00:04:09,360 thanks to a few methods. 66 00:04:09,520 --> 00:04:11,680 You can also write to a stream. 67 00:04:11,840 --> 00:04:14,240 The first step is to create the stream. 68 00:04:15,880 --> 00:04:19,840 With Array new: 6, I create a size-6 array. 69 00:04:20,640 --> 00:04:24,240 I send the message writeStream to create a stream on the array 70 00:04:24,400 --> 00:04:27,600 to be able to gradually fill it in thanks to the stream. 71 00:04:27,760 --> 00:04:30,320 I store the stream in the variable stream. 72 00:04:30,480 --> 00:04:33,280 I first send the message nextPut: 1 73 00:04:33,440 --> 00:04:38,360 which takes one element and adds it to the current position in the stream. 74 00:04:38,520 --> 00:04:43,800 My array now contains 1 followed by five empty cells. 75 00:04:46,280 --> 00:04:50,320 The message nextPutAll: takes a collection of objects 76 00:04:50,480 --> 00:04:53,360 which are appended to the stream. 77 00:04:54,240 --> 00:04:57,800 After sending nextPutAll: to the stream, 78 00:04:58,600 --> 00:05:01,000 I get an array that contains 1, 79 00:05:01,880 --> 00:05:04,480 the result of the previous nextPut:, 80 00:05:04,640 --> 00:05:06,880 followed by 4 8 2 6 7, 81 00:05:09,240 --> 00:05:11,120 the result of nextPutAll:. 82 00:05:11,280 --> 00:05:14,880 Streams are especially useful and efficient 83 00:05:15,040 --> 00:05:18,560 to read from and write to object collections. 84 00:05:19,400 --> 00:05:21,600 I can also write to and read from files. 85 00:05:21,760 --> 00:05:25,200 I'm giving an example of how to write 86 00:05:25,360 --> 00:05:27,440 to a new file that doesn't exist yet. 87 00:05:29,880 --> 00:05:32,480 In the stream, I type the name of the file. 88 00:05:33,640 --> 00:05:39,360 By sending a stream with the message asFileReference, 89 00:05:39,520 --> 00:05:41,720 I create a reference to a file. 90 00:05:41,880 --> 00:05:46,040 This is a file that doesn't exist yet, but I can still get a reference to it. 91 00:05:46,640 --> 00:05:49,440 I have a reference to a file, hello.txt. 92 00:05:50,720 --> 00:05:52,680 I send the message writeStream 93 00:05:54,120 --> 00:05:55,440 to the file 94 00:05:55,600 --> 00:06:00,760 in order to get a write stream related to this non-existent file. 95 00:06:00,920 --> 00:06:05,240 As soon as you write to the stream, the file is created. 96 00:06:06,240 --> 00:06:11,480 Now that I have a stream, I send the message nextPutAll: with a string. 97 00:06:11,640 --> 00:06:16,720 This message writes, one character at a time, each element of the string. 98 00:06:16,880 --> 00:06:19,400 "h" then "e" then "l", etc. 99 00:06:20,560 --> 00:06:21,560 In the end, 100 00:06:23,320 --> 00:06:24,960 I close the stream 101 00:06:25,120 --> 00:06:29,720 to tell the operating system I'm done writing in the file 102 00:06:29,880 --> 00:06:33,360 and that it can write everything to the storage system 103 00:06:33,520 --> 00:06:37,360 and close the file pointer. 104 00:06:37,520 --> 00:06:42,400 Now that I've written in the file, I can read it. 105 00:06:42,560 --> 00:06:46,720 The file name 106 00:06:46,880 --> 00:06:48,680 is displayed as a string. 107 00:06:50,880 --> 00:06:56,200 With asFileReference, I can create a reference to this file. 108 00:06:57,800 --> 00:06:59,440 With readStream, 109 00:06:59,600 --> 00:07:02,240 I can open a read flow, 110 00:07:02,400 --> 00:07:06,160 a read stream when it comes to this file. 111 00:07:07,840 --> 00:07:10,680 With next, I get the first element of the stream. 112 00:07:10,840 --> 00:07:14,920 I wrote "Hello Pharo!". The first element is "H". 113 00:07:15,600 --> 00:07:19,000 With upToEnd, I get all the characters 114 00:07:19,160 --> 00:07:22,400 between the current position, after "H" and before "e", 115 00:07:22,560 --> 00:07:25,840 and the end of the file. 116 00:07:26,000 --> 00:07:28,800 I get "ello Pharo!" without "H" 117 00:07:28,960 --> 00:07:33,160 as I already got it thanks to next. 118 00:07:33,320 --> 00:07:36,960 One can create collections using streams. 119 00:07:37,120 --> 00:07:39,880 It's useful when you want to create collections 120 00:07:40,040 --> 00:07:44,320 and you need code to choose what to gradually include in them. 121 00:07:45,480 --> 00:07:48,680 I want to create an OrderedCollection 122 00:07:50,840 --> 00:07:53,160 by sending messages to a stream. 123 00:07:53,320 --> 00:07:56,240 From the class OrderedCollection, 124 00:07:56,960 --> 00:07:58,640 I start a new instance 125 00:07:59,240 --> 00:08:01,760 which I turn into a writeStream. 126 00:08:02,520 --> 00:08:06,280 Thanks to the message nextPut:, I add 1 in the stream. 127 00:08:06,440 --> 00:08:10,200 If I type stream contents, 128 00:08:10,360 --> 00:08:13,440 I get an instance of the class OrderedCollection 129 00:08:13,600 --> 00:08:15,520 which contains the value 1 only. 130 00:08:16,240 --> 00:08:19,720 These three expressions can be simplified, as shown below. 131 00:08:20,720 --> 00:08:23,240 You may send the message streamContents: 132 00:08:23,400 --> 00:08:26,960 to the class we're interested in, which is OrderedCollection. 133 00:08:27,120 --> 00:08:29,960 I send streamContents: to OrderedCollection. 134 00:08:30,120 --> 00:08:35,000 I pass it a block as a parameter which takes a stream as a parameter. 135 00:08:35,160 --> 00:08:39,160 Within the block, I use the stream to gradually fill in the collection. 136 00:08:39,320 --> 00:08:41,760 When the block is over, I get a collection. 137 00:08:42,320 --> 00:08:46,120 In the block, I type stream nextPut: 1. 138 00:08:46,880 --> 00:08:49,720 I add 1 to the stream. 139 00:08:49,880 --> 00:08:51,880 It gets added to the collection. 140 00:08:52,040 --> 00:08:55,880 When streamContents: quits, when this expression is over, 141 00:08:56,040 --> 00:08:58,840 I'll get an OrderedCollection containing 1. 142 00:08:59,000 --> 00:09:03,720 streamContents: is useful to create collections from scratch. 143 00:09:04,400 --> 00:09:07,600 In the course, we learned about stream's API. 144 00:09:07,760 --> 00:09:11,920 There are many methods you should learn about by exploring the classes 145 00:09:12,080 --> 00:09:14,280 thanks to Nautilus code navigator. 146 00:09:14,440 --> 00:09:18,560 A stream can read from and write to collections in memory, 147 00:09:18,720 --> 00:09:22,480 files, the network, etc. 148 00:09:23,640 --> 00:09:26,160 A stream maintains a current position. 149 00:09:27,040 --> 00:09:31,440 The current position separates the past elements from the future elements. 150 00:09:31,600 --> 00:09:36,000 Whenever you write to or read from the flux, the current position changes. 151 00:09:37,200 --> 00:09:40,480 Streams can also help create new collections.