📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| 233行目: | 233行目: | ||
return true; | return true; | ||
} | |||
</syntaxhighlight> | |||
<br><br> | |||
== ストリーミング処理を使用したCSVファイルの読み込み == | |||
* ストリーミング処理 | |||
*: ファイル全体を1度にメモリに読み込むのではなく、1レコードずつ処理する。 | |||
*: これにより、大規模なファイルでもメモリ使用量を抑えることができる。 | |||
* コールバック関数 | |||
*: 各レコードの処理をコールバック関数として渡すことにより、柔軟な処理が可能になる。 | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QFile> | |||
#include <QTextStream> | |||
#include <QStringList> | |||
#include <functional> | |||
#include <QDebug> | |||
enum class CSVError { | |||
NoError, | |||
FileOpenError, | |||
ReadError, | |||
ParseError | |||
}; | |||
class CSVReader | |||
{ | |||
private: | |||
QString m_filename; | |||
public: | |||
CSVReader(const QString &filename) : m_filename(filename) {} | |||
CSVError readCSV(std::function<void(const QStringList&)> rowCallback) | |||
{ | |||
QFile file(m_filename); | |||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |||
qDebug() << "ファイルのオープンに失敗: " << m_filename; | |||
return CSVError::FileOpenError; | |||
} | |||
QTextStream in(&file); | |||
in.setCodec("UTF-8"); | |||
QString line; | |||
QStringList fields; | |||
bool inQuotes = false; | |||
QString field; | |||
qint64 lineNumber = 0; | |||
while (!in.atEnd()) { | |||
QChar ch; | |||
in >> ch; | |||
if (in.status() != QTextStream::Ok) { | |||
qDebug() << "読み込みエラー:" << m_filename << "行:" << lineNumber; | |||
return CSVError::ReadError; | |||
} | |||
if (inQuotes) { | |||
if (ch == '"') { | |||
if (in.peek() == '"') { | |||
field += ch; | |||
in >> ch; // 次の文字(二重引用符)を読み飛ばす | |||
} | |||
else { | |||
inQuotes = false; | |||
} | |||
} | |||
else { | |||
field += ch; | |||
} | |||
} | |||
else { | |||
if (ch == '"') { | |||
inQuotes = true; | |||
} | |||
else if (ch == ',' || ch == '\n' || in.atEnd()) { | |||
fields.append(field.trimmed()); | |||
field.clear(); | |||
if (ch == '\n' || in.atEnd()) { | |||
rowCallback(fields); | |||
fields.clear(); | |||
lineNumber++; | |||
} | |||
} | |||
else { | |||
field += ch; | |||
} | |||
} | |||
} | |||
if (inQuotes) { | |||
qDebug() << "パースエラー: 閉じていない引用符があります。行:" << lineNumber; | |||
return CSVError::ParseError; | |||
} | |||
file.close(); | |||
return CSVError::NoError; | |||
} | |||
}; | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
int main() | |||
{ | |||
CSVReader reader("example.csv"); | |||
CSVError error = reader.readCSV([](const QStringList& row) { | |||
// 各レコードの処理 | |||
qDebug() << row; | |||
}); | |||
switch (error) { | |||
case CSVError::NoError: | |||
qDebug() << "CSVファイルの読み込みに成功"; | |||
break; | |||
case CSVError::FileOpenError: | |||
qDebug() << "ファイルのオープンに失敗"; | |||
break; | |||
case CSVError::ReadError: | |||
qDebug() << "ファイルの読み込み中にエラーが発生"; | |||
break; | |||
case CSVError::ParseError: | |||
qDebug() << "CSVのパース中にエラーが発生"; | |||
break; | |||
} | |||
return 0; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||