Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Read an entire standard DBF file into a DataTable
- public static DataTable EncodedDataTable(string dbfFile)
- {
- long start = DateTime.Now.Ticks;
- DataTable dt = new DataTable();
- BinaryReader recReader;
- string number;
- string year;
- string month;
- string day;
- long lDate;
- long lTime;
- DataRow row;
- int fieldIndex;
- // If there isn't even a file, just return an empty DataTable
- if ((false == File.Exists(dbfFile)))
- {
- return dt;
- }
- BinaryReader br = null;
- try
- {
- // Read the header into a buffer
- br = new BinaryReader(File.OpenRead(dbfFile));
- byte[] buffer = br.ReadBytes(Marshal.SizeOf(typeof(DBFHeader)));
- // Marshall the header into a DBFHeader structure
- GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
- DBFHeader header = (DBFHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(DBFHeader));
- handle.Free();
- // Read in all the field descriptors. Per the spec, 13 (0D) marks the end of the field descriptors
- ArrayList fields = new ArrayList();
- while ((13 != br.PeekChar()))
- {
- buffer = br.ReadBytes(Marshal.SizeOf(typeof(FieldDescriptor)));
- handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
- fields.Add((FieldDescriptor)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(FieldDescriptor)));
- handle.Free();
- }
- // Read in the first row of records, we need this to help determine column types below
- ((FileStream)br.BaseStream).Seek(header.headerLen + 1, SeekOrigin.Begin);
- buffer = br.ReadBytes(header.recordLen);
- recReader = new BinaryReader(new MemoryStream(buffer));
- // Usput generiramo strukturu
- Struktura = new DataTable();
- Struktura.Columns.Add("NAME", typeof(string));
- Struktura.Columns.Add("TYPE", typeof(string));
- Struktura.Columns.Add("WIDTH", typeof(long));
- Struktura.Columns.Add("DECIMAL", typeof(long));
- // Create the columns in our new DataTable
- DataColumn col = null;
- foreach (FieldDescriptor field in fields)
- {
- number = Encoding.ASCII.GetString(recReader.ReadBytes(field.fieldLen));
- switch (field.fieldType)
- {
- case 'N':
- if (number.IndexOf(".") > -1)
- {
- col = new DataColumn(field.fieldName, typeof(decimal));
- }
- else
- {
- col = new DataColumn(field.fieldName, typeof(long));
- }
- Struktura.Rows.Add(field.fieldName, "N", field.fieldLen, field.count);
- break;
- case 'C':
- col = new DataColumn(field.fieldName, typeof(string));
- Struktura.Rows.Add(field.fieldName, "C", field.fieldLen, field.count);
- break;
- case 'T':
- // You can uncomment this to see the time component in the grid
- //col = new DataColumn(field.fieldName, typeof(string));
- col = new DataColumn(field.fieldName, typeof(DateTime));
- Struktura.Rows.Add(field.fieldName, "T", field.fieldLen, field.count);
- break;
- case 'D':
- col = new DataColumn(field.fieldName, typeof(DateTime));
- Struktura.Rows.Add(field.fieldName, "D", field.fieldLen, field.count);
- break;
- case 'L':
- col = new DataColumn(field.fieldName, typeof(bool));
- Struktura.Rows.Add(field.fieldName, "L", field.fieldLen, field.count);
- break;
- case 'F':
- col = new DataColumn(field.fieldName, typeof(Double));
- Struktura.Rows.Add(field.fieldName, "F", field.fieldLen, field.count);
- break;
- }
- dt.Columns.Add(col);
- }
- Struktura.AcceptChanges();
- // Skip past the end of the header.
- ((FileStream)br.BaseStream).Seek(header.headerLen, SeekOrigin.Begin);
- // Read in all the records
- for (int counter = 0; counter <= header.numRecords - 1; counter++)
- {
- // First we'll read the entire record into a buffer and then read each field from the buffer
- // This helps account for any extra space at the end of each record and probably performs better
- buffer = br.ReadBytes(header.recordLen);
- recReader = new BinaryReader(new MemoryStream(buffer));
- // All dbf field records begin with a deleted flag field. Deleted - 0x2A (asterisk) else 0x20 (space)
- if (recReader.ReadChar() == '*')
- {
- continue;
- }
- // Loop through each field in a record
- fieldIndex = 0;
- row = dt.NewRow();
- foreach (FieldDescriptor field in fields)
- {
- switch (field.fieldType)
- {
- case 'N': // Number
- // If you port this to .NET 2.0, use the Decimal.TryParse method
- number = Encoding.ASCII.GetString(recReader.ReadBytes(field.fieldLen));
- if (IsNumber(number))
- {
- var decimalCount = field.count; //<- Added this
- //REPLACED THIS: if (number.IndexOf(".") > -1) FOR:
- if (number.IndexOf(".") > -1 || decimalCount > 0)
- {
- //REPLACED THIS: row[fieldIndex] = decimal.Parse(number); FOR:
- row[fieldIndex] = decimal.Parse(number, System.Globalization.CultureInfo.InvariantCulture);
- }
- else
- {
- row[fieldIndex] = Convert.ToInt64(number);
- }
- }
- else
- {
- row[fieldIndex] = 0;
- }
- break;
- case 'C': // String *** Enkodirano 437 u 852
- row[fieldIndex] = EncodeString(Encoding.GetEncoding(852).GetString(recReader.ReadBytes(field.fieldLen)));
- //row[fieldIndex] = Encoding.ASCII.GetString(recReader.ReadBytes(field.fieldLen));
- break;
- case 'D': // Date (YYYYMMDD)
- year = Encoding.ASCII.GetString(recReader.ReadBytes(4));
- month = Encoding.ASCII.GetString(recReader.ReadBytes(2));
- day = Encoding.ASCII.GetString(recReader.ReadBytes(2));
- row[fieldIndex] = System.DBNull.Value;
- try
- {
- if (IsNumber(year) && IsNumber(month) && IsNumber(day))
- {
- if ((Int32.Parse(year) > 1900))
- {
- row[fieldIndex] = new DateTime(Int32.Parse(year), Int32.Parse(month), Int32.Parse(day));
- }
- }
- }
- catch
- { }
- break;
- case 'T': // Timestamp, 8 bytes - two integers, first for date, second for time
- // Date is the number of days since 01/01/4713 BC (Julian Days)
- // Time is hours * 3600000L + minutes * 60000L + Seconds * 1000L (Milliseconds since midnight)
- lDate = recReader.ReadInt32();
- lTime = recReader.ReadInt32() * 10000L;
- row[fieldIndex] = JulianToDateTime(lDate).AddTicks(lTime);
- break;
- case 'L': // Boolean (Y/N)
- if ('Y' == recReader.ReadByte())
- {
- row[fieldIndex] = true;
- }
- else
- {
- row[fieldIndex] = false;
- }
- break;
- case 'F':
- number = Encoding.ASCII.GetString(recReader.ReadBytes(field.fieldLen));
- if (IsNumber(number))
- {
- row[fieldIndex] = double.Parse(number);
- }
- else
- {
- row[fieldIndex] = 0.0F;
- }
- break;
- }
- fieldIndex++;
- }
- recReader.Close();
- dt.Rows.Add(row);
- }
- }
- catch
- {
- throw;
- }
- finally
- {
- if (null != br)
- {
- br.Close();
- }
- }
- long count = DateTime.Now.Ticks - start;
- return dt;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement