diff --git a/src/MiniExcel.Core/OpenXml/OpenXmlConfiguration.cs b/src/MiniExcel.Core/OpenXml/OpenXmlConfiguration.cs
index b3de0395..3a63df41 100644
--- a/src/MiniExcel.Core/OpenXml/OpenXmlConfiguration.cs
+++ b/src/MiniExcel.Core/OpenXml/OpenXmlConfiguration.cs
@@ -13,16 +13,24 @@ public class OpenXmlConfiguration : MiniExcelBaseConfiguration
public int FreezeRowCount { get; set; } = 1;
public int FreezeColumnCount { get; set; } = 0;
public bool EnableConvertByteArray { get; set; } = true;
+ public bool EnableWriteFilePath{ get; set; } = true;
public bool IgnoreTemplateParameterMissing { get; set; } = true;
public bool EnableWriteNullValueCell { get; set; } = true;
public bool WriteEmptyStringAsNull { get; set; } = false;
public bool TrimColumnNames { get; set; } = true;
public bool IgnoreEmptyRows { get; set; } = false;
+
public bool EnableSharedStringCache { get; set; } = true;
public long SharedStringCacheSize { get; set; } = 5 * 1024 * 1024;
+
+ ///
+ /// The directory where the shared strings cache files are stored.
+ /// It defaults to the system's temporary folder.
+ ///
+ public string SharedStringCachePath { get; set; } = Path.GetTempPath();
+
public OpenXmlStyleOptions StyleOptions { get; set; } = new();
public DynamicExcelSheetAttribute[]? DynamicSheets { get; set; }
- public bool EnableWriteFilePath{ get; set; } = true;
///
/// Calculate column widths automatically from each column value.
diff --git a/src/MiniExcel.Core/OpenXml/OpenXmlReader.cs b/src/MiniExcel.Core/OpenXml/OpenXmlReader.cs
index f3ee77db..17be9ab8 100644
--- a/src/MiniExcel.Core/OpenXml/OpenXmlReader.cs
+++ b/src/MiniExcel.Core/OpenXml/OpenXmlReader.cs
@@ -420,7 +420,7 @@ private async Task SetSharedStringsAsync(CancellationToken cancellationToken = d
#endif
if (_config.EnableSharedStringCache && sharedStringsEntry.Length >= _config.SharedStringCacheSize)
{
- SharedStrings = new SharedStringsDiskCache();
+ SharedStrings = new SharedStringsDiskCache(_config.SharedStringCachePath);
await foreach (var sharedString in XmlReaderHelper.GetSharedStringsAsync(stream, cancellationToken, Ns).ConfigureAwait(false))
{
SharedStrings[idx++] = sharedString;
diff --git a/src/MiniExcel.Core/OpenXml/Utils/SharedStringsDiskCache.cs b/src/MiniExcel.Core/OpenXml/Utils/SharedStringsDiskCache.cs
index bae9245c..bbc113bd 100644
--- a/src/MiniExcel.Core/OpenXml/Utils/SharedStringsDiskCache.cs
+++ b/src/MiniExcel.Core/OpenXml/Utils/SharedStringsDiskCache.cs
@@ -2,17 +2,17 @@
internal class SharedStringsDiskCache : IDictionary, IDisposable
{
+ private const int ExcelCellMaxLength = 32767;
private static readonly Encoding Encoding = new UTF8Encoding(true);
private readonly FileStream _positionFs;
private readonly FileStream _lengthFs;
private readonly FileStream _valueFs;
- private long _maxIndx = -1;
-
+ private long _maxIndex = -1;
private bool _disposedValue;
- public int Count => checked((int)(_maxIndx + 1));
+ public int Count => checked((int)(_maxIndex + 1));
public string this[int key]
{
@@ -20,25 +20,27 @@ public string this[int key]
set => Add(key, value);
}
- public bool ContainsKey(int key) => key <= _maxIndx;
+ public bool ContainsKey(int key) => key <= _maxIndex;
- public SharedStringsDiskCache()
+ public SharedStringsDiskCache(string sharedStringsCacheDir)
{
- var path = $"{Guid.NewGuid().ToString()}_miniexcelcache";
-
- _positionFs = new FileStream($"{path}_position", FileMode.OpenOrCreate);
- _lengthFs = new FileStream($"{path}_length", FileMode.OpenOrCreate);
- _valueFs = new FileStream($"{path}_data", FileMode.OpenOrCreate);
+ if (string.IsNullOrWhiteSpace(sharedStringsCacheDir) || !Directory.Exists(sharedStringsCacheDir))
+ throw new DirectoryNotFoundException($"\"{sharedStringsCacheDir}\" is not a valid directory for the shared strings cache.");
+
+ var prefix = $"{Path.GetRandomFileName()}_miniexcel";
+ _positionFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_position"), FileMode.OpenOrCreate);
+ _lengthFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_length"), FileMode.OpenOrCreate);
+ _valueFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_data"), FileMode.OpenOrCreate);
}
// index must start with 0-N
- internal void Add(int index, string value)
+ private void Add(int index, string value)
{
- if (index > _maxIndx)
- _maxIndx = index;
+ if (index > _maxIndex)
+ _maxIndex = index;
var valueBs = Encoding.GetBytes(value);
- if (value.Length > 32767) //check info length, becasue cell string max length is 47483647
+ if (value.Length > ExcelCellMaxLength) //check info length, becasue cell string max length is 47483647
throw new ArgumentOutOfRangeException("", "Excel one cell max length is 32,767 characters");
_positionFs.Write(BitConverter.GetBytes(_valueFs.Position), 0, 4);
@@ -105,13 +107,13 @@ public bool Remove(KeyValuePair item)
public IEnumerator> GetEnumerator()
{
- for (int i = 0; i < _maxIndx; i++)
+ for (int i = 0; i <= _maxIndex; i++)
yield return new KeyValuePair(i, this[i]);
}
IEnumerator IEnumerable.GetEnumerator()
{
- for (int i = 0; i < _maxIndx; i++)
+ for (int i = 0; i <= _maxIndex; i++)
yield return this[i];
}
diff --git a/tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs b/tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs
index 1d64866b..2e4a8f42 100644
--- a/tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs
+++ b/tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs
@@ -303,22 +303,19 @@ public void TestIssue360()
[Fact]
public void TestIssue117()
{
+ var cacheFull = new SharedStringsDiskCache(Path.GetTempPath());
+ for (int i = 0; i < 100; i++)
{
- var cache = new SharedStringsDiskCache();
- for (int i = 0; i < 100; i++)
- {
- cache[i] = i.ToString();
- }
- for (int i = 0; i < 100; i++)
- {
- Assert.Equal(i.ToString(), cache[i]);
- }
- Assert.Equal(100, cache.Count);
+ cacheFull[i] = i.ToString();
}
+ for (int i = 0; i < 100; i++)
{
- var cache = new SharedStringsDiskCache();
- Assert.Empty(cache);
+ Assert.Equal(i.ToString(), cacheFull[i]);
}
+ Assert.Equal(100, cacheFull.Count);
+
+ var cacheEmpty = new SharedStringsDiskCache(Path.GetTempPath());
+ Assert.Empty(cacheEmpty);
}
[Fact]