From cb92f38921817a28ef6f6cf22540d36170ec22a2 Mon Sep 17 00:00:00 2001 From: Jason Petrik Date: Tue, 28 Oct 2025 09:23:25 -0700 Subject: [PATCH] Add StringTrimming option --- src/DbfDataReader/DbfDataReader.cs | 6 +++--- src/DbfDataReader/DbfDataReaderOptions.cs | 10 +++++++++ src/DbfDataReader/DbfRecord.cs | 6 ++++-- src/DbfDataReader/DbfTable.cs | 12 +++++++---- src/DbfDataReader/DbfValueString.cs | 24 ++++++++++++++++++++-- src/DbfDataReader/DbfValueWideString.cs | 25 +++++++++++++++++++++-- 6 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/DbfDataReader/DbfDataReader.cs b/src/DbfDataReader/DbfDataReader.cs index 775615a..21c7658 100644 --- a/src/DbfDataReader/DbfDataReader.cs +++ b/src/DbfDataReader/DbfDataReader.cs @@ -20,21 +20,21 @@ public DbfDataReader(string path) public DbfDataReader(string path, DbfDataReaderOptions options) { _options = options; - DbfTable = new DbfTable(path, options.Encoding); + DbfTable = new DbfTable(path, options.Encoding, options.StringTrimming); DbfRecord = new DbfRecord(DbfTable); } public DbfDataReader(Stream stream, DbfDataReaderOptions options) { _options = options; - DbfTable = new DbfTable(stream, options.Encoding); + DbfTable = new DbfTable(stream, options.Encoding, options.StringTrimming); DbfRecord = new DbfRecord(DbfTable); } public DbfDataReader(Stream stream, Stream memoStream, DbfDataReaderOptions options) { _options = options; - DbfTable = new DbfTable(stream, memoStream, options.Encoding); + DbfTable = new DbfTable(stream, memoStream, options.Encoding, options.StringTrimming); DbfRecord = new DbfRecord(DbfTable); } diff --git a/src/DbfDataReader/DbfDataReaderOptions.cs b/src/DbfDataReader/DbfDataReaderOptions.cs index 3190b05..e6bed36 100644 --- a/src/DbfDataReader/DbfDataReaderOptions.cs +++ b/src/DbfDataReader/DbfDataReaderOptions.cs @@ -8,9 +8,19 @@ public DbfDataReaderOptions() { SkipDeletedRecords = false; Encoding = null; + StringTrimming = StringTrimmingOption.Trim; } public bool SkipDeletedRecords { get; set; } public Encoding Encoding { get; set; } + public StringTrimmingOption StringTrimming { get; set; } + } + + public enum StringTrimmingOption + { + None, + Trim, + TrimStart, + TrimEnd, } } \ No newline at end of file diff --git a/src/DbfDataReader/DbfRecord.cs b/src/DbfDataReader/DbfRecord.cs index 553a4bc..46847e0 100644 --- a/src/DbfDataReader/DbfRecord.cs +++ b/src/DbfDataReader/DbfRecord.cs @@ -11,12 +11,14 @@ public class DbfRecord private const byte EndOfFile = 0x1a; private readonly Encoding _encoding; + private readonly StringTrimmingOption _stringTrimming; private readonly int _recordLength; private readonly byte[] _buffer; public DbfRecord(DbfTable dbfTable) { _encoding = dbfTable.CurrentEncoding; + _stringTrimming = dbfTable.StringTrimming; _recordLength = dbfTable.Header.RecordLength; _buffer = new byte[_recordLength]; @@ -77,10 +79,10 @@ private IDbfValue CreateDbfValue(DbfColumn dbfColumn, DbfMemo memo) break; case DbfColumnType.General: case DbfColumnType.Character: - value = new DbfValueString(dbfColumn.Start, dbfColumn.Length, _encoding); + value = new DbfValueString(dbfColumn.Start, dbfColumn.Length, _encoding, _stringTrimming); break; case DbfColumnType.WideCharacter: - value = new DbfValueWideString(dbfColumn.Start, dbfColumn.Length); + value = new DbfValueWideString(dbfColumn.Start, dbfColumn.Length, _stringTrimming); break; default: value = new DbfValueNull(dbfColumn.Start, dbfColumn.Length); diff --git a/src/DbfDataReader/DbfTable.cs b/src/DbfDataReader/DbfTable.cs index 21adea4..07ede02 100644 --- a/src/DbfDataReader/DbfTable.cs +++ b/src/DbfDataReader/DbfTable.cs @@ -9,12 +9,13 @@ public class DbfTable : Disposable { private const byte Terminator = 0x0d; - public DbfTable(string path, Encoding encoding = null) + public DbfTable(string path, Encoding encoding = null, StringTrimmingOption stringTrimming = StringTrimmingOption.Trim) { if (!File.Exists(path)) throw new FileNotFoundException(); Path = path; CurrentEncoding = encoding; + StringTrimming = stringTrimming; Stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); @@ -24,15 +25,16 @@ public DbfTable(string path, Encoding encoding = null) if (!string.IsNullOrEmpty(memoPath)) Memo = CreateMemo(memoPath); } - public DbfTable(Stream stream, Encoding encoding = null) - : this(stream, null, encoding) + public DbfTable(Stream stream, Encoding encoding = null, StringTrimmingOption stringTrimming = StringTrimmingOption.Trim) + : this(stream, null, encoding, stringTrimming) { } - public DbfTable(Stream stream, Stream memoStream, Encoding encoding = null) + public DbfTable(Stream stream, Stream memoStream, Encoding encoding = null, StringTrimmingOption stringTrimming = StringTrimmingOption.Trim) { Path = string.Empty; CurrentEncoding = encoding; + StringTrimming = stringTrimming; Stream = stream; Init(); @@ -60,6 +62,8 @@ private void Init() public IList Columns { get; private set; } + public StringTrimmingOption StringTrimming { get; private set; } + public bool IsClosed => Stream == null; public void Close() diff --git a/src/DbfDataReader/DbfValueString.cs b/src/DbfDataReader/DbfValueString.cs index 2565652..d4c0b1f 100644 --- a/src/DbfDataReader/DbfValueString.cs +++ b/src/DbfDataReader/DbfValueString.cs @@ -7,12 +7,18 @@ public class DbfValueString : DbfValue { private const char NullChar = '\0'; - public DbfValueString(int start, int length, Encoding encoding) : base(start, length) + public DbfValueString(int start, int length, Encoding encoding) : this(start, length, encoding, StringTrimmingOption.Trim) + { + } + + public DbfValueString(int start, int length, Encoding encoding, StringTrimmingOption stringTrimming) : base(start, length) { Encoding = encoding; + StringTrimming = stringTrimming; } protected readonly Encoding Encoding; + protected readonly StringTrimmingOption StringTrimming; public override void Read(ReadOnlySpan bytes) { @@ -23,7 +29,21 @@ public override void Read(ReadOnlySpan bytes) } var value = Encoding.GetString(bytes); - Value = value.Trim(NullChar, ' '); + Value = TrimString(value); + } + + private string TrimString(string value) + { + var trimmedNull = value.Trim(NullChar); + + return StringTrimming switch + { + StringTrimmingOption.None => trimmedNull, + StringTrimmingOption.Trim => trimmedNull.Trim(' '), + StringTrimmingOption.TrimStart => trimmedNull.TrimStart(' '), + StringTrimmingOption.TrimEnd => trimmedNull.TrimEnd(' '), + _ => trimmedNull.Trim(' '), + }; } } } \ No newline at end of file diff --git a/src/DbfDataReader/DbfValueWideString.cs b/src/DbfDataReader/DbfValueWideString.cs index b2635ac..022aa1a 100644 --- a/src/DbfDataReader/DbfValueWideString.cs +++ b/src/DbfDataReader/DbfValueWideString.cs @@ -7,9 +7,16 @@ public class DbfValueWideString : DbfValue { private const char NullChar = '\0'; - public DbfValueWideString(int start, int length) : base(start, length) + public DbfValueWideString(int start, int length) : this(start, length, StringTrimmingOption.Trim) { } + + public DbfValueWideString(int start, int length, StringTrimmingOption stringTrimming) : base(start, length) + { + StringTrimming = stringTrimming; + } + + protected readonly StringTrimmingOption StringTrimming; public override void Read(ReadOnlySpan bytes) { @@ -20,7 +27,21 @@ public override void Read(ReadOnlySpan bytes) } var value = Encoding.Unicode.GetString(bytes); - Value = value.Trim(NullChar, ' '); + Value = TrimString(value); + } + + private string TrimString(string value) + { + var trimmedNull = value.Trim(NullChar); + + return StringTrimming switch + { + StringTrimmingOption.None => trimmedNull, + StringTrimmingOption.Trim => trimmedNull.Trim(' '), + StringTrimmingOption.TrimStart => trimmedNull.TrimStart(' '), + StringTrimmingOption.TrimEnd => trimmedNull.TrimEnd(' '), + _ => trimmedNull.Trim(' '), + }; } } } \ No newline at end of file