首先,需要创建两个类:CCsvFile(派生自CStdioFile,用于从屋里文件中读取数据)和CCsvRecord(派生自CObject,适合作为CCsvFile类的Object映射成员,包含指定行的数据。
1)CCsvRecord类的创建
由于每个CSV记录都包含很多列,所以增加一个名为m_arrCloumns的CStringArray类型的成员变量(该变量包含记录的真正数据):
protected:
CStringArray m_arrColumns;
接下来,编写构造函数,获得包含以逗号分隔记录的字符串数值。使用C语言的strtok函数来遍历字符串寻找逗号,每当找到一个逗号的时候,变量的token就包含逗号前面的值。然后,将这个值添加到m_arrColumns数组中。
char DELIMITERS[] = ",";
CCsvRecord::CCsvRecord(LPTSTR lpszRecord)
{
char *token;
token = strtok(lpszRecord, DELIMITERS);
while(NULL != token)
{
m_arrColumns.Add(token);
token = strtok(NULL, DELIMITERS);
}
}
最后,添加返回m_arrCloumns数据的大小和检索与一列相关的数据
UINT CCsvRecord::GetNbrOfColumns()
{
return m_arrColumns.GetSize();
}
CString CCsvRecord::GetColumn(UINT uiColumn)
{
CString strColumn;
if (((uiColumn >= 0) && (uiColumn <= (GetNbrOfColumns() - 1))))
{
strColumn = m_arrColumns[uiColumn];
}
return strColumn;
}
2)CCsvFile类的创建
首先,定义CCsvFile对象的集合,使用模板化的集合来保证类型的安全,并定义数组m_CsvRecordArray。EnsOfFile值是一个枚举型的值,用来判断是否到达文件尾。FileExists判断文件是否存在。m_dwNumberOfRecords返回数组的大小,即表示文件中包含的记录数。
typedef CTypedPtrArray<CObArray, CCsvRecord*> CCsvRecordArray;
class CCsvFile : public CStdioFile
{
public:
CCsvFile(LPSTR lpszFileName);
CCsvFile(CString& strFileName);
~CCsvFile();
protected:
void Initialize(LPSTR lpszFileName);
public:
enum
{
EndOfFile = -1
};
public:
static BOOL FileExists(LPCTSTR lpszFileName)
{
return (0 == (_access(lpszFileName, 4)));
}
protected:
DWORD LoadRecords();
protected:
DWORD m_dwNumberOfRecords;
public:
DWORD GetNumberOfRecords()
{
return m_dwNumberOfRecords;
}
protected:
CCsvRecordArray m_CsvRecordArray;
public:
UINT GetStartPosition();
void GetNextAssoc(UINT& rPosition, CCsvRecord** ppCsvRecord);
};
利用Initialize对两个构造函数进行初始化,读取物理文件并得出包含的记录数
CCsvFile::CCsvFile(LPSTR lpszFileName)
{
Initialize(lpszFileName);
}
CCsvFile::CCsvFile(CString& strFileName)
{
Initialize(strFileName.GetBuffer(0));
}
void CCsvFile::Initialize(LPSTR lpszFileName)
{
m_dwNumberOfRecords = 0;
ASSERT(lpszFileName != NULL);
ASSERT(AfxIsValidString(lpszFileName));
if (CCsvFile::FileExists(lpszFileName))
{
if (Open(lpszFileName, CFile::modeRead))
{
m_dwNumberOfRecords = LoadRecords();
}
}
}
DWORD CCsvFile::LoadRecords()
{
m_dwNumberOfRecords = 0;
CCsvRecord* pCsvRecord;
CString strRecord;
while (ReadString(strRecord))
{
pCsvRecord = new CCsvRecord(strRecord.GetBuffer(0));
ASSERT(pCsvRecord);
if (pCsvRecord)
{
m_CsvRecordArray.Add(pCsvRecord);
}
strRecord.ReleaseBuffer();
}
return m_CsvRecordArray.GetSize();
}
增加两个遍历记录数组的函数,GetStrarPosition和GetNextAssoc函数
UINT CCsvFile::GetStartPosition()
{
UINT uiPosition;
if (0 < m_CsvRecordArray.GetSize())
{
uiPosition = 0;
}
else
{
uiPosition = CCsvFile::EndOfFile;
}
return uiPosition;
}
void CCsvFile::GetNextAssoc(UINT& uiPosition, CCsvRecord** ppCsvRecord)
{
UINT uiNewPosition = CCsvFile::EndOfFile;
*ppCsvRecord = NULL;
UINT nRecords = m_CsvRecordArray.GetSize();
if (uiPosition >= 0 && uiPosition <= (nRecords - 1))
{
*ppCsvRecord = m_CsvRecordArray[uiPosition];
if ( (uiPosition + 1) <= (nRecords - 1) )
{
uiNewPosition = uiPosition + 1;
}
}
uiPosition = uiNewPosition;
}
最后,编写西沟函数来清楚前面分配的CCsvRecord对象:
CCsvFile::~CCsvFile()
{
CCsvRecord* pCsvRecord;
for (int i = m_CsvRecordArray.GetUpperBound(); i > -1; i--)
{
pCsvRecord = m_CsvRecordArray[i];
m_CsvRecordArray.RemoveAt(i);
ASSERT(pCsvRecord);
if (pCsvRecord)
{
delete pCsvRecord;
}
}
VERIFY(0 == m_CsvRecordArray.GetSize());
}
3)打印和显示CSV文件
单击Open事件,在实例化CCsvFile之后,只需在for循环中使用GetStratPosition和GetNextAssoc函数来检索CCsvRecord对象。并对每条记录调用InsertDataIntoListView函数。
void CCViewCSVDlg::OnButton1()
{
CFileDialog dlg(true);
if (IDOK == dlg.DoModal())
{
try
{
m_strFileName = dlg.GetPathName();
UpdateData(FALSE);
CCsvFile file(dlg.GetPathName());
CCsvRecord* pCsvRecord;
for (UINT uiRow = file.GetStartPosition();
CCsvFile::EndOfFile != uiRow;)
{
// get the actual record
file.GetNextAssoc(uiRow, &pCsvRecord);
if (pCsvRecord)
{
InsertDataIntoListView(uiRow, *pCsvRecord);
}
}
}
catch(CFileException* pe)
{
pe->ReportError();
}
}
SizeAllColumns();
}
void CCViewCSVDlg::InsertDataIntoListView(UINT uiRow, CCsvRecord& csvRecord)
{
// For each column in the passed record
for (int iCol = 0; iCol < csvRecord.GetNbrOfColumns(); iCol++)
{
// If this is the first row in the listview
if (uiRow == 1)
{
// Create the listview columns.
CString strColumnName;
strColumnName.Format("Col %ld", iCol);
m_lstFileContents.InsertColumn(iCol, strColumnName);
}
if (iCol == 0)
m_lstFileContents.InsertItem(m_lstFileContents.GetItemCount(),
csvRecord.GetColumn(iCol));
else
m_lstFileContents.SetItemText(m_lstFileContents.GetItemCount()-1,
iCol,csvRecord.GetColumn(iCol));
}
}
最后,设置好列表框的每列的宽度
void CCViewCSVDlg::SizeAllColumns()
{
CHeaderCtrl* pHeader = m_lstFileContents.GetHeaderCtrl();
ASSERT(pHeader);
if (pHeader)
{
// Turn off redraw until the columns have all
// been resized
m_lstFileContents.SetRedraw(FALSE);
for (int iCurrCol = 0;
iCurrCol < pHeader->GetItemCount();
iCurrCol++)
{
m_lstFileContents.SetColumnWidth(iCurrCol, LVSCW_AUTOSIZE);
int nCurrWidth = m_lstFileContents.GetColumnWidth(iCurrCol);
m_lstFileContents.SetColumnWidth(iCurrCol,
LVSCW_AUTOSIZE_USEHEADER);
int nColHdrWidth = m_lstFileContents.GetColumnWidth(iCurrCol);
m_lstFileContents.SetColumnWidth(iCurrCol,
max(nCurrWidth, nColHdrWidth));
}
// Now that sizing is finished, turn redraw back on and
// invalidate so that the control is repainted
m_lstFileContents.SetRedraw(TRUE);
m_lstFileContents.Invalidate();
}
}
4)相关函数:
token = strtok(lpszRecord, DELIMITERS);
typedef CTypedPtrArray<CObArray, CCsvRecord*> CCsvRecordArray;
return (0 == (_access(lpszFileName, 4)));
ASSERT(AfxIsValidString(lpszFileName));
for (int i = m_CsvRecordArray.GetUpperBound(); i > -1; i--)
m_CsvRecordArray.RemoveAt(i);
VERIFY(0 == m_CsvRecordArray.GetSize());
pCsvRecord = new CCsvRecord(strRecord.GetBuffer(0));
strRecord.ReleaseBuffer();
m_lstFileContents.InsertColumn(iCol, strColumnName);
m_lstFileContents.InsertItem(m_lstFileContents.GetItemCount(),csvRecord.GetColumn(iCol));
m_lstFileContents.SetItemText(m_lstFileContents.GetItemCount()-1,iCol,csvRecord.GetColumn(iCol));
m_lstFileContents.SetRedraw(FALSE);
m_lstFileContents.SetColumnWidth(iCurrCol, LVSCW_AUTOSIZE);
int nCurrWidth = m_lstFileContents.GetColumnWidth(iCurrCol);
m_lstFileContents.SetRedraw(TRUE);
m_lstFileContents.Invalidate();
posted on 2009-07-29 23:06
The_Moment 阅读(2858)
评论(2) 编辑 收藏 引用 所属分类:
VC实践