Poco::FileStream

ファイルの読み書きを取り扱う Poco::FileStream、正確には、それを継承した Poco::FileInputStream, Poco::FileOutputStream を紹介します。
それだけだと内容が少なすぎるので、圧縮/伸長、エンコード/デコードをしながらのファイルの読み書きも紹介します。

FileTest.cpp

・スコープから外れたらファイルが削除されるように Poco::TemporaryFile を利用。
Poco::TeeOutputStream を使って、出力ストリームを分岐し、後で write/read の比較に使用。
Poco::StreamCopier を使って、入力ストリームを文字列にコピー。
Poco::CountingOutputStreamPoco::CountingInputStream とを使って、出力/入力ストリームの
 文字数/行数をチェック。
Poco::DeflatingOutputStreamPoco::InflatingInputStream とを使って、出力/入力ストリームを
 GZIP と ZLIB で圧縮/伸長。
Poco::Base64EncoderPoco::Base64Decoder とを使って、出力/入力ストリームを Base64 に
 エンコード/デコード。
Poco::HexBinaryEncoderPoco::HexBinaryDecoder とを使って、出力/入力ストリームを HexBinary
 にエンコード/デコード。
Poco::Net::QuotedPrintableEncoderPoco::Net::QuotedPrintableDecoder とを使って、出力/入力
 ストリームを QuotedPrintable にエンコード/デコード。

#include <Poco/FileStream.h>
#include <Poco/File.h>
#include <Poco/StreamCopier.h>
#include <Poco/TeeStream.h>
#include <Poco/InflatingStream.h>
#include <Poco/DeflatingStream.h>
#include <Poco/Base64Encoder.h>
#include <Poco/Base64Decoder.h>
#include <Poco/HexBinaryEncoder.h>
#include <Poco/HexBinaryDecoder.h>
#include <Poco/CountingStream.h>
#include <Poco/Net/QuotedPrintableEncoder.h>
#include <Poco/Net/QuotedPrintableDecoder.h>
#include <Poco/Format.h>
#include <Poco/TemporaryFile.h>
 
#include <string>
#include <sstream>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
 
typedef void (*TestRoutine)(ScopedLogMessage& msg);
 
const char* const kSampleText =
	"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
	"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
	"FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n"
	"SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n"
	"FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n"
	"ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n"
	"DEALINGS IN THE SOFTWARE.";
 
enum
{
	eStandard = 0
,	eGZIP
,	eZLIB
};
 
void TestSimple(ScopedLogMessage& msg)
{
	Poco::TemporaryFile file;
	std::ostringstream ostrBackup;
 
	msg.Message(" --- Simple file wrie/read ---");
	{
		Poco::FileOutputStream ostr(file.path());
		Poco::TeeOutputStream tos(ostr);
		tos.addStream(ostrBackup);
		tos << kSampleText;
	}
	msg.Message(Poco::format("  File size        : %z bytes", static_cast<std::size_t>(file.getSize())));
	{
		Poco::FileInputStream istr(file.path());
		std::string str;
		Poco::StreamCopier::copyToString(istr, str);
		msg.Message(Poco::format("  Write/Read check : %s", std::string(0 == str.compare(ostrBackup.str()) ? "OK":"NG")));
	}
}
 
void TestCountingStream(ScopedLogMessage& msg)
{
	Poco::TemporaryFile file;
	std::ostringstream ostrBackup;
 
	msg.Message(" --- Simple file wrie/read with counting stream ---");
	{
		Poco::FileOutputStream ostr(file.path());
		Poco::CountingOutputStream countingOstr(ostr);
		Poco::TeeOutputStream tos(countingOstr);
		tos.addStream(ostrBackup);
		tos << kSampleText;
 
		msg.Message(Poco::format("  Characters       : %d", countingOstr.chars()));
		msg.Message(Poco::format("  Lines            : %d", countingOstr.lines()));
	}
	msg.Message(Poco::format("  File size        : %z bytes", static_cast<std::size_t>(file.getSize())));
	{
		Poco::FileInputStream istr(file.path());
		Poco::CountingInputStream countingIstr(istr);
		std::string str;
		Poco::StreamCopier::copyToString(countingIstr, str);
		msg.Message(Poco::format("  Write/Read check : %s", std::string(0 == str.compare(ostrBackup.str()) ? "OK":"NG")));
		msg.Message(Poco::format("  Characters       : %d", countingIstr.chars()));
		msg.Message(Poco::format("  Lines            : %d", countingIstr.lines()));
	}
}
 
template <class Tenc, class Tdec, int sel>
class TestEncodeDecode
{
public:
	void Test(ScopedLogMessage& msg, const std::string& text)
	{
		Poco::TemporaryFile file;
		std::ostringstream ostrBackup;
 
		msg.Message(text);
		{
			Poco::FileOutputStream ostr(file.path());
			Tenc* encoder = Encoder(ostr, Int2Type<sel>());
			Poco::TeeOutputStream tos(*encoder);
			tos.addStream(ostrBackup);
			tos << kSampleText;
			delete encoder;
		}
		msg.Message(Poco::format("  File size        : %z bytes (%5.2f%% of original)"
				,	static_cast<std::size_t>(file.getSize())
				,	(100.0*file.getSize())/(std::string(kSampleText)).length()));
		{
			Poco::FileInputStream istr(file.path());
			Tdec* decoder = Decoder(istr, Int2Type<sel>());
			std::string str;
			Poco::StreamCopier::copyToString(*decoder, str);
			msg.Message(Poco::format("  Write/Read check : %s"
									, std::string(0 == str.compare(ostrBackup.str()) ? "OK":"NG")));
			delete decoder;
		}
	}
 
private:
	template <int v>
	struct Int2Type
	{
		enum {value = v};
	};
 
	Tenc* Encoder(Poco::FileOutputStream& ostr, Int2Type<eStandard>)
	{
		return (new Tenc(ostr));
	}
	Tenc* Encoder(Poco::FileOutputStream& ostr, Int2Type<eGZIP>)
	{
		return (new Tenc(ostr, Poco::DeflatingStreamBuf::STREAM_GZIP));
	}
	Tenc* Encoder(Poco::FileOutputStream& ostr, Int2Type<eZLIB>)
	{
		return (new Tenc(ostr, Poco::DeflatingStreamBuf::STREAM_ZLIB));
	}
	Tdec* Decoder(Poco::FileInputStream& istr, Int2Type<eStandard>)
	{
		return (new Tdec(istr));
	}
	Tdec* Decoder(Poco::FileInputStream& istr, Int2Type<eGZIP>)
	{
		return (new Tdec(istr, Poco::InflatingStreamBuf::STREAM_GZIP));
	}
	Tdec* Decoder(Poco::FileInputStream& istr, Int2Type<eZLIB>)
	{
		return (new Tdec(istr, Poco::InflatingStreamBuf::STREAM_ZLIB));
	}
};
 
void TestGZIPCompressed(ScopedLogMessage& msg)
{
	TestEncodeDecode<Poco::DeflatingOutputStream, Poco::InflatingInputStream, eGZIP> test;
	test.Test(msg, " --- GZIP compressing file wrie/read ---");
}
 
void TestZLIBCompressed(ScopedLogMessage& msg)
{
	TestEncodeDecode<Poco::DeflatingOutputStream, Poco::InflatingInputStream, eZLIB> test;
	test.Test(msg, " --- ZLIB compressing file wrie/read ---");
}
 
void TestBase64Encoding(ScopedLogMessage& msg)
{
	TestEncodeDecode<Poco::Base64Encoder, Poco::Base64Decoder, eStandard> test;
	test.Test(msg, " --- Base64 encoding file wrie/read ---");
}
 
void TestHexBinaryEncoding(ScopedLogMessage& msg)
{
	TestEncodeDecode<Poco::HexBinaryEncoder, Poco::HexBinaryDecoder, eStandard> test;
	test.Test(msg, " --- HexBinary encoding file wrie/read ---");
}
 
void TestQuotedPrintableEncoding(ScopedLogMessage& msg)
{
	TestEncodeDecode<Poco::Net::QuotedPrintableEncoder, Poco::Net::QuotedPrintableDecoder, eStandard> test;
	test.Test(msg, " --- QuotedPrintable encoding file wrie/read ---");
}
 
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);
 
	ScopedLogMessage msg("FileStreamTest ", "start", "end");
 
	TestRoutine tests[] = {	TestSimple
			,	TestCountingStream
			,	TestGZIPCompressed
			,	TestZLIBCompressed
			,	TestBase64Encoding
			,	TestHexBinaryEncoding
			,	TestQuotedPrintableEncoding	};
 
	for(std::size_t i=0; i<sizeof(tests)/sizeof(tests[0]); ++i)
	{
		msg.Message("");
		tests[i](msg);
	}
	msg.Message("");
 
	return 0;
}

Results of execution

[0] FileStreamTest start
[0] 
[0]  --- Simple file wrie/read ---
[0]   File size        : 473 bytes
[0]   Write/Read check : OK
[0] 
[0]  --- Simple file wrie/read with counting stream ---
[0]   Characters       : 473
[0]   Lines            : 7
[0]   File size        : 473 bytes
[0]   Write/Read check : OK
[0]   Characters       : 473
[0]   Lines            : 7
[0] 
[0]  --- GZIP compressing file wrie/read ---
[0]   File size        : 282 bytes (59.62% of original)
[0]   Write/Read check : OK
[0] 
[0]  --- ZLIB compressing file wrie/read ---
[0]   File size        : 270 bytes (57.08% of original)
[0]   Write/Read check : OK
[0] 
[0]  --- Base64 encoding file wrie/read ---
[0]   File size        : 648 bytes (137.00% of original)
[0]   Write/Read check : OK
[0] 
[0]  --- HexBinary encoding file wrie/read ---
[0]   File size        : 959 bytes (202.75% of original)
[0]   Write/Read check : OK
[0] 
[0]  --- QuotedPrintable encoding file wrie/read ---
[0]   File size        : 473 bytes (100.00% of original)
[0]   Write/Read check : OK
[0] 
[0] FileStreamTest end

Downloads

ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2010年5月21日からのダウンロード数:872

Subversion

・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。

Reference

POCO流ファイル処理あれこれ
http://pocoproject.org にある Streams のプレセンテーション。(PDF)

Powered by POCO Copyright © 2010 Round Square Inc. All rights reserved.


  1. i try to compile the program with vs2008/win-xp
    and get:

    1>—— Build started: Project: testFileStream, Configuration: Debug Win32 ——
    1>Compiling…
    1>testFileStream.cpp
    1>e:\program files\microsoft visual studio 9.0\vc\include\cstdio(53) : error C2039: ‘sprintf’ : is not a member of ‘`global namespace”
    1>e:\program files\microsoft visual studio 9.0\vc\include\cstdio(53) : error C2873: ‘sprintf’ : symbol cannot be used in a using-declaration
    1>e:\program files\microsoft visual studio 9.0\vc\include\cstdio(56) : error C2039: ‘vsprintf’ : is not a member of ‘`global namespace”
    1>e:\program files\microsoft visual studio 9.0\vc\include\cstdio(56) : error C2873: ‘vsprintf’ : symbol cannot be used in a using-declaration
    1>Build log was saved at “file://e:\schmidt_POCO\testFileStream\testFileStream\Debug\BuildLog.htm”
    1>testFileStream – 4 error(s), 0 warning(s)
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>