diff --git a/dBASE.NET.Tests/Writing.cs b/dBASE.NET.Tests/Writing.cs
index 0733ca7..f54156b 100644
--- a/dBASE.NET.Tests/Writing.cs
+++ b/dBASE.NET.Tests/Writing.cs
@@ -2,7 +2,7 @@
{
using System;
using System.IO;
-
+ using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
@@ -86,7 +86,61 @@ record = dbf.CreateRecord();
Assert.AreEqual("OUT THERE", dbf.Records[2][0], "Record content should be OUT THERE.");
}
+ [TestMethod]
+ public void WriteRecordAndDeleteIt()
+ {
+ dbf = new Dbf();
+ var field = new DbfField("TEST", DbfFieldType.Character, 12);
+ dbf.Fields.Add(field);
+ var record = dbf.CreateRecord();
+ record.Data[0] = "HELLO WORLD ! DELETE ME!";
+ dbf.DeleteRecord(0);
+ dbf.Write("test.dbf", DbfVersion.VisualFoxPro);
+ dbf = new Dbf();
+ dbf.Read("test.dbf",false);
+ Assert.AreEqual(0, dbf.Records.Count,"dbf should have no records");
+ }
+ [TestMethod]
+ public void WriteMultipleRecordsAndDeleteOne()
+ {
+ var dbf = new Dbf();
+ var field = new DbfField("TEST", DbfFieldType.Character, 12);
+ dbf.Fields.Add(field);
+ AddMultipleRecords(dbf,12);
+ dbf.DeleteRecord(0);
+ dbf.Write("test.dbf", DbfVersion.VisualFoxPro);
+ dbf = new Dbf();
+ dbf.Read("test.dbf", false);
+ Assert.AreEqual(11, dbf.Records.Count,"dbf should have 11 records");
+ }
+ [TestMethod]
+ public void WriteMultipleRecordsAndDeleteAll()
+ {
+ var dbf = new Dbf();
+ var field = new DbfField("TEST", DbfFieldType.Character, 12);
+ dbf.Fields.Add(field);
+ AddMultipleRecords(dbf, 12);
+ dbf.DeleteRecords(Enumerable.Range(0,12).ToArray());
+ dbf.Write("test.dbf", DbfVersion.VisualFoxPro);
+ dbf = new Dbf();
+ dbf.Read("test.dbf", false);
+ Assert.AreEqual(0, dbf.Records.Count, "dbf should have no record");
+ }
+ [TestMethod]
+ public void WriteRecordAndDeleteButLoadDeletedRecords()
+ {
+ dbf = new Dbf();
+ var field = new DbfField("TEST", DbfFieldType.Character, 12);
+ dbf.Fields.Add(field);
+ var record = dbf.CreateRecord();
+ record.Data[0] = "HELLO WORLD ! DELETE ME!";
+ dbf.DeleteRecord(0);
+ dbf.Write("test.dbf", DbfVersion.VisualFoxPro);
+ dbf = new Dbf();
+ dbf.Read("test.dbf");
+ Assert.AreEqual(0, dbf.Records.Count, "dbf should have no records");
+ }
[TestMethod]
public void NumericField()
{
@@ -96,7 +150,6 @@ public void NumericField()
DbfRecord record = dbf.CreateRecord();
record.Data[0] = 3.14;
dbf.Write("test.dbf", DbfVersion.VisualFoxPro);
-
dbf = new Dbf();
dbf.Read("test.dbf");
@@ -198,5 +251,16 @@ public void CurrencyField()
Assert.AreEqual((float) 4.34, dbf.Records[0][0], "Record content should be 4.34.");
}
+ private void AddMultipleRecords(Dbf dbf,int recordsLength)
+ {
+ for (int j = 0; j < recordsLength; ++j)
+ {
+ var record = dbf.CreateRecord();
+ for (int i = 0; i < dbf.Fields.Count; ++i)
+ {
+ record.Data[i] = $"test field {i}";
+ }
+ }
+ }
}
}
diff --git a/dBASE.NET/Dbf.cs b/dBASE.NET/Dbf.cs
index fb66fa7..ff610be 100644
--- a/dBASE.NET/Dbf.cs
+++ b/dBASE.NET/Dbf.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+ using System.Linq;
using System.Text;
///
@@ -11,8 +12,7 @@
///
public class Dbf
{
- private DbfHeader header;
-
+ private DbfHeader header;
///
/// Initializes a new instance of the .
///
@@ -64,21 +64,21 @@ public DbfRecord CreateRecord()
/// Opens a DBF file, reads the contents that initialize the current instance, and then closes the file.
///
/// The file to read.
- public void Read(string path)
- {
- // Open stream for reading.
+ public void Read(string path,bool loadDeleted = true)
+ {
+ // Open stream for reading.
using (FileStream baseStream = File.Open(path, FileMode.Open, FileAccess.Read))
{
string memoPath = GetMemoPath(path);
if (memoPath == null)
{
- Read(baseStream);
+ Read(baseStream,loadDeleted:loadDeleted);
}
else
{
using (FileStream memoStream = File.Open(memoPath, FileMode.Open, FileAccess.Read))
{
- Read(baseStream, memoStream);
+ Read(baseStream, memoStream,loadDeleted);
}
}
}
@@ -89,7 +89,7 @@ public void Read(string path)
///
/// Stream with a database.
/// Stream with a memo.
- public void Read(Stream baseStream, Stream memoStream = null)
+ public void Read(Stream baseStream, Stream memoStream = null,bool loadDeleted = true)
{
if (baseStream == null)
{
@@ -110,7 +110,7 @@ public void Read(Stream baseStream, Stream memoStream = null)
// After reading the fields, we move the read pointer to the beginning
// of the records, as indicated by the "HeaderLength" value in the header.
baseStream.Seek(header.HeaderLength, SeekOrigin.Begin);
- ReadRecords(reader, memoData);
+ ReadRecords(reader, memoData,loadDeleted);
}
}
@@ -197,15 +197,23 @@ private void ReadFields(BinaryReader reader)
reader.ReadByte();
}
- private void ReadRecords(BinaryReader reader, byte[] memoData)
+ private void ReadRecords(BinaryReader reader, byte[] memoData,bool loadDeleted)
{
Records.Clear();
// Records are terminated by 0x1a char (officially), or EOF (also seen).
while (reader.PeekChar() != 0x1a && reader.PeekChar() != -1)
{
+ var isDeletedMarker = (byte)reader.PeekChar() == (byte)0x2A;
+ if (isDeletedMarker)
+ {
+ reader.ReadBytes(header.RecordLength);
+ continue;
+ }
try
{
+
+
Records.Add(new DbfRecord(reader, header, Fields, memoData, Encoding));
}
catch (EndOfStreamException) { }
@@ -233,7 +241,25 @@ private void WriteRecords(BinaryWriter writer)
// Write EOF character.
writer.Write((byte)0x1a);
}
-
+ ///
+ /// Write the delete Mark as deleted
+ ///
+ /// /// the index of the file to be deleted
+ public void DeleteRecord(int index)
+ {
+ this.Records[index].DeleteRecord();
+ }
+ ///
+ /// Delete multiple records from theirs indexes on record list
+ ///
+ ///
+ public void DeleteRecords(params int[] indexes)
+ {
+ for (int i = 0; i < indexes.Length; i++)
+ {
+ DeleteRecord(indexes[i]);
+ }
+ }
private static string GetMemoPath(string basePath)
{
string memoPath = Path.ChangeExtension(basePath, "fpt");
diff --git a/dBASE.NET/DbfRecord.cs b/dBASE.NET/DbfRecord.cs
index 551a0ab..a433a53 100644
--- a/dBASE.NET/DbfRecord.cs
+++ b/dBASE.NET/DbfRecord.cs
@@ -25,7 +25,7 @@ internal DbfRecord(BinaryReader reader, DbfHeader header, List fields,
// Read record marker.
byte marker = reader.ReadByte();
-
+ Deleted = marker == 0x2A;
// Read entire record as sequence of bytes.
// Note that record length includes marker.
byte[] row = reader.ReadBytes(header.RecordLength - 1);
@@ -55,7 +55,7 @@ internal DbfRecord(List fields)
Data = new List