****** A Gentle Introduction to C++ IO Streams - TopicsExpress



          

****** A Gentle Introduction to C++ IO Streams ****** Guys its written By Manasij Mukherjee Guys One of the great strengths of C++ is its I/O system, IO Streams. As Bjarne Stroustrup says in his book The C++ Programming Language, Designing and implementing a general input/output facility for a programming language is notoriously difficult. I do believe he most definitely did an excellent job, and the C++ IOstreams library is part of the reason for C++s success. IO streams provide an incredibly flexible yet simple way to design the input/output routines of any application. IOstreams can be used for a wide variety of data manipulations thanks to the following features: A stream is internally nothing but a series of characters. The characters may be either normal characters (char) or wide characters (wchar_t). Streams provide you with a universal character-based interface to any type of storage medium (for example, a file), without requiring you to know the details of how to write to the storage medium. Any object that can be written to one type of stream, can be written to all types of streams. In other words, as long as an object has a stream representation, any storage medium can accept objects with that stream representation. Streams work with built-in data types, and you can make user-defined types work with streams by overloading the insertion operator () to read objects from streams. The stream librarys unified approach makes it very friendly to use. Using a consistent interface for outputting to the screen and sending files over a network makes life easier. The programs below will show you what is possible. The IO stream class hierarchy is quite complicated, so rather than introduce you to the full hierarchy at this point, Ill start with explaining the concepts of the design and show you examples of streams in action. Once you are familiar with elements of the design and how to apply those concepts to design a robust I/O system for your software, an understanding of what belongs where in the hierarchy will come naturally. Guys do you really know what do input and output really mean? To get a good idea about what input and output are, think of information as a stream of characters. This makes sense because whatever we enter through a keyboard can only be characters. Suppose the user enters the number 7479....WAIT...! How do you know the user entered a number? The problem is that you dont really know. All you have is a set of 4 characters: 7, 4, 7 and 9. It is completely up to you, the programmer, whether you want the input to be a number, to be a string, or to be fodder for /dev/random; whether the characters can be valid for the desired type totally depends upon whether that type can interpret the characters in the input stream as a description for an object of that type. You have to get the input characters into a recognizable data type for them to be of any use other than as a character array. IO streams not only define the relation between a stream of characters and the standard data types but also allows you to define a relationship between a stream of characters and your own classes. It also allows you nearly limitless freedom to manipulate those streams both using object oriented interfaces and working directly on character buffers when necessary. (Of course some of the lower level manipulations may be undefined; for example, you cant probe forward into an input stream to see the future!) Do you know how do streams work? Streams are serial interfaces to storage, buffers files, or any other storage medium. The difference between storage media is intentionally hidden by the interface; you may not even know what kind of storage youre working with but the interface is exactly the same. The serial nature of streams is a very important element of their interface. You cannot directly make random access random reads or writes in a stream (unlike, say, using an array index to access any value you want) although you can seek to a position in a stream and perform a read at that point. Using a serial representation gives a consistent interface for all devices. Many devices have the capability of both producing and consuming data at the same time; if data is being continually produced, the simplest way to think about reading that data is by doing a fetch of the next characters in a stream. If that data hasnt been produced yet (the user hasnt typed anything, or the network is still busy processing a packet), you wait for more data to become available, and the read will return that data. Even if you try to seek past the end (or beginning) of a stream, the stream pointer (i.e. get or put pointer) will remain at the boundary, making the situation safe. (Compare this with accessing data off the end of an array, where the behavior is undefined.) The underlying low-level interface that corresponds to the actual medium very closely is a character buffer (the stream buffer, technically called the streambuf), which can be thought of as the backbone of the stream. Being a buffer, it does not hold the entire content of the stream, if the stream is large enough, so you cant use it for random access. The most important of the basic stream operations are: First, the stream is initialized with the appropriate type (like a std::string for a stringstream and the filename for an fstream) of values and suitable modes (like ios::in for input and ios::out for output and many more depending on the type of the stream). After that, you can specify where the I/O should occur, through the get and put pointers. Depending on how you open the stream, the location may already be set appropriately (for example, if you open a file with ios::app, your get pointer set at the end of the stream, allowing appends). Remember the member functions associated with setting the get and put pointers are: seekg()and seekp() for .dragging. the get and put pointer, respectively, to the position specified. Both seek methods take an argument (of type streampos) providing a position in the file relative to the beginning of the file (using ios::beg), the end of the file (using ios::end), or the current position (using ios::cur). You may also provide just a specific location, such as io::beg, for the beginning of the file. tellg() and tellp() provide the current location of the get and put pointers, respectively The following one-liners should clear up most questions: seekg(0); seekg(0,ios::beg); //sets the get pointer to the beginning. seekg(5,ios::beg); //sets the get pointer to 5 chars forward of the beginning. tellp(); tellg() //returns the current value of the put/get pointer seekp(-10,ios::end); //sets the put pointer to 10 chars before the end seekp(1,ios::cur); //proceeds to next char N.B: Be careful when seeking the put pointer into the middle of in the stream. If you put anything in the stream, it will directly into the stream at the put location, overwriting the previous contents. In other words, if you need to insert data in the middle of a stream, you have to manually move the data that would be overwritten. As a side note, if youre finding yourself doing that too often, then you may want to use a string representation of your data, which can simplify this kind of random access operation. Once youre at the right location in the stream, input and output is done through the > operators. If you want to input an object to the stream, use the >. The class for your object must, of course, have provided overloads for these methods. Heres a short example: //Inserts var into string (like objects are displayed by // putting them to cout) output_stream
Posted on: Fri, 21 Mar 2014 20:21:45 +0000

Trending Topics



Recently Viewed Topics




© 2015