QT框架下的文字操作(一)
阿新 • • 發佈:2018-11-09
簡介
檔案操作作為軟體開發中不可或缺的一環,將其獨立出來並形成一個模組就顯得十分必要。這樣不僅易於維護管理,而且易於在專案中整合。
文字型別
常用的文字型別包括:
- csv檔案
- dbf 檔案
- excel 檔案
- ini 檔案
- json 檔案
- xml 檔案
文字操作
- csv、dbf、ini、json、xml檔案
- 讀取
- 寫入
- excel 檔案
- 讀取
- 寫入
- 格式設定
- 插入圖表
程式碼實現
csv 檔案
csv檔案的實質就是在每行的各項資料之間新增逗號分隔符 ,,所有我們直接使用 QFile 和 QTextStream 去實現讀寫。
檔案開啟
在標頭檔案中
QFile* m_CSVFile;
QTextStream* m_textStream;
在cpp中
m_CSVFile = new QFile(fileName);
if (!m_CSVFile->open(flag))
qDebug() << "open failed:" << m_CSVFile->error();
m_textStream = new QTextStream (m_CSVFile);
其中,fileName為檔名,flag為檔案開啟模式,型別為 QIODevice::OpenModeFlag
enum OpenModeFlag {
NotOpen = 0x0000,
ReadOnly = 0x0001,
WriteOnly = 0x0002,
ReadWrite = ReadOnly | WriteOnly,
Append = 0x0004,
Truncate = 0x0008,
Text = 0x0010,
Unbuffered = 0x0020
};
檔案寫入
bool CsvUtil::setCSVData(const QList<QVariantList>& CSVList,bool overWrite) {
if (CSVList.empty())
return false;
if (!m_CSVFile->isOpen())
return false;
if (overWrite && !m_CSVFile->resize(0))
return false;
QString lineString = "";
bool isFirst = true;
Q_FOREACH(const QVariantList& lineData, CSVList) {
lineString = "";
isFirst = true;
Q_FOREACH (const QVariant& unitData,lineData) {
if (!isFirst)
lineString += ",";
isFirst = false;
lineString += unitData.toString();
}
lineString += "\n";
m_CSVFile->write(lineString.toLocal8Bit());
}
m_CSVFile->flush();
return true;
}
其中,CSVList中的每一個元素為要寫入的一行的資料,overWrite決定是否需要覆蓋文字中的原有資料。
檔案讀取
// 獲取第lineNum行的資料
QStringList CsvUtil::getCSVData(int lineNum)
{
m_textStream->seek(0);
int lineCount = 0;
QString lineData = "";
while (!m_textStream->atEnd())
{
lineData = m_textStream->readLine();
if (lineNum == lineCount)
return lineData.split(",");
lineCount++;
}
return QStringList();
}
// 獲取檔案所有資料
QList<QStringList> CsvUtil::getAllCSVData()
{
QList<QStringList> CSVList;
m_textStream->seek(0);
QString lineData = "";
while (!m_textStream->atEnd())
{
lineData = m_textStream->readLine();
CSVList.push_back(lineData.split(","));
}
return CSVList;
}
dbf檔案
DBF檔案是一種以二進位制進行儲存的表格資料檔案,其檔案內部有著嚴格的格式要求,具體由檔案頭和記錄項組成。具體參考 DBF檔案格式說明。
我們這裡使用第三方庫 QDbf 來實現對dbf檔案的讀寫。
QDbf github地址: https://github.com/IvanPinezhaninov/QDbf.
檔案開啟
在標頭檔案中
QDbf::QDbfTable m_table;
在cpp中
// fileName:檔名,openMode:開啟模式(QDbf::QDbfTable::OpenMode)
// fileCode:檔案編碼(QDbf::QDbfTable::Codepage)
if (!m_table.open(fileName, openMode))
qDebug() << QString("open dbf file failed,fileName:%1").arg(fileName);
if (!m_table.setCodepage(fileCode))
qDebug() << QString("set dbf file code failed,fileName:%1").arg(fileName);
其中:
enum OpenMode {
ReadOnly = 0,
ReadWrite
};
enum Codepage {
CodepageNotSet = 0,
IBM437,
IBM850,
IBM866,
Windows1250,
Windows1251,
Windows1252,
GB18030,
UnsupportedCodepage
};
檔案讀取
// @params: dataMaps:返回的一行一行的資料,key:列名,rowIndex:行序號,columnIndex:列序號
bool DbfUtil::getValue(QList<QVariantMap> &dataMaps, int beginRowIndex, int endRowIndex,
int beginColumnIndex, int endColumnIndex) {
dataMaps.clear();
if (!isOpen() || !m_table.seek(-1))
return false;
QVariantMap dataMap;
int rowIndex = -1, columnIndex = 0;
while (m_table.next()) {
rowIndex++;
if (rowIndex < beginRowIndex)
continue;
if (rowIndex > endRowIndex)
break;
dataMap.clear();
QDbf::QDbfRecord record = m_table.record();
for (columnIndex = 0; columnIndex < record.count(); columnIndex++) {
if (columnIndex < beginColumnIndex)
continue;
if (columnIndex > endColumnIndex)
break;
dataMap.insert(record.fieldName(columnIndex), record.value(columnIndex));
}
dataMaps.append(dataMap);
}
return true;
}
// @params: dataMaps:返回的一行一行的資料,key:列名,rowIndex:行序號,columnNames:列名
bool DbfUtil::getValue(QList<QVariantMap> &dataMaps, int beginRowIndex, int endRowIndex,
const QStringList &columnNames) {
dataMaps.clear();
if (!isOpen() || !m_table.seek(-1))
return false;
QVariantMap dataMap;
int rowIndex = -1, columnIndex = 0;
while (m_table.next()) {
rowIndex++;
if (rowIndex < beginRowIndex)
continue;
if (rowIndex > endRowIndex)
break;
dataMap.clear();
QDbf::QDbfRecord record = m_table.record();
for (columnIndex = 0; columnIndex < record.count(); columnIndex++) {
if (!columnNames.contains(record.fieldName(columnIndex)))
continue;
dataMap.insert(record.fieldName(columnIndex), record.value(columnIndex));
}
dataMaps.append(dataMap);
}
return true;
}
檔案修改
寫入
新增多行資料:
// @param dataMaps中的元素為一行資料
bool DbfUtil::addValue(const QList<QVariantMap> &dataMaps) {
if (!isOpen() || !m_table.last())
return false;
Q_FOREACH(const QVariantMap &dataMap, dataMaps) {
if (!m_table.addRecord())
return false;
for (auto it = dataMap.constBegin(); it != dataMap.constEnd(); it++) {
if (!m_table.setValue(it.key(), it.value()))
return false;
}
}
return true;
}
插入一行資料:
// @param dataMap:行資料,rowIndex:插入位置的行序號
bool DbfUtil::insertValue(const QVariantMap &dataMap, int rowIndex) {
if (!isOpen() || !m_table.seek(rowIndex - 1))
return false;
if (!m_table.addRecord())
return false;
for (auto it = dataMap.constBegin(); it != dataMap.constEnd(); it++) {
if (!m_table.setValue(it.key(), it.value()))
return false;
}
return true;
}
修改行資料:
// @param dataMap:行資料,rowIndex:修改位置的行序號,為-1時,修改所有行
bool DbfUtil::updateValue(const QVariantMap &dataMap, int rowIndex) {
if (!isOpen() || !m_table.seek(rowIndex))
return false;
// 修改所有行
if (-1 == rowIndex) {
while (m_table.next()) {
for (auto it = dataMap.constBegin(); it != dataMap.constEnd(); it++) {
if (!m_table.setValue(it.key(), it.value()))
return false;
}
}
}
// 修改指定行
else {
for (auto it = dataMap.constBegin(); it != dataMap.constEnd(); it++) {
if (!m_table.setValue(it.key(), it.value()))
return false;
}
}
return true;
}
刪除
刪除行資料:
// @param rowIndex:刪除位置的行序號,為-1時,刪除所有行
bool DbfUtil::removeValue(int rowIndex) {
if (!isOpen() || !m_table.seek(rowIndex))
return false;
// 刪除所有行
if (-1 == rowIndex) {
while (m_table.next()) {
if (!m_table.removeRecord())
return false;
}
return true;
}
// 刪除指定行
else {
return m_table.removeRecord();
}
}
PS:本人很少寫部落格,以後有空會常寫,如有不當之處還請大家指教-。-
本小節先寫到這,完整的文字操作原始碼,點選此處下載。