예제 #1
0
        public void CtorInitializedProperties()
        {
            var fixture = new Fixture();
            var value   = fixture.Create <bool>();

            var sut = new DbaseFileHeaderReadBehavior(value);

            Assert.Equal(value, sut.IgnoreFieldOffset);
        }
        public static DbaseFileHeader Read(BinaryReader reader, DbaseFileHeaderReadBehavior behavior)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }
            if (behavior == null)
            {
                throw new ArgumentNullException(nameof(behavior));
            }

            if (reader.ReadByte() != ExpectedDbaseFormat)
            {
                throw new DbaseFileHeaderException("The database file type must be 3 (dBase III).");
            }

            var lastUpdated = new DateTime(
                reader.ReadByte() + 1900,
                reader.ReadByte(),
                reader.ReadByte(),
                0,
                0,
                0,
                DateTimeKind.Unspecified);

            var recordCount  = new DbaseRecordCount(reader.ReadInt32());
            var headerLength = reader.ReadInt16();
            var fieldCount   = (headerLength - HeaderMetaDataSize) / FieldMetaDataSize;

            if (fieldCount > DbaseSchema.MaximumFieldCount)
            {
                throw new DbaseFileHeaderException(
                          $"The database file can not contain more than {DbaseSchema.MaximumFieldCount} fields.");
            }

            var recordLength = new DbaseRecordLength(reader.ReadInt16());

            reader.ReadBytes(17);
            var rawCodePage = reader.ReadByte();

            if (!DbaseCodePage.TryParse(rawCodePage, out var codePage))
            {
                throw new DbaseFileHeaderException($"The database code page {rawCodePage} is not supported.");
            }

            reader.ReadBytes(2);
            var fields = new DbaseField[fieldCount];

            for (var recordFieldIndex = 0; recordFieldIndex < fieldCount; recordFieldIndex++)
            {
                fields[recordFieldIndex] = DbaseField.Read(reader);
            }

            if (!behavior.IgnoreFieldOffset)
            {
                // verify field offsets are aligned
                var offset = ByteOffset.Initial;
                foreach (var field in fields)
                {
                    if (field.Offset != offset)
                    {
                        throw new DbaseFileHeaderException(
                                  $"The field {field.Name} does not have the expected offset {offset} but instead {field.Offset}. Please ensure the offset has been properly set for each field and that the order in which they appear in the record field layout matches their offset.");
                    }

                    offset = field.Offset.Plus(field.Length);
                }
            }

            var schema = new AnonymousDbaseSchema(fields);

            if (recordLength != schema.Length)
            {
                throw new DbaseFileHeaderException(
                          $"The database file record length ({recordLength}) does not match the total length of all fields ({schema.Length}).");
            }

            if (reader.ReadByte() != Terminator)
            {
                throw new DbaseFileHeaderException("The database file header terminator is missing.");
            }

            // skip to first record
            var bytesToSkip = headerLength - (HeaderMetaDataSize + FieldMetaDataSize * fieldCount);

            reader.ReadBytes(bytesToSkip);

            return(new DbaseFileHeader(lastUpdated, codePage, recordCount, schema));
        }