Skip to content

Commit c09cb8c

Browse files
Changing shared strings cache path from Guid based to TempPath based (#897)
- Changing shared strings cache path from Guid based to TempPath based - Adding an option to OpenXmlConfiguration for manually overriding the path
1 parent 2027843 commit c09cb8c

File tree

4 files changed

+37
-30
lines changed

4 files changed

+37
-30
lines changed

src/MiniExcel.Core/OpenXml/OpenXmlConfiguration.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,24 @@ public class OpenXmlConfiguration : MiniExcelBaseConfiguration
1313
public int FreezeRowCount { get; set; } = 1;
1414
public int FreezeColumnCount { get; set; } = 0;
1515
public bool EnableConvertByteArray { get; set; } = true;
16+
public bool EnableWriteFilePath{ get; set; } = true;
1617
public bool IgnoreTemplateParameterMissing { get; set; } = true;
1718
public bool EnableWriteNullValueCell { get; set; } = true;
1819
public bool WriteEmptyStringAsNull { get; set; } = false;
1920
public bool TrimColumnNames { get; set; } = true;
2021
public bool IgnoreEmptyRows { get; set; } = false;
22+
2123
public bool EnableSharedStringCache { get; set; } = true;
2224
public long SharedStringCacheSize { get; set; } = 5 * 1024 * 1024;
25+
26+
/// <summary>
27+
/// The directory where the shared strings cache files are stored.
28+
/// It defaults to the system's temporary folder.
29+
/// </summary>
30+
public string SharedStringCachePath { get; set; } = Path.GetTempPath();
31+
2332
public OpenXmlStyleOptions StyleOptions { get; set; } = new();
2433
public DynamicExcelSheetAttribute[]? DynamicSheets { get; set; }
25-
public bool EnableWriteFilePath{ get; set; } = true;
2634

2735
/// <summary>
2836
/// Calculate column widths automatically from each column value.

src/MiniExcel.Core/OpenXml/OpenXmlReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ private async Task SetSharedStringsAsync(CancellationToken cancellationToken = d
420420
#endif
421421
if (_config.EnableSharedStringCache && sharedStringsEntry.Length >= _config.SharedStringCacheSize)
422422
{
423-
SharedStrings = new SharedStringsDiskCache();
423+
SharedStrings = new SharedStringsDiskCache(_config.SharedStringCachePath);
424424
await foreach (var sharedString in XmlReaderHelper.GetSharedStringsAsync(stream, cancellationToken, Ns).ConfigureAwait(false))
425425
{
426426
SharedStrings[idx++] = sharedString;

src/MiniExcel.Core/OpenXml/Utils/SharedStringsDiskCache.cs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,45 @@
22

33
internal class SharedStringsDiskCache : IDictionary<int, string>, IDisposable
44
{
5+
private const int ExcelCellMaxLength = 32767;
56
private static readonly Encoding Encoding = new UTF8Encoding(true);
67

78
private readonly FileStream _positionFs;
89
private readonly FileStream _lengthFs;
910
private readonly FileStream _valueFs;
1011

11-
private long _maxIndx = -1;
12-
12+
private long _maxIndex = -1;
1313
private bool _disposedValue;
1414

15-
public int Count => checked((int)(_maxIndx + 1));
15+
public int Count => checked((int)(_maxIndex + 1));
1616

1717
public string this[int key]
1818
{
1919
get => GetValue(key);
2020
set => Add(key, value);
2121
}
2222

23-
public bool ContainsKey(int key) => key <= _maxIndx;
23+
public bool ContainsKey(int key) => key <= _maxIndex;
2424

25-
public SharedStringsDiskCache()
25+
public SharedStringsDiskCache(string sharedStringsCacheDir)
2626
{
27-
var path = $"{Guid.NewGuid().ToString()}_miniexcelcache";
28-
29-
_positionFs = new FileStream($"{path}_position", FileMode.OpenOrCreate);
30-
_lengthFs = new FileStream($"{path}_length", FileMode.OpenOrCreate);
31-
_valueFs = new FileStream($"{path}_data", FileMode.OpenOrCreate);
27+
if (string.IsNullOrWhiteSpace(sharedStringsCacheDir) || !Directory.Exists(sharedStringsCacheDir))
28+
throw new DirectoryNotFoundException($"\"{sharedStringsCacheDir}\" is not a valid directory for the shared strings cache.");
29+
30+
var prefix = $"{Path.GetRandomFileName()}_miniexcel";
31+
_positionFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_position"), FileMode.OpenOrCreate);
32+
_lengthFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_length"), FileMode.OpenOrCreate);
33+
_valueFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_data"), FileMode.OpenOrCreate);
3234
}
3335

3436
// index must start with 0-N
35-
internal void Add(int index, string value)
37+
private void Add(int index, string value)
3638
{
37-
if (index > _maxIndx)
38-
_maxIndx = index;
39+
if (index > _maxIndex)
40+
_maxIndex = index;
3941

4042
var valueBs = Encoding.GetBytes(value);
41-
if (value.Length > 32767) //check info length, becasue cell string max length is 47483647
43+
if (value.Length > ExcelCellMaxLength) //check info length, becasue cell string max length is 47483647
4244
throw new ArgumentOutOfRangeException("", "Excel one cell max length is 32,767 characters");
4345

4446
_positionFs.Write(BitConverter.GetBytes(_valueFs.Position), 0, 4);
@@ -105,13 +107,13 @@ public bool Remove(KeyValuePair<int, string> item)
105107

106108
public IEnumerator<KeyValuePair<int, string>> GetEnumerator()
107109
{
108-
for (int i = 0; i < _maxIndx; i++)
110+
for (int i = 0; i <= _maxIndex; i++)
109111
yield return new KeyValuePair<int, string>(i, this[i]);
110112
}
111113

112114
IEnumerator IEnumerable.GetEnumerator()
113115
{
114-
for (int i = 0; i < _maxIndx; i++)
116+
for (int i = 0; i <= _maxIndex; i++)
115117
yield return this[i];
116118
}
117119

tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -303,22 +303,19 @@ public void TestIssue360()
303303
[Fact]
304304
public void TestIssue117()
305305
{
306+
var cacheFull = new SharedStringsDiskCache(Path.GetTempPath());
307+
for (int i = 0; i < 100; i++)
306308
{
307-
var cache = new SharedStringsDiskCache();
308-
for (int i = 0; i < 100; i++)
309-
{
310-
cache[i] = i.ToString();
311-
}
312-
for (int i = 0; i < 100; i++)
313-
{
314-
Assert.Equal(i.ToString(), cache[i]);
315-
}
316-
Assert.Equal(100, cache.Count);
309+
cacheFull[i] = i.ToString();
317310
}
311+
for (int i = 0; i < 100; i++)
318312
{
319-
var cache = new SharedStringsDiskCache();
320-
Assert.Empty(cache);
313+
Assert.Equal(i.ToString(), cacheFull[i]);
321314
}
315+
Assert.Equal(100, cacheFull.Count);
316+
317+
var cacheEmpty = new SharedStringsDiskCache(Path.GetTempPath());
318+
Assert.Empty(cacheEmpty);
322319
}
323320

324321
[Fact]

0 commit comments

Comments
 (0)