📄 str_0182.htm
字号:
}</PRE><P>Working with pointers and references has a drawback: you have to create an output file stream object on the heap and, in principle, you have to worry about deleting the object again, which might lead you into other dire straits.</P><P>In summary, creating a copy of a stream is not trivial and should only be done if you really need a copy of a stream object. In many cases, it is more appropriate to use references or pointers to stream objects instead, or to share a stream buffer between two streams. </P><HR><STRONG><P><I>Keep in mind: </I>Never create a copy of a stream object when a reference or a pointer to the stream object would suffice, or when a shared stream buffer would solve the problem.</P></STRONG><HR><A NAME="2.9.2"><H3>2.9.2 Sharing a Stream Buffer Among Streams</H3></A><P>Despite the previous caveats, there are situations where sharing a stream buffer among streams is useful and intended. Let us focus on these in this section.</P><A NAME="2.9.2.1"><H4>2.9.2.1 Several Format Settings for the Same Stream</H4></A><P>Imagine you need different formatting for different kinds of output to the same stream. Instead of switching the format settings between the different kinds of output, you can arrange for two separate streams to share a stream buffer. The streams would have different format settings, but write output to the same stream buffer. Here is an example:</P><PRE>ofstream file1("/tmp/x");ostream file2(file1.rdbuf()); \\1file1.setf(ios_base::fixed, ios_base::floatfield); \\2file1.precision(5);file2.setf(ios_base::scientific, ios_base::floatfield);file2.precision(3);file1 << setw(10) << 47.11 << '\n'; \\3file2 << setw(10) << 47.11 << '\n'; \\4</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>The stream buffer of <SAMP>file1</SAMP> is replaced by the stream buffer of <SAMP>file2</SAMP>. Afterwards, both streams share the buffer.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>Create different format settings for both files.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>The output here will be: 47.11000</TD></TR><TR VALIGN="top"><TD>//4</TD><TD>The output here will be: 4.711e+01</TD></TR></TABLE><P>Note that <SAMP>file2</SAMP> in the example above has to be an output stream rather than an output file stream. This is because file streams do not allow you to switch the file stream buffer.</P><A NAME="2.9.2.2"><H4>2.9.2.2 Several Locales for the Same Stream</H4></A><P>Similarly, you can use separate streams that share a stream buffer in order to avoid locale switches. This is useful when you have to insert multilingual text into the same stream. Here is an example:</P><PRE> ostringstream file1; ostream file2(file1.rdbuf()); file1.imbue(locale("De_DE")); file2.imbue(locale("En_US")); file1 << 47.11 << '\t'; file2 << 47.11 << '\n'; cout << file1.str() << endl; \\1</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>The output will be:<SAMP> 47,11 47.11</SAMP></TD></TR></TABLE><P>Again, there is a little snag. In Figure 16, note that a stream buffer has a locale object of its own, in addition to the stream's locale object. </P><H4>Figure 16. Locale objects and shared stream buffers</H4><BR><IMG SRC="images/image33.gif"><P><A HREF="arc_7049.htm#2.2.2.1">Section 2.2.2.1</A> explained the role of those two locale objects. To recap, the stream delegates the handling of numeric entities to its locale's numeric facets. The stream buffer uses its locale's code conversion facet for character-wise transformation between the buffer content and characters transported to and from the external device.</P><P>Usually the stream's locale and the stream buffer's locale are identical. However, when you share a stream buffer between two streams with different locales, you must decide which locale the stream buffer will use. </FN><P>You can set the stream buffer's locale by calling the <SAMP>pubimbue()</SAMP> function as follows:</P><PRE>..file1.imbue(locale("De_DE")); file2.imbue(locale("En_US")); file1.rdbuf()->pubimbue(locale("De_DE"));</PRE><A NAME="2.9.2.3"><H4>2.9.2.3 Input and Output to the Same Stream</H4></A><P>You can also use a shared stream buffer in order to have read <I>and</I> write access to a stream:</P><PRE>filebuf fbuf; //1 fbuf.open("/tmp/inout",ios_base::in|ios_base::out); //2 istream in(&fbuf); //3 ostream out(&fbuf); //4 cout << in.rdbuf(); //5 out << "..." << '\n' ; //6</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>Create a file buffer, and </TD></TR><TR VALIGN="top"><TD>//2</TD><TD>Connect it to a file. Note that you have to open the file in input and output mode if you want to read <I>and</I> write to it.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>Create an input stream that works with the file buffer <SAMP>fbuf</SAMP>.</TD></TR><TR VALIGN="top"><TD>//4</TD><TD>Create an output stream that also uses the file buffer <SAMP>fbuf</SAMP>.</TD></TR><TR VALIGN="top"><TD>//5</TD><TD>Read the entire content of the file and insert it into the standard output stream. Afterwards the file position is at the end of the file.<BR><BR>The most efficient way to read a file's entire content is through the <SAMP>rdbuf()</SAMP> function, which returns a pointer to the underlying stream buffer object. There is an inserter available that takes a stream buffer pointer, so you can insert the buffer's content into another stream.</TD></TR><TR VALIGN="top"><TD>//6</TD><TD>Write output to the file. As the current file position is the end of the file, all output will be inserted at the end.</TD></TR></TABLE><P>Naturally, it is easier and less error-prone to use bidirectional streams when you have to read and write to a file. The bidirectional equivalent to the example above would be:</P><PRE>fstream of("/tmp/inout"); cout << of.rdbuf(); of << "..." << '\n' ; </PRE><P>Notice that there is a difference between the solutions that you can see by comparing Figure 17 and Figure 18. An input and an output stream that share a stream buffer, as shown in Figure 17, can still have separate format settings, different locales, different exception masks, and so on. </P><H4>Figure 17. An input and an output stream sharing a stream buffer</H4><BR><IMG SRC="images/image34.gif"><P>In contrast, the bidirectional stream shown in Figure 18 can have only one format setting, one locale, and so on: </P><H4>Figure 18. A bidirectional stream</H4><BR><IMG SRC="images/image35.gif"><P>It seems clear that you cannot have different settings for input and output operations when you use a bidirectional stream. Still, it is advisable to use bidirectional file or string streams if you need to read and write to a file or string, instead of creating an input and an output stream that share a stream buffer. The bidirectional stream is easier to declare, and you do not have to worry about the stream buffer object's lifetime.</P><HR><STRONG><P>Please note: It's better to use one bidirectional file or string stream for reading and writing to a file or string, rather than two streams that share a stream buffer. </P></STRONG><HR><A NAME="2.9.3"><H3>2.9.3 Copies of the Stream Buffer</H3></A><P>The previous section showed how you can read the content of a file in its entirety by using the <SAMP>rdbuf()</SAMP> function. Let us now explore a variation of that example. Imagine another file containing some sort of header information that needs to be analyzed before we start appending the file. Instead of writing the current file content to the standard output stream, we want to process the content before we start adding to it. The easiest way to put the entire file content into a memory location for further processing is by creating a string stream and inserting the file's stream buffer into the string stream:</P><PRE>fstream fil("/tmp/inout"); stringstream header_stream; //1 header_stream << fil.rdbuf(); //2 // process the header, e.g. string word; header_stream >> word; //3</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>The easiest way to put the entire file content into a memory location for further processing is by creating a string stream, and</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>Inserting the file's stream buffer into the string stream.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>We now have the usual facilities of an input stream for reading and analyzing the header information; i.e., <SAMP>operator>>()</SAMP>, <SAMP>read()</SAMP>, <SAMP>get()</SAMP>, and so on.</TD></TR></TABLE><P>In cases where this procedure is insufficient, you should create a string that contains the header information and process the header by means of the string operations <SAMP>find()</SAMP>, <SAMP>compare()</SAMP>, etc.</P><PRE>fstream fil("/tmp/inout"); header_stream << fil.rdbuf(); string header_string = header_stream.str(); // process the header, e.g. string::size_type pos = header_string.rfind('.');</PRE><P>If the header contains binary data instead of text, even a string will probably not suffice. Here you would want to see the header as a plain byte sequence, i.e., an ordinary <SAMP>char*</SAMP> buffer. But note that a code conversion might already have been performed, depending on the locale attached to the file stream. In cases where you want to process binary data, you have to make sure that the attached locale has a non-converting code conversion facet:</P><PRE>fstream fil("/tmp/inout"); header_stream << fil.rdbuf(); string header_string = header_stream.str(); const char* header_char_ptr = header_string.data(); // process the header, e.g. int idx; memcpy((char*) &idx,header_char_ptr,sizeof(int));</PRE><P>A note on efficiency: If the header information is extensive, you will have to consider the number of copy operations performed in the previous example. Figure 19 shows how these copies are made:</P><H4>Figure 19: Copies of the file content</H4><BR><IMG SRC="images/image36.gif"><P>The content of the file is copied into the string stream's buffer when the pointer obtained through <SAMP>rdbuf()</SAMP> is inserted to the string stream. A second copy is created when the string stream's function <SAMP>str()</SAMP> is called. The call to the string's function <SAMP>data()</SAMP> does not create yet another copy, but returns a pointer to the string's internal data.</FN><HR><A HREF="man_6665.htm"><IMG SRC="images/prev.gif"></A> <A HREF="booktoc2.htm"><IMG SRC="images/toc.gif"></A><A HREF="syn_4687.htm"><IMG SRC="images/next.gif"></A><P>©Copyright 1996, Rogue Wave Software, Inc.</P></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -