コード例 #1
0
        /// <summary>
        /// Saves this <see cref="DataTable"/> as the specified file in the DBF/dBaseIII format
        /// </summary>
        /// <param name="dt">The DataTable to save</param>
        /// <param name="filepath">The fully-qualified path of the file to write to</param>
        public static void Save(this DataTable dt, string filepath)
        {
            DbfFile file = new DbfFile(dt);

            using (FileStream fs = new FileStream(filepath, FileMode.Create))
            {
                WriteHeader(file, fs);
                WriteFieldDescriptors(file, fs);
                WriteDataTableToStream(file, fs);
            }
        }
コード例 #2
0
ファイル: DbfFileWriter.cs プロジェクト: sraboy/skaa_editor
        /// <summary>
        /// Saves this <see cref="DataTable"/> as the specified file in the DBF/dBaseIII format
        /// </summary>
        /// <param name="dt">The DataTable to save</param>
        /// <param name="filepath">The fully-qualified path of the file to write to</param>
        public static void Save(this DataTable dt, string filepath)
        {
            DbfFile file = new DbfFile(dt);

            using (FileStream fs = new FileStream(filepath, FileMode.Create))
            {
                WriteHeader(file, fs);
                WriteFieldDescriptors(file, fs);
                WriteDataTableToStream(file, fs);
            }
        }
コード例 #3
0
ファイル: DbfFileWriter.cs プロジェクト: sraboy/skaa_editor
        /// <summary>
        /// Saves this <see cref="DataTable"/> to the specified stream in the DBF/dBaseIII format
        /// </summary>
        /// <param name="dt">The DataTable to save</param>
        /// <param name="str">The stream to which to write</param>
        public static void Save(this DataTable dt, Stream str)
        {
            DbfFile file = new DbfFile(dt);
            GetFieldDescriptorListFromSchema(file); //need to know how many we have to calculate below, before writing the header
            file.Header.LengthOfHeader += (short)(file.FieldDescriptors.Count * DbfFile.FieldDescriptor.Size);
            file.Header.LengthOfRecord = 1; //1 byte for RowState (0x20 or 0x2a)
            foreach (DataColumn col in dt.Columns)
                file.Header.LengthOfRecord += col.GetByteLength();

            WriteHeader(file, str);
            WriteFieldDescriptors(file, str);
            WriteDataTableToStream(file, str);
        }
コード例 #4
0
 private static void WriteHeader(DbfFile file, Stream str)
 {
     str.WriteByte(file.Header.Version);
     str.Write(file.Header.LastEdited, 0, 3);
     str.Write(BitConverter.GetBytes(file.Header.NumberOfRecords), 0, 4);
     str.Write(BitConverter.GetBytes(file.Header.LengthOfHeader), 0, 2);
     str.Write(BitConverter.GetBytes(file.Header.LengthOfRecord), 0, 2);
     str.Write(file.Header.ReservedOne, 0, 2);
     str.WriteByte(file.Header.IncompleteTransaction);
     str.WriteByte(file.Header.EncryptionFlag);
     str.Write(file.Header.FreeRecordThread, 0, 4);
     str.Write(file.Header.ReservedMultiUser, 0, 8);
     str.WriteByte(file.Header.MdxFlag);
     str.WriteByte(file.Header.Language);
     str.Write(file.Header.ReservedTwo, 0, 2);
 }
コード例 #5
0
        /// <summary>
        /// Saves this <see cref="DataTable"/> to the specified stream in the DBF/dBaseIII format
        /// </summary>
        /// <param name="dt">The DataTable to save</param>
        /// <param name="str">The stream to which to write</param>
        public static void Save(this DataTable dt, Stream str)
        {
            DbfFile file = new DbfFile(dt);

            GetFieldDescriptorListFromSchema(file); //need to know how many we have to calculate below, before writing the header
            file.Header.LengthOfHeader += (short)(file.FieldDescriptors.Count * DbfFile.FieldDescriptor.Size);
            file.Header.LengthOfRecord  = 1;        //1 byte for RowState (0x20 or 0x2a)
            foreach (DataColumn col in dt.Columns)
            {
                file.Header.LengthOfRecord += col.GetByteLength();
            }

            WriteHeader(file, str);
            WriteFieldDescriptors(file, str);
            WriteDataTableToStream(file, str);
        }
コード例 #6
0
        private static void GetFieldDescriptorListFromSchema(DbfFile file)
        {
            //http://www.clicketyclick.dk/databases/xbase/format/data_types.html

            file.FieldDescriptors = new List <DbfFile.FieldDescriptor>();

            int fieldAddr = 1; //first is always 1

            foreach (DataColumn col in file.DataTable.Columns)
            {
                DbfFile.FieldDescriptor fd = col.GetFieldDescriptor();
                fd.FieldDataAddress = BitConverter.GetBytes(fieldAddr);
                //FieldDataAddress is the index/offset of this field's data in a record, if the records were byte arrays
                file.FieldDescriptors.Add(fd);
                fieldAddr += fd.FieldLength; //sum each previous column's ByteLength, which equals the FieldLength
            }
        }
コード例 #7
0
ファイル: DbfFileWriter.cs プロジェクト: sraboy/skaa_editor
        private static void GetFieldDescriptorListFromSchema(DbfFile file)
        {
            //http://www.clicketyclick.dk/databases/xbase/format/data_types.html

            file.FieldDescriptors = new List<DbfFile.FieldDescriptor>();

            int fieldAddr = 1; //first is always 1

            foreach (DataColumn col in file.DataTable.Columns)
            {
                DbfFile.FieldDescriptor fd = col.GetFieldDescriptor();
                fd.FieldDataAddress = BitConverter.GetBytes(fieldAddr);
                //FieldDataAddress is the index/offset of this field's data in a record, if the records were byte arrays
                file.FieldDescriptors.Add(fd);
                fieldAddr += fd.FieldLength; //sum each previous column's ByteLength, which equals the FieldLength
            }
        }
コード例 #8
0
        /// <summary>
        /// Opens the specified <see cref="FileFormats.ResIdxDbf"/>, adds all of its tables and records to the <see cref="DataSet"/> and adds the file's name,
        /// from <see cref="Path.GetFileName(string)"/>, as a new data source
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns>false if <see cref="DbfFile.ReadStream(Stream)"/> returned false, true otherwise</returns>
        public static bool OpenStandardGameSet(this DataSet ds, string filePath)
        {
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                var defs = ResourceDefinitionReader.ReadDefinitions(fs, false);

                // Create a backup copy in the event Tables.Add() succeeds for one or more tables before
                // failing. This will allow us to just return false without mucking up the DataSet with
                // only some of the loaded tables.
                using (DataSet temp = new DataSet())
                {
                    temp.Merge(ds);

                    foreach (KeyValuePair <string, uint> kv in defs)
                    {
                        fs.Position = kv.Value; //the DBF's offset value in the set file
                        DbfFile file = new DbfFile();
                        if (file.ReadStream(fs) != true)
                        {
                            return(false);
                        }
                        file.DataTable.TableName = Path.GetFileNameWithoutExtension(kv.Key);
                        file.DataTable.AddDataSource(Path.GetFileName((fs as FileStream)?.Name));

                        if (ds.Tables.Contains(file.DataTable.TableName))
                        {
                            Logger.TraceEvent(TraceEventType.Error, 0, $"Failed to open standard game set due to a duplicate table: {file.DataTable.TableName} in {filePath}");
                            return(false);
                        }
                        else
                        {
                            temp.Tables.Add(file.DataTable);
                        }
                    }

                    // only add the tables once we're sure there are no duplicates
                    ds.Merge(temp);
                    ds.AddDataSource(Path.GetFileName(filePath));
                    Logger.TraceInformation($"Opened standard game set from: {filePath}");
                }
            }
            return(true);
        }
コード例 #9
0
        private static void WriteFieldDescriptors(DbfFile file, Stream str)
        {
            foreach (DbfFile.FieldDescriptor fd in file.FieldDescriptors)
            {
                StringBuilder sb = new StringBuilder(fd.FieldName);
                sb.Append((char)0x0, 11 - fd.FieldName.Length);
                string writeme = sb.ToString();
                str.Write(Encoding.UTF8.GetBytes(writeme), 0, 11);

                str.WriteByte((byte)fd.FieldType);
                str.Write(fd.FieldDataAddress, 0, 4);
                str.WriteByte(fd.FieldLength);
                str.WriteByte(fd.DecimalCount);
                str.Write(fd.ReservedMultiUserOne, 0, 2);
                str.WriteByte(fd.WorkAreaId);
                str.Write(fd.ReservedMultiUserTwo, 0, 2);
                str.WriteByte(fd.FlagSetFields);
                str.Write(fd.Reserved, 0, 7);
                str.WriteByte(fd.IndexFieldFlag);
            }

            str.WriteByte(0xD);
        }
コード例 #10
0
        private static void WriteDataTableToStream(DbfFile file, Stream str)
        {
            foreach (DataRow dr in file.DataTable.Rows)
            {
                str.WriteByte(DbfFile.RecordValidMarker);

                foreach (DataColumn col in file.DataTable.Columns)
                {
                    string value;

                    if (col.DataType == typeof(string))
                    {
                        byte[] bytes = new byte[col.GetByteLength()];
                        value = dr[col] == DBNull.Value ? " " : (string)dr[col];

                        if (col.ColumnName.EndsWith("PTR")) //actually a number (C pointer), not a string
                        {
                            int val = value == "0" ? Convert.ToInt32(0) : Convert.ToInt32(value);
                            bytes = BitConverter.GetBytes(val);
                        }
                        else
                        {
                            value = dr[col] == DBNull.Value ? string.Empty : (string)dr[col];
                            value = value.PadRight(col.GetByteLength(), ' ');
                            bytes = Encoding.GetEncoding(1252).GetBytes(value);
                        }
                        str.Write(bytes, 0, col.GetByteLength());
                    }
                    else if (col.DataType == typeof(long))
                    {
                        long val = dr[col] == DBNull.Value ? 0 : (long)dr[col];
                        value = val.ToString();
                        value = value.PadLeft(col.GetByteLength(), ' ');
                        byte[] bytes = new byte[col.GetByteLength()];
                        Encoding.GetEncoding(1252).GetBytes(value, 0, col.GetByteLength(), bytes, 0);
                        str.Write(bytes, 0, col.GetByteLength());
                    }
                    else
                    {
                        //todo: handle other DbfDataColumn types
                        throw new NotImplementedException(string.Format("Unknown DataColumn Type: {0}", col.DataType.ToString()));
                        //case 'L': //nullable bool, byte
                        //    throw new NotImplementedException("Encountered /'L/' for nullable bool!");
                        //    break;
                        //case 'D': //YYYYMMDD
                        //    throw new NotImplementedException("Encountered /'D/' for YYYYMMDD!");
                        //    break;
                        //case '@': //long1 = days since 1 Jan 4713, long2 = hrs * 3600000 + min * 60000 + sec * 1000
                        //    throw new NotImplementedException("Encountered /'@/' for time!");
                        //    break;
                        //case 'O': //double (8 bytes)
                        //    throw new NotImplementedException("Encountered /'O/' for double!");
                        //    break;
                        //case '+': //auto-increment (long)
                        //    throw new NotImplementedException("Encountered /'+/' for auto-increment!");
                        //    break;
                    }
                }
            }

            str.WriteByte(DbfFile.EofMarker);
        }
コード例 #11
0
ファイル: DbfFileWriter.cs プロジェクト: sraboy/skaa_editor
        private static void WriteDataTableToStream(DbfFile file, Stream str)
        {
            foreach (DataRow dr in file.DataTable.Rows)
            {
                str.WriteByte(DbfFile.RecordValidMarker);

                foreach (DataColumn col in file.DataTable.Columns)
                {
                    string value;

                    if (col.DataType == typeof(string))
                    {
                        byte[] bytes = new byte[col.GetByteLength()];
                        value = dr[col] == DBNull.Value ? " " : (string)dr[col];

                        if (col.ColumnName.EndsWith("PTR")) //actually a number (C pointer), not a string
                        {
                            int val = value == "0" ? Convert.ToInt32(0) : Convert.ToInt32(value);
                            bytes = BitConverter.GetBytes(val);
                        }
                        else
                        {
                            value = dr[col] == DBNull.Value ? string.Empty : (string)dr[col];
                            value = value.PadRight(col.GetByteLength(), ' ');
                            bytes = Encoding.GetEncoding(1252).GetBytes(value);
                        }
                        str.Write(bytes, 0, col.GetByteLength());
                    }
                    else if (col.DataType == typeof(long))
                    {
                        long val = dr[col] == DBNull.Value ? 0 : (long)dr[col];
                        value = val.ToString();
                        value = value.PadLeft(col.GetByteLength(), ' ');
                        byte[] bytes = new byte[col.GetByteLength()];
                        Encoding.GetEncoding(1252).GetBytes(value, 0, col.GetByteLength(), bytes, 0);
                        str.Write(bytes, 0, col.GetByteLength());
                    }
                    else
                    {
                        //todo: handle other DbfDataColumn types
                        throw new NotImplementedException(string.Format("Unknown DataColumn Type: {0}", col.DataType.ToString()));
                        //case 'L': //nullable bool, byte
                        //    throw new NotImplementedException("Encountered /'L/' for nullable bool!");
                        //    break;
                        //case 'D': //YYYYMMDD
                        //    throw new NotImplementedException("Encountered /'D/' for YYYYMMDD!");
                        //    break;
                        //case '@': //long1 = days since 1 Jan 4713, long2 = hrs * 3600000 + min * 60000 + sec * 1000
                        //    throw new NotImplementedException("Encountered /'@/' for time!");
                        //    break;
                        //case 'O': //double (8 bytes)
                        //    throw new NotImplementedException("Encountered /'O/' for double!");
                        //    break;
                        //case '+': //auto-increment (long)
                        //    throw new NotImplementedException("Encountered /'+/' for auto-increment!");
                        //    break;
                    }
                }
            }

            str.WriteByte(DbfFile.EofMarker);
        }
コード例 #12
0
ファイル: DbfFileWriter.cs プロジェクト: sraboy/skaa_editor
 private static void WriteHeader(DbfFile file, Stream str)
 {
     str.WriteByte(file.Header.Version);
     str.Write(file.Header.LastEdited, 0, 3);
     str.Write(BitConverter.GetBytes(file.Header.NumberOfRecords), 0, 4);
     str.Write(BitConverter.GetBytes(file.Header.LengthOfHeader), 0, 2);
     str.Write(BitConverter.GetBytes(file.Header.LengthOfRecord), 0, 2);
     str.Write(file.Header.ReservedOne, 0, 2);
     str.WriteByte(file.Header.IncompleteTransaction);
     str.WriteByte(file.Header.EncryptionFlag);
     str.Write(file.Header.FreeRecordThread, 0, 4);
     str.Write(file.Header.ReservedMultiUser, 0, 8);
     str.WriteByte(file.Header.MdxFlag);
     str.WriteByte(file.Header.Language);
     str.Write(file.Header.ReservedTwo, 0, 2);
 }
コード例 #13
0
ファイル: DbfFileWriter.cs プロジェクト: sraboy/skaa_editor
        private static void WriteFieldDescriptors(DbfFile file, Stream str)
        {
            foreach (DbfFile.FieldDescriptor fd in file.FieldDescriptors)
            {
                StringBuilder sb = new StringBuilder(fd.FieldName);
                sb.Append((char)0x0, 11 - fd.FieldName.Length);
                string writeme = sb.ToString();
                str.Write(Encoding.UTF8.GetBytes(writeme), 0, 11);

                str.WriteByte((byte)fd.FieldType);
                str.Write(fd.FieldDataAddress, 0, 4);
                str.WriteByte(fd.FieldLength);
                str.WriteByte(fd.DecimalCount);
                str.Write(fd.ReservedMultiUserOne, 0, 2);
                str.WriteByte(fd.WorkAreaId);
                str.Write(fd.ReservedMultiUserTwo, 0, 2);
                str.WriteByte(fd.FlagSetFields);
                str.Write(fd.Reserved, 0, 7);
                str.WriteByte(fd.IndexFieldFlag);
            }

            str.WriteByte(0xD);
        }
コード例 #14
0
        /// <summary>
        /// Opens the specified <see cref="FileFormats.ResIdxDbf"/>, adds all of its tables and records to the <see cref="DataSet"/> and adds the file's name, 
        /// from <see cref="Path.GetFileName(string)"/>, as a new data source
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns>false if <see cref="DbfFile.ReadStream(Stream)"/> returned false, true otherwise</returns>
        public static bool OpenStandardGameSet(this DataSet ds, string filePath)
        {
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                var defs = ResourceDefinitionReader.ReadDefinitions(fs, false);

                // Create a backup copy in the event Tables.Add() succeeds for one or more tables before 
                // failing. This will allow us to just return false without mucking up the DataSet with 
                // only some of the loaded tables.
                using (DataSet temp = new DataSet())
                {
                    temp.Merge(ds);

                    foreach (KeyValuePair<string, uint> kv in defs)
                    {
                        fs.Position = kv.Value; //the DBF's offset value in the set file
                        DbfFile file = new DbfFile();
                        if (file.ReadStream(fs) != true)
                            return false;
                        file.DataTable.TableName = Path.GetFileNameWithoutExtension(kv.Key);
                        file.DataTable.AddDataSource(Path.GetFileName((fs as FileStream)?.Name));

                        if (ds.Tables.Contains(file.DataTable.TableName))
                        {
                            Logger.TraceEvent(TraceEventType.Error, 0, $"Failed to open standard game set due to a duplicate table: {file.DataTable.TableName} in {filePath}");
                            return false;
                        }
                        else
                            temp.Tables.Add(file.DataTable);
                    }

                    // only add the tables once we're sure there are no duplicates
                    ds.Merge(temp);
                    ds.AddDataSource(Path.GetFileName(filePath));
                    Logger.TraceInformation($"Opened standard game set from: {filePath}");
                }
            }
            return true;
        }