Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ private void SetSharedStrings()
var idx = 0;
if (_config.EnableSharedStringCache && sharedStringsEntry.Length >= _config.SharedStringCacheSize)
{
_sharedStrings = new SharedStringsDiskCache();
_sharedStrings = new SharedStringsDiskCache(_config.SharedStringCachePath);
foreach (var sharedString in XmlReaderHelper.GetSharedStrings(stream, _ns))
_sharedStrings[idx++] = sharedString;
}
Expand Down
8 changes: 8 additions & 0 deletions src/MiniExcel/OpenXml/OpenXmlConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.IO;
using MiniExcelLibs.Attributes;

namespace MiniExcelLibs.OpenXml
Expand All @@ -18,6 +19,13 @@ public class OpenXmlConfiguration : Configuration
public bool IgnoreEmptyRows { get; set; } = false;
public bool EnableSharedStringCache { get; set; } = true;
public long SharedStringCacheSize { get; set; } = 5 * 1024 * 1024;

/// <summary>
/// The directory where the shared strings cache files are stored.
/// It defaults to the system's temporary folder.
/// </summary>
public string SharedStringCachePath { get; set; } = Path.GetTempPath();

public OpenXmlStyleOptions StyleOptions { get; set; } = new OpenXmlStyleOptions();
public DynamicExcelSheet[] DynamicSheets { get; set; }
public bool EnableWriteFilePath{ get; set; } = true;
Expand Down
17 changes: 10 additions & 7 deletions src/MiniExcel/OpenXml/SharedStringsDiskCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ public bool ContainsKey(int key)
return key <= _maxIndx;
}

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);
Comment on lines +32 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using FileMode.OpenOrCreate with a randomly generated file name could potentially lead to issues if a file with the same name already exists from a previous unclean shutdown. This might cause the cache to be created with incorrect data. To ensure that a new, empty file is always created, it would be safer to use FileMode.CreateNew. This mode throws an IOException if the file already exists, which would prevent accidental data corruption. Given the low probability of a name collision, this change would make the cache creation more robust.

            _positionFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_position"), FileMode.CreateNew);
            _lengthFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_length"), FileMode.CreateNew);
            _valueFs = new FileStream(Path.Combine(sharedStringsCacheDir, $"{prefix}_data"), FileMode.CreateNew);

}

// index must start with 0-N
Expand Down Expand Up @@ -140,13 +143,13 @@ public bool Remove(KeyValuePair<int, string> item)

public IEnumerator<KeyValuePair<int, string>> GetEnumerator()
{
for (int i = 0; i < _maxIndx; i++)
for (int i = 0; i <= _maxIndx; i++)
yield return new KeyValuePair<int, string>(i, this[i]);
}

IEnumerator IEnumerable.GetEnumerator()
{
for (int i = 0; i < _maxIndx; i++)
for (int i = 0; i <= _maxIndx; i++)
yield return this[i];
}

Expand Down
4 changes: 2 additions & 2 deletions tests/MiniExcelTests/MiniExcelIssueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ public void TestIssue360()
public void TestIssue117()
{
{
var cache = new SharedStringsDiskCache();
var cache = new SharedStringsDiskCache(Path.GetTempPath());
for (int i = 0; i < 100; i++)
{
cache[i] = i.ToString();
Expand All @@ -425,7 +425,7 @@ public void TestIssue117()
Assert.Equal(100, cache.Count);
}
{
var cache = new SharedStringsDiskCache();
var cache = new SharedStringsDiskCache(Path.GetTempPath());
Assert.Empty(cache);
}
}
Expand Down
Loading