[C++] Guo Laoer’s blog post: C++ directory
1. Description
POCO provides a variety of stream classes that are compatible with standard c++ IOStreams.
Most POCO stream classes are implemented as filters, which means that they do not write to or read from the device, but from another stream to which they are connected.
2. Text encoding and decoding
2.1 Description
POCO provides filter stream classes for encoding and decoding data in Base64 and HexBinary formats.
Both Base64 and HexBinary can be used to encode arbitrary binary data, using only printable ASCII characters.
Base64 uses numbers, uppercase and lowercase characters, and '+' and '-' to encode 6-bit groups. The encoded data takes up 1.33 times the space of the original data.
HexBinary uses numbers and the characters 'A' to 'F' to encode groups of 4 digits. Encoded data takes up twice the space.
2.2 Codec
Poco::Base64Encoder
Poco::HexBinaryEncoder
Poco::Base64Decoder
Poco::HexBinaryDecoder
#include "Poco/Base64Encoder.h"
#include <iostream>
using Poco::Base64Encoder;
int main(int argc, char** argv)
{
Base64Encoder encoder(std::cout);
encoder << "Hello, world!";
return 0;
}
Compile:
g++ enc.cpp -I ~/git/poco/install/include -L ~/git/poco/install/lib -lPocoFoundationd
output
SGVsbG8sIHdvcmxkIQ==
2. zlib compression
2.1 Related classes
压缩:
Poco::DeflatingInputStream
Poco::DeflatingOutputStream
解压:
Poco::InflatingInputStream
Poco::InflatingOutputStream
2.2 Example
#include "Poco/DeflatingStream.h"
#include <fstream>
using Poco::DeflatingOutputStream;
using Poco::DeflatingStreamBuf;
int main(int argc, char** argv)
{
std::ofstream ostr("test.gz", std::ios::binary);
DeflatingOutputStream deflater(ostr, DeflatingStreamBuf::STREAM_GZIP);
deflater << "Hello, world!";
// 确保在连接的流关闭之前清空缓冲区
deflater.close();
ostr.close();
return 0;
}
Compile:
g++ zlib.cpp -I ~/git/poco/install/include -L ~/git/poco/install/lib -lPocoFoundationd
3. Special flow
3.1 Statistics
Poco::CountingInputStream and Poco::CountingOutputStream
Count the number of characters and lines in a file. They also keep track of the current row number and column position.
3.2 Convert newlines
Poco::InputLineEndingConverter and Poco::OutputLineEndingConverter
Convert newlines between Unix (LF), DOS/Windows (CRLF), and Mac (CR).
#include "Poco/LineEndingConverter.h"
#include "Poco/FileStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/String.h"
#include <sstream>
#include <iostream>
using Poco::InputLineEndingConverter;
using Poco::LineEnding;
using Poco::StreamCopier;
using Poco::FileInputStream;
using Poco::FileOutputStream;
using Poco::icompare;
inline void dosToUnix(std::istream& input, std::ostream& output)
{
InputLineEndingConverter conv(input, LineEnding::NEWLINE_LF);
StreamCopier::copyStream(conv, output);
}
inline void unixToDos(std::istream& input, std::ostream& output)
{
InputLineEndingConverter conv(input, LineEnding::NEWLINE_CRLF);
StreamCopier::copyStream(conv, output);
}
inline int usage()
{
std::cout << "Usage: LineEndingConverter {u2d | d2u} filename" << std::endl;
return -1;
}
int main(int argc, char** argv)
{
if (argc < 3) return usage();
if (strlen(argv[1]) != 3) return usage();
std::string conv(argv[1]);
FileInputStream fis(argv[2]);
std::stringstream ss;
StreamCopier::copyStream(fis, ss);
fis.close();
FileOutputStream fos(argv[2]);
if (0 == icompare(conv, "u2d")) unixToDos(ss, fos);
else if (0 == icompare(conv, "d2u")) dosToUnix(ss, fos);
else return usage();
fos.flush();
return 0;
}
3.3 Copy flow
Poco::TeeInputStream and Poco::TeeOutputStream
Copies all characters (read or written) passing through them to one or more output streams
#include "Poco/TeeStream.h"
#include <iostream>
#include <fstream>
using Poco::TeeOutputStream;
int main(int argc, char** argv)
{
TeeOutputStream tee(std::cout);
std::ofstream fstr("output.txt");
tee.addStream(fstr);
tee << "Hello, world!" << std::endl;
return 0;
}
3.4 Empty flow
Poco::NullOutputStream: Discard all data written to it.
Poco::NullInputStream: Indicates the end of the file for each read operation.
3.5 Binary reading and writing
Poco::BinaryWriter: Used to write values of basic types into the output stream in binary form.
Poco::BinaryReader: Basic type used to read binary form (generated by Poco::BinaryWriter)
Both support writing and reading in big-endian and little-endian byte order, as well as automatic byte order conversion. These classes are useful for exchanging binary data between systems of different architectures.
#include "Poco/BinaryWriter.h"
#include "Poco/BinaryReader.h"
#include <sstream>
#include <iostream>
using Poco::BinaryWriter;
using Poco::BinaryReader;
int main(int argc, char** argv)
{
std::stringstream str;
BinaryWriter writer(str);
writer << true
<< 'x'
<< 42
<< 3.14159265
<< "foo bar";
bool b;
char c;
int i;
double d;
std::string s;
BinaryReader reader(str);
reader >> b
>> c
>> i
>> d
>> s;
std::cout << b << std::endl
<< c << std::endl
<< i << std::endl
<< d << std::endl
<< s << std::endl;
return 0;
}
4. File reading and writing
POCO provides stream classes for reading and writing files: FileStream, FileInputStream, FileOutputStream
Header file: #include “Poco/FileStream.h”
On Windows platforms, the path passed to the file stream is UTF-8 encoded.
File streams are always opened in binary mode. Support Seek.
#include "Poco/FileStream.h"
int main(int argc, char** argv)
{
Poco::FileStream str("test.txt", std::ios::out | std::ios::trunc);
str << "0123456789\n";
str << "abcdefghij\n";
str << "klmnopqrst\n";
str.close();
std::string s;
str.open("test.txt", std::ios::in);
std::getline(str, s);
str.close();
}
5. Custom flow
POCO provides stream buffer class templates, which simplifies the implementation of custom stream classes.
Streaming is implemented by first creating a stream buffer class (streambuf) and then adding the IOS, istream and ostream classes.
The available stream buffer class templates are as follows:
- Poco::BasicUnbufferedStreamBuf: is the simplest way to implement a custom stream.
- Poco::BasicBufferedStreamBuf: Class template that must be instantiated for character types.
- Poco::BasicBufferedBidirectionalStreamBuf
Subclasses need to reimplement the following functions
- int readFromDevice(): Read and return a single (unsigned) byte. If no more data is available, return char_traits::eof()(-1).
Note: Never return a char value directly, because char may be signed. Always use int charToInt(char c) to convert a character to an integer. - int writeToDevice(char c): Write a single byte. Returns bytes (as integer) if successful, otherwise char_traits::eof() (-1)