WEBVTT

00:01.670 --> 00:09.110
Hello again! In this video, we are going to look at unbuffered input and output. We saw in the last

00:09.110 --> 00:09.490
video

00:09.530 --> 00:15.530
that the stream can hold up data. And sometimes we want data to be sent to the output immediately.

00:15.710 --> 00:18.860
So we can use the flush to override the stream's behavior.

00:20.510 --> 00:25.400
Sometimes we want to go even further and override the buffer altogether, To bypass them.

00:26.090 --> 00:28.400
An example of that is a network application.

00:29.450 --> 00:34.970
There is a network protocol, which is basically a set of rules for communicating between computers.

00:35.630 --> 00:41.390
And these will say that the data has to be sent in a so-called "packet", a block of memory which has a

00:41.900 --> 00:43.790
fixed size or a given size.

00:44.420 --> 00:48.320
And almost certainly that is not going to be the size that the stream chooses for the buffer.

00:49.990 --> 00:54.130
It may also be critical to send or receive data at a particular time.

00:54.580 --> 00:59.950
So really, we do not want to have stream buffers getting in the way and delaying data and sending the

00:59.950 --> 01:00.910
wrong size of data.

01:03.510 --> 01:08.940
C++ provides some lower-level operations on streams which do bypass the stream;s buffer.

01:09.360 --> 01:11.760
They also avoid performing any formatting.

01:12.390 --> 01:17.730
If you have an output stream, it may add spaces or change numbers to make them look nice.

01:18.480 --> 01:23.130
If you have an input stream and you're using the right shift operator, it will

01:23.130 --> 01:27.450
remove all the white space. So none of that will happen with these low-level operators.

01:29.820 --> 01:32.280
These are lower-level, so they are more difficult to use.

01:32.550 --> 01:37.020
You should really use the left shift and right [shift] operators unless you actually need these lower level

01:37.020 --> 01:37.320
ones.

01:38.400 --> 01:44.100
Some circumstances where they are useful is for networking applications and also for communicating directly

01:44.100 --> 01:44.790
with hardware.

01:45.330 --> 01:51.990
If you have a network card or a sound card or a hard drive, it probably requires that you communicate

01:51.990 --> 01:58.230
[with] it with memory with a fixed block. And you need to have control over the timing of when data is sent and

01:58.230 --> 01:58.740
received.

02:01.400 --> 02:07.370
The simplest memory block is a single character, and there are member functions for that. An input screen

02:07.370 --> 02:11.210
has a get() member function, which will fetch the next character from the stream.

02:12.530 --> 02:17.630
An output stream has a put() member function, which will send a single character to the stream.

02:21.080 --> 02:27.170
get() will take a character by address, so it can be modified, and put() will take it by value.

02:28.950 --> 02:32.760
get() will return true unless it reads the end of input character.

02:38.610 --> 02:43.920
So we can try that out. We have a program which prompts the user to enter some text, so they do not

02:43.920 --> 02:46.800
see a blank screen, and then we have this loop.

02:47.310 --> 02:53.520
So, keep getting a single character until the end of input, and then send that character to the output.

02:59.240 --> 03:00.770
So let's enter some text.

03:03.520 --> 03:06.370
So it doesn't actually read the data until I press the return key.

03:06.700 --> 03:09.050
So this is still line-oriented input.

03:10.390 --> 03:14.830
Obviously, if you are reading from a file or a network socket, then it would not wait until the end

03:14.830 --> 03:15.310
of the line.

03:17.890 --> 03:22.510
So there we are. We got the text that we entered. The space characters were not removed.

03:22.870 --> 03:25.060
It has not added any extra space characters.

03:27.530 --> 03:33.800
So once I pressed the return key, the stream got the data. And then it went through and took the first character,

03:34.610 --> 03:39.130
and stored it in this variable 'c', and then we called put() on the output stream.

03:39.140 --> 03:41.570
And that sent the character to the output.

03:42.230 --> 03:44.690
And then the next character and so on.

03:45.680 --> 03:49.070
And because I have not entered the end-of-input [character], it is still waiting for more input.

03:53.310 --> 04:00.120
So I will enter control-Z, which should be the Windows end of input character. And there, the program has now ended.

04:01.310 --> 04:05.450
The loop has terminated because get() saw the end-of-input input symbol.

04:10.040 --> 04:15.770
If we want to read or write more than one character at a time, the read and write member functions will

04:15.770 --> 04:16.730
do that for us.

04:18.270 --> 04:21.920
We are not using the stream's buffer, so we need to provide one ourselves.

04:23.970 --> 04:30.120
This will be an array of characters. For write, this buffer will contain all the data that we are going

04:30.120 --> 04:34.680
to send to the output. For a read operation,

04:35.280 --> 04:39.180
this buffer must be large enough to store all the data that we are going to receive.

04:43.200 --> 04:49.650
These member functions take two arguments. The first one is the array, a pointer to the first element, and

04:49.650 --> 04:51.810
the second one is the number of characters.

04:52.980 --> 04:58.630
So for a read operation, this must be the number of characters we expect to receive, and the buffer

04:58.680 --> 05:01.410
must be big enough to hold at least that many characters.

05:02.820 --> 05:07.500
And then, when we have a write operation, the buffer will contain the data that is going to be written.

05:08.100 --> 05:11.730
And then we have the number of elements in that data.

05:16.300 --> 05:19.300
We are going to read from a file, "input.txt".

05:22.550 --> 05:26.210
There is nothing very exciting here, just the numbers from 0 to 9.

05:28.160 --> 05:29.840
So we open that file.

05:30.350 --> 05:31.400
We do the usual checks.

05:31.940 --> 05:43.070
Then we read into this buffer. So we pass our array of character and the size of the array. And then we close

05:43.070 --> 05:44.870
the file, because we have finished reading from it.

05:47.210 --> 05:52.370
And then we now have the data in the "filebuf" [array], that we read from the file, so we can send that to

05:52.370 --> 05:54.560
the output, using the write member function.

06:01.050 --> 06:04.680
So there we are, we got the data from the file, 0 to 9.

06:09.900 --> 06:14.830
Usually when you are receiving data, you will have some idea how much you are going to get. The network

06:14.830 --> 06:18.180
protocol will probably have something which says how much data it is going to send.

06:18.900 --> 06:19.830
Sometimes it does not.

06:22.110 --> 06:23.820
So you need to be able to find out.

06:24.300 --> 06:29.210
And also, you need it anyway. If you are going to process the data, you may need to allocate memory,

06:29.220 --> 06:31.110
so you need to know how much memory to allocate.

06:31.560 --> 06:35.940
Or you may have to pass it to a function which has the number of elements as an argument.

06:36.960 --> 06:40.410
And also you need to check that the transfer was successful.

06:41.100 --> 06:45.750
If the other computer only sent part of the data and is going to send the rest later, you need to

06:45.750 --> 06:46.410
know about that.

06:47.520 --> 06:52.140
If something went wrong, if the packages is corrupt or the connection has been dropped, then you need

06:52.200 --> 06:53.250
to know about that as well.

06:54.420 --> 07:00.030
So we need to know the number of characters that we have read. And the gcount member function will

07:00.090 --> 07:00.720
return that.

07:01.020 --> 07:07.620
So we call that on the stream, and this will return the number of characters that it read in the last read operation.

07:09.240 --> 07:14.910
The type of this is - I think there is a special type for this, but it is a number. That is usually all

07:14.910 --> 07:15.510
you need to know.

07:15.810 --> 07:18.070
So this is a valid situation for using "auto".

07:19.500 --> 07:25.560
So I have added that to the program that we had to before. I am storing the number of bytes that we

07:25.560 --> 07:26.400
read in this variable.

07:27.090 --> 07:29.460
And then in this example, we just print it out.

07:33.260 --> 07:38.960
So we read 10 bytes from the input file, which is correct. And we still have the same data.

07:40.160 --> 07:41.840
Okay, so that's it for this video.

07:42.110 --> 07:42.930
I'll see you next time.

07:43.160 --> 07:44.720
Meanwhile, keep coding!
