http://www.developer.com/net/cplus/article.php/3412961/Managed-Extensions-Using-the-NET-OLE-DB-Classes-to-Read-Text-Files.htm
Welcome to this week's installment of .NET Tips & Techniques! Each week, award-winning Architect and Lead Programmer Tom Archer demonstrates how to perform a practical .NET programming task using either C# or Managed C++ Extensions.
A previous .NET Tips & Techniques article illustrated how to access comma-delimited text files using the .NET ODBC classes. This week's tip covers performing the same task using the .NET OLE DB classes.
Note: If you're trying to decide which database-access technology to use—ODBC or OLE DB—I posted an article on my consulting Web site that compares ODBC to OLE DB.
No header row, file is delimited
Since these values are to be used in lieu of having a schema.ini file, you can find the valid values on the Microsoft Web site.
The following figure shows what the registry key looks like on my development machine:
To download the accompanying source code for this article, click here. The founder of the Archer Consulting Group (ACG), Tom Archer has been the project lead on three award-winning applications and is a best-selling author of 10 programming books as well as countless magazine and online articles.
Managed Extensions: Using the .NET OLE DB Classes to Read Text Files
September 28, 2004
Using the OLE DB Classes
Much like any of the database-access classes provided by the .NET BCL (Base Class Library), the OLE DB classes that you'll use most often represent a connection to the data source (OleDbConnection), a command object that will be executed against the data source (OleDbCommand), and a reader that is used to enumerate the results of a command (OleDbDataReader). Therefore, the standard process for reading any type of file using OLE DB classes is the following:
Specifying the Connection String
When formatting an OLE DB connection string, be aware of the following three main parts:
Note that I didn't mention how to change the FMT parameter of the Extended Properties. This is because if your file is delimited by something other than commas, you'll need to define a schema.ini file.
Extended Properties='text;HDR=No;FMT=Delimited'
Header row, file is delimited
Extended Properties='text;HDR=Yes;FMT=Delimited'
The schema.ini File
Since the Jet OLE DB provider uses the Microsoft Text Driver to access text files, you can define a schema.ini file just as you would if you were using ODBC to access the data. This is covered in
a previous article so I won't repeat all that here. However,
bare in mind that if a conflict exists between what you specify in the Extended Properties part of the OLE DB connection string and a parameter you specify in the schema.ini file, the schema.ini file will take precedence. For example, if you specify HDR=No in the connection string, but specify ColNameHeader=TRUE in the schema.ini file, then the file will be parsed as if the first row is a column header.
Demo Application
This article includes a simple demo that reads and displays the text from a small text file. Here's a screen shot of that application:
void CReadingCsvFilesWithOledbDlg::DisplayCsvFile()
{
#pragma push_macro("new")
#undef new
CWaitCursor wc;
m_lstCsvData.DeleteAllItems();
DeleteAllColumns(m_lstCsvData);
OleDbConnection* connection = NULL;
OleDbDataReader* reader = NULL;
try
{
StringBuilder* connString = new StringBuilder();
connString->Append(S"Provider=Microsoft.Jet.OLEDB.4.0;");
connString->AppendFormat(S"Data Source={0};", Path::GetDirectoryName(m_strFileName));
connString->Append(S"Extended Properties='text;HDR=No;FMT=TabDelimited'");
connection = new OleDbConnection(connString->ToString());
connection->Open();
CString strSelect;
strSelect.Format(_T("SELECT * FROM [%s]"), Path::GetFileName(m_strFileName));
OleDbCommand* command = new OleDbCommand(strSelect, connection);
reader = command->ExecuteReader();
int iCurrRow = 0;
while (reader->Read())
{
int idx;
for (int iCurrCol = 0; iCurrCol < reader->FieldCount; iCurrCol++)
{
if (0 == iCurrRow)
{
// assumes a schema.ini file
m_lstCsvData.InsertColumn(iCurrCol, (CString)reader->GetName(iCurrCol));
}
if (0 == iCurrCol)
{
idx = m_lstCsvData.InsertItem(iCurrRow, (CString)(reader->GetValue(iCurrCol)->ToString()));
}
else
m_lstCsvData.SetItemText(idx, iCurrCol, (CString)(reader->GetValue(iCurrCol)->ToString()));
}
iCurrRow++;
}
SizeAllColumns(m_lstCsvData);
}
catch(Exception* e)
{
m_strFileName = _T("");
UpdateData(FALSE);
AfxMessageBox((CString)e->Message);
}
__finally
{
if (NULL != reader) reader->Close();
if (NULL != connection) connection->Close();
}
#pragma pop_macro("new")
}
After looking at the screen shot and the following code, you should be able to surmise that I have a schema.ini file that specifies the names of the columns that are displayed in the listview control.
Using the Registry
If you do not wish to use a schema.ini file—for example, if you wanted a given machine to always handle text files the same way without having to maintain a bunch of separate schema.ini files and without having to hard-code the Extended Properties parameter to each OLE DB connection string—you can control how the Microsoft Text Driver works with your text files by modifying the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Text\Format
Download the Code
About the Author