TextFileReader¶
BinaryFileReader
クラスを活用して、テキストファイルからテキストをstd::string
として読み込むクラスを実装する。- UTF-8 でエンコードされたテキストを想定すればよい。
TextFileReader.hpp
#pragma once
#include <memory> // std::shared_ptr
#include <string_view> // std::string_view
#include <string> // std::string
#include "Common.hpp"
namespace seccamp
{
/// @brief テキストファイルを読み込むクラス
class TextFileReader
{
public:
/// @brief デフォルトコンストラクタ
[[nodiscard]]
TextFileReader();
/// @brief ファイルをオープンします。
/// @param path ファイルパス
[[nodiscard]]
explicit TextFileReader(std::string_view path);
/// @brief ファイルがオープンされているかを返します。
/// @return オープンされている場合 true, それ以外の場合は false
[[nodiscard]]
bool isOpen() const noexcept;
/// @brief ファイルがオープンされているかを返します。
/// @return オープンされている場合 true, それ以外の場合は false
[[nodiscard]]
explicit operator bool() const noexcept;
/// @brief ファイルをオープンします。すでにオープンされている場合はクローズしてから再オープンします。
/// @param path ファイルパス
/// @return オープンに成功した場合 true, それ以外の場合は false
bool open(std::string_view path);
/// @brief ファイルをクローズします。
void close();
/// @brief ファイルから 1 行読み込みます。
/// @param line 読み込んだ文字列の格納先
/// @return 読み込みに成功した場合 true, それ以外の場合は false
bool readLine(std::string& line);
/// @brief ファイルの絶対パスを返します。
/// @return ファイルの絶対パス。ファイルがオープンされていない場合は空文字列
[[nodiscard]]
const std::string& fullPath() const noexcept;
private:
class Impl;
std::shared_ptr<Impl> m_pImpl;
};
}
TextFileReader.cpp
#include "TextFileReader.hpp"
#include "BinaryFileReader.hpp"
namespace seccamp
{
class TextFileReader::Impl
{
public:
Impl() = default;
~Impl()
{
close();
}
[[nodiscard]]
bool isOpen() const noexcept
{
return m_binaryFileReader.isOpen();
}
bool open(const std::string_view path)
{
return m_binaryFileReader.open(path);
}
void close()
{
m_binaryFileReader.close();
}
bool readLine(std::string& line)
{
line.clear();
int32 readBytes = 0;
for (;;)
{
char c = '\0';
// もし 1 バイト読み込めなかった場合
if (m_binaryFileReader.read(&c, 1) == 0)
{
if (readBytes == 0)
{
// EOF
return false;
}
else
{
break;
}
}
++readBytes;
if (c == '\r')
{
// CR の場合は無視
continue;
}
else if (c == '\n')
{
// LF の場合は一行読み込み完了
break;
}
line.push_back(c);
}
return true;
}
const std::string& fullPath() const noexcept
{
return m_binaryFileReader.fullPath();
}
private:
BinaryFileReader m_binaryFileReader;
};
TextFileReader::TextFileReader()
: m_pImpl{ std::make_shared<Impl>() } {}
TextFileReader::TextFileReader(const std::string_view path)
: TextFileReader{} // 移譲コンストラクタ
{
m_pImpl->open(path);
}
bool TextFileReader::isOpen() const noexcept
{
return m_pImpl->isOpen();
}
TextFileReader::operator bool() const noexcept
{
return m_pImpl->isOpen();
}
bool TextFileReader::open(const std::string_view path)
{
return m_pImpl->open(path);
}
void TextFileReader::close()
{
m_pImpl->close();
}
bool TextFileReader::readLine(std::string& line)
{
return m_pImpl->readLine(line);
}
const std::string& TextFileReader::fullPath() const noexcept
{
return m_pImpl->fullPath();
}
}
追加のチャレンジ¶
- UTF-8 BOM にも対応する。
BinaryFileReader
の追加のチャレンジを実装すると、BOM のチェックをopen()
時に簡単に行える。- 一定のサイズのバッファを用意してテキストを読み込むことでオーバーヘッドを抑える実装も考えられる。