2013-04-03 46 views
0

假設你有一個包含以下文件:從具有固定的文件中讀取長記錄

  • 一個文件頭包括:1)第一個空的記錄號,二)的大小每個記錄,以及c)該文件可容納的最大記錄數。
  • 記錄包含:a)表示記錄是空閒還是佔用的字節,b)固定數量的字段。

當我想讀一個隨機記錄,我用這個函數:

int FixedLengthRecordFile :: read (int numRec, FixedLengthFieldsRecord & rec) 

的問題是,爲了讓此功能工作,我必須事先創建一個FixedLengthFieldsRecord,這意味着指定該記錄具有的字段數...這不是我想要的。我希望文件處理程序足夠「聰明」,足以識別該記錄有多少個字段,並在讀取它時即時創建一個FixedLengthFieldsRecord

我該如何做到這一點?該函數必須返回int,因爲我將其用作退出代碼(錯誤/成功)。

回答

2

潛在的,你可以定義FixedLengthFieldsRecord類,以便類本身強制執行正確的記錄長度,但允許領域的每個記錄任意號碼。一個可能的好方法是讓CONSTRUCTOR從文件中讀取下一條記錄。

該類(減去一些必要的錯誤檢查,您可以添加)可以按照與以下類似的方式編寫(該類假定您在創建此類的對象之前先讀取文件的第一行):

using namespace std; 
class FixedLengthFieldsRecord 
{ 

    public: 

     FixedLengthFieldsRecord(int const recordLength, istream & s); // Set the length of the record in the constructor 
     bool IsEmpty() const; 
     int FieldCount() const; // variable number of fields allowed; but LENGTH of record is enforced (see below) 

     bool IsValidRecord(); // Does the record contain the correct number of bytes? 
     string GetField(int const index) const; // This could throw an exception if the record is not valid 

    protected: 
     // Could have sophisticated functions here to replace fields, remove fields, reorder fields, etc. 

    // This section contains the actual implementation. 
    private: 
     vector<string> fields; // The vector contains a VARIABLE number of fields 
     bool is_empty; 
     bool is_valid; 
     int const record_length; // This contains the LENGTH of the record; it is set in the constructor and cannot be changed 

    // The following variable and function store (and access) ALL the records 
    static vector<FixedLengthFieldsRecord> records; 
    static read(int numRec, FixedLengthFieldsRecord & rec); 

} 

FixedLengthFieldsRecord::FixedLengthFieldsRecord(int const recordLength_, istream & s) 
    : record_length(recordLength) 
{ 
    // pseudocode provided here 
    // this functionality could be factored into other functions that are called by the constructor 

    is_valid = true; 

    is_empty = ReadFirstByte(s); // ReadFirstByte (not shown) reads first byte of current line and returns true if it indicates an empty record 

    if (!is_empty) 
    { 
     string field; 
     int currentRecordLength = 0; 
     while (ReadNextField(s, field)) // ReadNextField() returns true if another field was read from the line (i.e., not end-of-line 
     { 
      currentRecordLength+= field.length(); 
     } 
     if (currentRecordLength != record_length) 
     { 
      is_valid = false; 
     } 
     if (currentRecordLength > record_length) 
     { 
      break; 
     } 
     if (is_valid) 
     { 
      fields.push_back(field); 
     } 
    } 
    if (is_valid) 
    { 
     records.push_back(*this); // not efficient, nor thread safe - deep copy occurs here 
    } 
} 

bool FixedLengthFieldsRecord::IsEmpty() 
{ 
    return is_empty(); 
} 

bool FixedLengthFieldsRecord::IsValidRecord() 
{ 
    return is_valid; 
} 

string FixedLengthFieldsRecord::GetField(int const index) 
{ 
    if (!is_valid) 
    { 
     // throw an exception, or return an empty string 
    } 
    if (index < 0 || index >= fields.size()) 
    { 
     // throw an exception, or return an empty string 
    } 
    return fields[index]; 
} 

FixedLengthFieldsRecord::read(int numRec, FixedLengthFieldsRecord & rec) 
{ 
    if (numRec < 0 || numRec >= records.size()) 
    { 
     // throw an exception, or just return 
    } 
    rec = records[numRec]; 
} 
0

FixedLengthRecordFile應打開文件(或更好,走在構造函數中的std::istream),讀取頭,然後FixedLengthRecordFile::read(...)成員函數可以使用std::istream::seekgstd::istream::read獲取數據。

現在,你的實際問題。爲什麼你要FixedLengthRecordFile::read函數返回int,而它通過引用記錄?會不會像

FixedLengthFieldsRecord FixedLengthRecordFile::read(size_t numRec, int& foo); 

更容易?

如果你堅持你原來的簽名,使FixedLengthFieldsRecord默認構造函數初始化對象爲無效狀態(例如添加設置爲false一個bool isValid標誌),並添加setData(size_t length, const char* data)成員函數,然後可以通過調用FixedLengthRecordFile::read功能。

相關問題