public static DataTable LoadSchema(DbfHeader dbf) { DataTable dtRet = new DataTable(); // Add the DBF fields to the DataTable foreach (DbfField fld in dbf.Fields) { DataColumn dc = new DataColumn(fld.FieldName.Trim()); switch (fld.FieldDataType) { case DbfHeader.dBaseFieldType.Character: dc.DataType = typeof(System.String); dc.MaxLength = fld.FieldLength; break; case DbfHeader.dBaseFieldType.Date: dc.DataType = typeof(System.DateTime); break; case DbfHeader.dBaseFieldType.Logical: dc.DataType = typeof(System.Boolean); break; case DbfHeader.dBaseFieldType.Memo: dc.DataType = typeof(System.Int32); break; case DbfHeader.dBaseFieldType.Numeric: dc.DataType = typeof(System.String); break; } dtRet.Columns.Add(dc); } return(dtRet); }
public DbfField(string fldName, DbfHeader.dBaseFieldType fldType, int recOffset, int fldLength, int decLength, int ordinal) { this.FieldNameHex = Hex.ToHex(Encoding.Unicode.GetBytes(fldName)); this.FieldTypeHex = Hex.ToHex(new byte[] { (byte)fldType }); this.RecordOffsetHex = Hex.ToHex(recOffset).PadLeft(8, '0'); this.FieldLength = fldLength; this.DecimalLength = decLength; this.Ordinal = ordinal; this.Owner = null; }
public static DbfTable WriteDbf(DataTable dt, FileStream fs, DbfHeader dbStruct) { // This string contains all the system data types that map to a // particular DBF data type. This saves from crazy-long // "if" statements. string numericType = "Int16,Int32,Int64,Float,Double,Decimal"; // This DbfField collection stores the info about the fields // in the DBF file we're creating. DbfFieldCollection flds = new DbfFieldCollection(); #region Write DBF Header // The first byte is the version identifier. // Here, we're specifying dBase IV. fs.WriteByte((byte)DbfHeader.dBaseType.dBase4WithOutMemo); // The next three bytes are the date that the file // was last modified. DateTime dtNow = DateTime.Now; fs.Write(new byte[] { (byte)(dtNow.Year - 1900), (byte)dtNow.Month, (byte)dtNow.Day }, 0, 3); // The next four bytes contain a count of the number of records // in the file. NOTE: these values are stored in reverse order. byte[] recCnt = Hex.GetBytes(Hex.ToHex(dt.Rows.Count).PadLeft(8, '0')); Array.Reverse(recCnt); fs.Write(recCnt, 0, 4); // The next two bytes indicate the offset to the start of the // actual data. NOTE: these values are stored in reverse order. // The base header takes 32 bytes and each field header takes an // additional 32 bytes. byte[] hdrSize = Hex.GetBytes(Hex.ToHex(32 + (dt.Columns.Count * 32)).PadLeft(4, '0')); Array.Reverse(hdrSize); fs.Write(hdrSize, 0, 2); // The next two bytes identify the size of each record. This number // represents the sum of all field lengths + 1, due to the first // byte of each record being a deletion flag. NOTE: these values // are stored in reverse order. int recLen = 0; foreach (DataColumn dc in dt.Columns) { recLen += (dc.MaxLength > 0) ? dc.MaxLength : 100; } byte[] recSize = Hex.GetBytes(Hex.ToHex(recLen + 1).PadLeft(4, '0')); Array.Reverse(recSize); fs.Write(recSize, 0, 2); // The next sixteen bytes are not used, so we just fill the // space with zeros. byte[] nullBytes = new byte[16]; nullBytes.Initialize(); fs.Write(nullBytes, 0, 16); // The next byte is the compound index flag. This flag should be set to // 0x01h if a stuctural CDX file is attached to the database. // At present, I don't know how to write or read these, so I will // hardcode this to 0x00h. fs.WriteByte(0x00); // The next three bytes are also not used, so fill with zeros. nullBytes = new byte[3]; nullBytes.Initialize(); fs.Write(nullBytes, 0, 3); #endregion #region Write Field Headers // Now we parse and write the header for each column. int fldOffset = 0; if (dbStruct != null) { flds = dbStruct.Fields; byte[] fldsHdr = dbStruct.Fields.GetRawHeader(); fs.Write(fldsHdr, 0, fldsHdr.Length); } else { foreach (DataColumn dc in dt.Columns) { DbfHeader.dBaseFieldType fldType; if (dc.DataType.Name == "DateTime") { fldType = DbfHeader.dBaseFieldType.Date; } else if (numericType.Contains(dc.DataType.Name)) { fldType = DbfHeader.dBaseFieldType.Numeric; } else if (dc.DataType.Name == "Boolean") { fldType = DbfHeader.dBaseFieldType.Logical; } else { fldType = DbfHeader.dBaseFieldType.Character; } string fldName = dc.ColumnName.Substring(0, (dc.ColumnName.Length <= 10) ? dc.ColumnName.Length : 10); //int fldSize = (dc.MaxLength > 0 || dc.DataType.Name != "String") ? dc.MaxLength : 100; int fldSize = 50; if (dc.DataType.Name == "DateTime") { fldSize = 8; } else if (dc.MaxLength > 0) { fldSize = dc.MaxLength; } flds.Add(new DbfField(fldName, fldType, fldOffset, fldSize, 0, dc.Ordinal)); fldOffset += fldSize; } byte[] fldsHdr = flds.GetRawHeader(); fs.Write(fldsHdr, 0, fldsHdr.Length); } #endregion #region Write DBF Data foreach (DataRow dr in dt.Rows) { // The first byte of every record is the deletion flag. fs.WriteByte(0x00); // Convert each value to a byte array & add it to the buffer. for (int i = 0; i < dbStruct.Fields.Count; i++) { byte[] record = new byte[0]; if (flds[i].FieldDataType == DbfHeader.dBaseFieldType.Date) { try { record = Array.ConvertAll <Char, Byte>(((DateTime)dr[i]).ToString("yyyyMMdd").ToCharArray(), new Converter <Char, Byte>(Convert.ToByte)); } catch (InvalidCastException) { record = Array.ConvertAll <Char, Byte>(" ".ToCharArray(), new Converter <Char, Byte>(Convert.ToByte)); } } else if (flds[i].FieldDataType == DbfHeader.dBaseFieldType.Memo) { record = Array.ConvertAll <Char, Byte>("00000000".ToCharArray(), new Converter <char, byte>(Convert.ToByte)); } else { record = Array.ConvertAll <Char, Byte>(dr[i].ToString().PadRight(flds[i].FieldLength, ' ').ToCharArray(), new Converter <Char, Byte>(Convert.ToByte)); } fs.Write(record, 0, record.Length); } } // Write the EOF markers. fs.WriteByte(0x1A); fs.WriteByte(0x1A); #endregion return(new DbfTable()); }
//*************************************************************************** // Class Constructors // public DbfTable() { this._hdr = new DbfHeader(this); }
public static DbfTable WriteDbf(DataTable dt, string filename, DbfHeader dbStruct) { using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write)) return(DbfTable.WriteDbf(dt, fs, dbStruct)); }
public static DataTable LoadSchema(DbfHeader dbf) { DataTable dtRet = new DataTable(); // Add the DBF fields to the DataTable foreach (DbfField fld in dbf.Fields) { DataColumn dc = new DataColumn(fld.FieldName.Trim()); switch (fld.FieldDataType) { case DbfHeader.dBaseFieldType.Character: dc.DataType = typeof(System.String); dc.MaxLength = fld.FieldLength; break; case DbfHeader.dBaseFieldType.Date: dc.DataType = typeof(System.DateTime); break; case DbfHeader.dBaseFieldType.Logical: dc.DataType = typeof(System.Boolean); break; case DbfHeader.dBaseFieldType.Memo: dc.DataType = typeof(System.Int32); break; case DbfHeader.dBaseFieldType.Numeric: dc.DataType = typeof(System.String); break; } dtRet.Columns.Add(dc); } return dtRet; }
public static DbfTable WriteDbf(DataTable dt, FileStream fs, DbfHeader dbStruct) { // This string contains all the system data types that map to a // particular DBF data type. This saves from crazy-long // "if" statements. string numericType = "Int16,Int32,Int64,Float,Double,Decimal"; // This DbfField collection stores the info about the fields // in the DBF file we're creating. DbfFieldCollection flds = new DbfFieldCollection(); #region Write DBF Header // The first byte is the version identifier. // Here, we're specifying dBase IV. fs.WriteByte((byte)DbfHeader.dBaseType.dBase4WithOutMemo); // The next three bytes are the date that the file // was last modified. DateTime dtNow = DateTime.Now; fs.Write(new byte[] { (byte)(dtNow.Year - 1900), (byte)dtNow.Month, (byte)dtNow.Day }, 0, 3); // The next four bytes contain a count of the number of records // in the file. NOTE: these values are stored in reverse order. byte[] recCnt = Hex.GetBytes(Hex.ToHex(dt.Rows.Count).PadLeft(8, '0')); Array.Reverse(recCnt); fs.Write(recCnt, 0,4); // The next two bytes indicate the offset to the start of the // actual data. NOTE: these values are stored in reverse order. // The base header takes 32 bytes and each field header takes an // additional 32 bytes. byte[] hdrSize = Hex.GetBytes(Hex.ToHex(32 + (dt.Columns.Count * 32)).PadLeft(4, '0')); Array.Reverse(hdrSize); fs.Write(hdrSize,0,2); // The next two bytes identify the size of each record. This number // represents the sum of all field lengths + 1, due to the first // byte of each record being a deletion flag. NOTE: these values // are stored in reverse order. int recLen = 0; foreach (DataColumn dc in dt.Columns) recLen += (dc.MaxLength > 0) ? dc.MaxLength : 100; byte[] recSize = Hex.GetBytes(Hex.ToHex(recLen + 1).PadLeft(4, '0')); Array.Reverse(recSize); fs.Write(recSize,0,2); // The next sixteen bytes are not used, so we just fill the // space with zeros. byte[] nullBytes = new byte[16]; nullBytes.Initialize(); fs.Write(nullBytes,0,16); // The next byte is the compound index flag. This flag should be set to // 0x01h if a stuctural CDX file is attached to the database. // At present, I don't know how to write or read these, so I will // hardcode this to 0x00h. fs.WriteByte(0x00); // The next three bytes are also not used, so fill with zeros. nullBytes = new byte[3]; nullBytes.Initialize(); fs.Write(nullBytes,0,3); #endregion #region Write Field Headers // Now we parse and write the header for each column. int fldOffset = 0; if (dbStruct != null) { flds = dbStruct.Fields; byte[] fldsHdr = dbStruct.Fields.GetRawHeader(); fs.Write(fldsHdr, 0, fldsHdr.Length); } else { foreach (DataColumn dc in dt.Columns) { DbfHeader.dBaseFieldType fldType; if (dc.DataType.Name == "DateTime") fldType = DbfHeader.dBaseFieldType.Date; else if (numericType.Contains(dc.DataType.Name)) fldType = DbfHeader.dBaseFieldType.Numeric; else if (dc.DataType.Name == "Boolean") fldType = DbfHeader.dBaseFieldType.Logical; else fldType = DbfHeader.dBaseFieldType.Character; string fldName = dc.ColumnName.Substring(0, (dc.ColumnName.Length <= 10) ? dc.ColumnName.Length : 10); //int fldSize = (dc.MaxLength > 0 || dc.DataType.Name != "String") ? dc.MaxLength : 100; int fldSize = 50; if (dc.DataType.Name == "DateTime") fldSize = 8; else if (dc.MaxLength > 0) fldSize = dc.MaxLength; flds.Add(new DbfField(fldName, fldType, fldOffset, fldSize, 0, dc.Ordinal)); fldOffset += fldSize; } byte[] fldsHdr = flds.GetRawHeader(); fs.Write(fldsHdr, 0, fldsHdr.Length); } #endregion #region Write DBF Data foreach (DataRow dr in dt.Rows) { // The first byte of every record is the deletion flag. fs.WriteByte(0x00); // Convert each value to a byte array & add it to the buffer. for (int i = 0; i < dbStruct.Fields.Count; i++) { byte[] record = new byte[0]; if (flds[i].FieldDataType == DbfHeader.dBaseFieldType.Date) { try { record = Array.ConvertAll<Char, Byte>(((DateTime)dr[i]).ToString("yyyyMMdd").ToCharArray(), new Converter<Char, Byte>(Convert.ToByte)); } catch (InvalidCastException) { record = Array.ConvertAll<Char, Byte>(" ".ToCharArray(), new Converter<Char, Byte>(Convert.ToByte)); } } else if (flds[i].FieldDataType == DbfHeader.dBaseFieldType.Memo) { record = Array.ConvertAll<Char, Byte>("00000000".ToCharArray(), new Converter<char, byte>(Convert.ToByte)); } else record = Array.ConvertAll<Char, Byte>(dr[i].ToString().PadRight(flds[i].FieldLength, ' ').ToCharArray(), new Converter<Char, Byte>(Convert.ToByte)); fs.Write(record, 0, record.Length); } } // Write the EOF markers. fs.WriteByte(0x1A); fs.WriteByte(0x1A); #endregion return new DbfTable(); }
public static DbfTable WriteDbf(DataTable dt, string filename, DbfHeader dbStruct) { using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write)) return DbfTable.WriteDbf(dt, fs, dbStruct); }
/// <summary> /// Retursn the System.Type equivalent to the supplied DbfHeader.dBaseFieldType. /// </summary> /// <param name="fldType">A DbfHeader.dBaseFieldType value to convert from.</param> /// <returns>An equivalent System.Type object.</returns> public static Type GetSystemDataType(DbfHeader.dBaseFieldType fldType) { switch (fldType) { case DbfHeader.dBaseFieldType.Logical: return typeof(System.Boolean); case DbfHeader.dBaseFieldType.Date: return typeof(System.DateTime); case DbfHeader.dBaseFieldType.DateTime: return typeof(System.DateTime); case DbfHeader.dBaseFieldType.Timestamp: return typeof(System.DateTime); case DbfHeader.dBaseFieldType.Memo: return typeof(System.String); case DbfHeader.dBaseFieldType.Numeric: return typeof(System.String); case DbfHeader.dBaseFieldType.Character: return typeof(System.String); case DbfHeader.dBaseFieldType.Unknown: return typeof(System.Object); case DbfHeader.dBaseFieldType.Long: return typeof(System.Int64); case DbfHeader.dBaseFieldType.Binary: return typeof(System.Int64); case DbfHeader.dBaseFieldType.AutoIncrement: return typeof(System.Int64); case DbfHeader.dBaseFieldType.Picture: return typeof(System.Byte[]); case DbfHeader.dBaseFieldType.FloatingPoint: return typeof(System.Double); } return typeof(System.String); }