diff --git a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs index 3509187..9ba96af 100644 --- a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs @@ -8,32 +8,26 @@ using System.Buffers; namespace IP2Region.Net.Internal.Abstractions; -internal abstract class AbstractCacheStrategy +internal abstract class AbstractCacheStrategy(string xdbPath) { - protected readonly FileStream XdbFileStream; private const int BufferSize = 4096; internal int IoCount { get; private set; } - protected AbstractCacheStrategy(string xdbPath) - { - XdbFileStream = new FileStream(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, - useAsync: true); - } - internal virtual ReadOnlyMemory GetData(int offset, int length) { byte[] buffer = ArrayPool.Shared.Rent(length); int totalBytesRead = 0; try { - XdbFileStream.Seek(offset, SeekOrigin.Begin); + var stream = GetXdbFileStream(); + stream.Seek(offset, SeekOrigin.Begin); int bytesRead; while (totalBytesRead < length) { int bytesToRead = Math.Min(BufferSize, length - totalBytesRead); - bytesRead = XdbFileStream.Read(buffer, totalBytesRead, bytesToRead); + bytesRead = stream.Read(buffer, totalBytesRead, bytesToRead); totalBytesRead += bytesRead; IoCount++; @@ -46,4 +40,15 @@ internal abstract class AbstractCacheStrategy return new ReadOnlyMemory(buffer, 0, totalBytesRead); } + + FileStream? _xdbFileStream; + + protected FileStream GetXdbFileStream() + { + if (_xdbFileStream == null) + { + _xdbFileStream = new FileStream(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.RandomAccess); + } + return _xdbFileStream; + } } diff --git a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs index c455521..0ef7251 100644 --- a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs @@ -8,19 +8,18 @@ using IP2Region.Net.Internal.Abstractions; namespace IP2Region.Net.Internal; -class ContentCacheStrategy : AbstractCacheStrategy +class ContentCacheStrategy(string xdbPath) : AbstractCacheStrategy(xdbPath) { - readonly ReadOnlyMemory _cacheData; - - public ContentCacheStrategy(string xdbPath) : base(xdbPath) - { - _cacheData = base.GetData(0, (int)XdbFileStream.Length); - XdbFileStream.Close(); - XdbFileStream.Dispose(); - } + ReadOnlyMemory _cacheData = ReadOnlyMemory.Empty; internal override ReadOnlyMemory GetData(int offset, int length) { + if (_cacheData.IsEmpty) + { + using var reader = base.GetXdbFileStream(); + _cacheData = base.GetData(0, (int)reader.Length); + } + return _cacheData.Slice(offset, length); } } diff --git a/binding/csharp/IP2Region.Net/XDB/Util.cs b/binding/csharp/IP2Region.Net/XDB/Util.cs index f593a9b..5f8673c 100644 --- a/binding/csharp/IP2Region.Net/XDB/Util.cs +++ b/binding/csharp/IP2Region.Net/XDB/Util.cs @@ -38,8 +38,13 @@ public static class Util throw new FileNotFoundException("xdb file not fould.", dbPath); } - XdbVersion ret = default; using var reader = File.OpenRead(dbPath); + return await GetVersionAsync(reader, token); + } + + internal static async Task GetVersionAsync(FileStream reader, CancellationToken token = default) + { + XdbVersion ret = default; var buffer = ArrayPool.Shared.Rent(256); try