首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

MFC C++ 使用 CStdioFile 讀取文本並過濾非法數據

     編輯:程式設計疑難解答

在 MFC 中使用 CStdioFile 讀取文本檔案時,若需過濾「非法數據」,關鍵在於明確定義何為「合法」,再針對每行進行解析驗證。本文提供完整讀取框架與三種常見驗證策略。

基礎讀取框架

CStdioFile file;
CString strLine;
CFileException ex;

if (!file.Open(_T("data.txt"), CFile::modeRead | CFile::typeText, &ex)) {
    ex.ReportError();
    return;
}

while (file.ReadString(strLine)) {
    strLine.Trim(); // 移除首尾空白/換行
    if (strLine.IsEmpty()) continue; // 跳過空行

    // === 此處放入驗證邏輯 ===
    if (IsValidLine(strLine)) {
        ProcessValidLine(strLine); // 解析、存入結構、顯示等
    } else {
        LogInvalidLine(strLine);   // 記錄或忽略
    }
}
file.Close();

三種常見「合法性」定義與驗證實現

1. 純數值格式驗證 (整數/浮點數)

要求每行為單一數字,或固定欄位數字:

bool IsValidLine(const CString& line) {
    // 允許:整數、負數、浮點數、科學記號
    // 正則:^[-+]?\d+(\.\d+)?([eE][-+]?\d+)?$
    // MFC 無內建正則,可用 ATL::CAtlRegExp 或手寫解析
    // 簡易版:逐字元檢查
    int len = line.GetLength();
    if (len == 0) return false;
    int i = 0;
    if (line[0] == '+' || line[0] == '-') i++;
    bool hasDigit = false, hasDot = false;
    for (; i < len; ++i) {
        TCHAR ch = line[i];
        if (ch >= '0' && ch <= '9') hasDigit = true;
        else if (ch == '.' && !hasDot) hasDot = true;
        else return false; // 非法字元
    }
    return hasDigit;
}

2. 固定欄位分隔格式 (CSV、Tab、固定寬度)

例:ID,Name,Score 三欄,Score 必為數字:

bool IsValidLine(const CString& line) {
    CString token;
    int curPos = 0;
    // 欄位 1: ID (非空)
    token = line.Tokenize(_T(","), curPos);
    if (token.IsEmpty()) return false;
    // 欄位 2: Name (非空)
    token = line.Tokenize(_T(","), curPos);
    if (token.IsEmpty()) return false;
    // 欄位 3: Score (數字)
    token = line.Tokenize(_T(","), curPos);
    if (token.IsEmpty()) return false;
    double val;
    // 簡易數字轉換檢查
    return _stscanf_s(token, _T("%lf"), &val) == 1;
}

3. 正則表達式驗證 (靈活、可維護)

引入 atlrx.h 使用 CAtlRegExp:

#include 

bool IsValidLine(const CString& line) {
    // 例:行首為 4 位年份,逗號,任意文字,逗號,浮點數
    static const TCHAR* pattern = _T("^\\d{4},.+,[-+]?\\d+(\\.\\d+)?$");
    CAtlRegExp<> re;
    REParseError status = re.Parse(pattern);
    if (status != REPARSE_ERROR_OK) return false; // 模式錯誤
    return re.Match(line) != FALSE;
}

進階:大檔案效能優化

  • 分塊讀取:CStdioFile 內部已緩衝,逐行 ReadString 通常足夠。
  • 避免重複編譯正則:將 CAtlRegExp 物件提升為成員/靜態,僅 Parse 一次。
  • 異步處理:若檔案超大 (GB 級),考慮放入工作線程,配合 PostMessage 更新 UI 進度。

總結

CStdioFile 本身不具備「判斷非法」能力,開發者必須:

  1. 業務上定義清楚「合法格式」(數值範圍、欄位數、編碼規則)。
  2. 在 ReadString 迴圈中逐行解析驗證。
  3. 根據複雜度選擇:手寫解析(高效能、簡單格式)、Tokenize 分欄(CSV 類)、正則(複雜/可變格式)。

建議先在獨立測試程式驗證邏輯,再整合至 MFC 專案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved