diff --git a/NebulaStore.sln b/NebulaStore.sln
index 78b335f..d846551 100644
--- a/NebulaStore.sln
+++ b/NebulaStore.sln
@@ -1,134 +1,218 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.31903.59
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "storage", "storage", "{D0E78B5A-0D39-4CE8-A836-5FC8C7D60478}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "afs", "afs", "{F6G7H8I9-J0K1-2345-MNOP-QR6789012345}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "embedded", "embedded", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Storage.Embedded", "storage\embedded\NebulaStore.Storage.Embedded.csproj", "{08F6A698-C457-4D0E-8618-28836ABF02FD}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Storage.EmbeddedConfiguration", "storage\embedded-configuration\NebulaStore.Storage.EmbeddedConfiguration.csproj", "{B1C2D3E4-F5G6-7890-HIJK-LM1234567890}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Storage", "storage\storage\NebulaStore.Storage.csproj", "{C2D3E4F5-G6H7-8901-IJKL-MN2345678901}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Blobstore", "afs\blobstore\NebulaStore.Afs.Blobstore.csproj", "{E4F5G6H7-I8J9-0123-KLMN-OP4567890123}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Storage.Embedded.Tests", "storage\embedded\tests\NebulaStore.Storage.Embedded.Tests.csproj", "{2099EB97-32CB-4403-BF84-AD7F965FA520}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Blobstore.Tests", "afs\blobstore\test\NebulaStore.Afs.Blobstore.Tests.csproj", "{F5G6H7I8-J9K0-1234-LMNO-PQ5678901234}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Tests", "afs\tests\NebulaStore.Afs.Tests.csproj", "{G6H7I8J9-K0L1-2345-NOPQ-RS6789012345}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Examples.ConsoleApp", "examples\ConsoleApp\NebulaStore.Examples.ConsoleApp.csproj", "{D3E4F5G6-H7I8-9012-JKLM-NO3456789012}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.GigaMap", "gigamap\NebulaStore.GigaMap.csproj", "{H7I8J9K0-L1M2-3456-NOPQ-RS7890123456}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.GigaMap.Tests", "gigamap\tests\NebulaStore.GigaMap.Tests.csproj", "{I8J9K0L1-M2N3-4567-OPQR-ST8901234567}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "aws", "aws", "{J9K0L1M2-N3O4-5678-PQRS-TU9012345678}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Aws.S3", "afs\aws\s3\NebulaStore.Afs.Aws.S3.csproj", "{K0L1M2N3-O4P5-6789-QRST-UV0123456789}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Aws.S3.Tests", "afs\aws\s3\test\NebulaStore.Afs.Aws.S3.Tests.csproj", "{L1M2N3O4-P5Q6-7890-RSTU-VW1234567890}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azure", "azure", "{M2N3O4P5-Q6R7-8901-STUV-WX2345678901}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Azure.Storage", "afs\azure\storage\NebulaStore.Afs.Azure.Storage.csproj", "{N3O4P5Q6-R7S8-9012-TUVW-XY3456789012}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Azure.Storage.Tests", "afs\azure\storage\test\NebulaStore.Afs.Azure.Storage.Tests.csproj", "{Q7R8S9T0-U1V2-3456-WXYZ-AB4567890123}"
-EndProject
-
-
-
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {08F6A698-C457-4D0E-8618-28836ABF02FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {08F6A698-C457-4D0E-8618-28836ABF02FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {08F6A698-C457-4D0E-8618-28836ABF02FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {08F6A698-C457-4D0E-8618-28836ABF02FD}.Release|Any CPU.Build.0 = Release|Any CPU
- {B1C2D3E4-F5G6-7890-HIJK-LM1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B1C2D3E4-F5G6-7890-HIJK-LM1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B1C2D3E4-F5G6-7890-HIJK-LM1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B1C2D3E4-F5G6-7890-HIJK-LM1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
- {C2D3E4F5-G6H7-8901-IJKL-MN2345678901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C2D3E4F5-G6H7-8901-IJKL-MN2345678901}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C2D3E4F5-G6H7-8901-IJKL-MN2345678901}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C2D3E4F5-G6H7-8901-IJKL-MN2345678901}.Release|Any CPU.Build.0 = Release|Any CPU
- {2099EB97-32CB-4403-BF84-AD7F965FA520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2099EB97-32CB-4403-BF84-AD7F965FA520}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2099EB97-32CB-4403-BF84-AD7F965FA520}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2099EB97-32CB-4403-BF84-AD7F965FA520}.Release|Any CPU.Build.0 = Release|Any CPU
- {D3E4F5G6-H7I8-9012-JKLM-NO3456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D3E4F5G6-H7I8-9012-JKLM-NO3456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D3E4F5G6-H7I8-9012-JKLM-NO3456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D3E4F5G6-H7I8-9012-JKLM-NO3456789012}.Release|Any CPU.Build.0 = Release|Any CPU
- {E4F5G6H7-I8J9-0123-KLMN-OP4567890123}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E4F5G6H7-I8J9-0123-KLMN-OP4567890123}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E4F5G6H7-I8J9-0123-KLMN-OP4567890123}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E4F5G6H7-I8J9-0123-KLMN-OP4567890123}.Release|Any CPU.Build.0 = Release|Any CPU
- {F5G6H7I8-J9K0-1234-LMNO-PQ5678901234}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F5G6H7I8-J9K0-1234-LMNO-PQ5678901234}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F5G6H7I8-J9K0-1234-LMNO-PQ5678901234}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F5G6H7I8-J9K0-1234-LMNO-PQ5678901234}.Release|Any CPU.Build.0 = Release|Any CPU
- {G6H7I8J9-K0L1-2345-NOPQ-RS6789012345}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {G6H7I8J9-K0L1-2345-NOPQ-RS6789012345}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {G6H7I8J9-K0L1-2345-NOPQ-RS6789012345}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {G6H7I8J9-K0L1-2345-NOPQ-RS6789012345}.Release|Any CPU.Build.0 = Release|Any CPU
- {H7I8J9K0-L1M2-3456-NOPQ-RS7890123456}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {H7I8J9K0-L1M2-3456-NOPQ-RS7890123456}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {H7I8J9K0-L1M2-3456-NOPQ-RS7890123456}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {H7I8J9K0-L1M2-3456-NOPQ-RS7890123456}.Release|Any CPU.Build.0 = Release|Any CPU
- {I8J9K0L1-M2N3-4567-OPQR-ST8901234567}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {I8J9K0L1-M2N3-4567-OPQR-ST8901234567}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {I8J9K0L1-M2N3-4567-OPQR-ST8901234567}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {I8J9K0L1-M2N3-4567-OPQR-ST8901234567}.Release|Any CPU.Build.0 = Release|Any CPU
- {K0L1M2N3-O4P5-6789-QRST-UV0123456789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {K0L1M2N3-O4P5-6789-QRST-UV0123456789}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {K0L1M2N3-O4P5-6789-QRST-UV0123456789}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {K0L1M2N3-O4P5-6789-QRST-UV0123456789}.Release|Any CPU.Build.0 = Release|Any CPU
- {L1M2N3O4-P5Q6-7890-RSTU-VW1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {L1M2N3O4-P5Q6-7890-RSTU-VW1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {L1M2N3O4-P5Q6-7890-RSTU-VW1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {L1M2N3O4-P5Q6-7890-RSTU-VW1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
- {N3O4P5Q6-R7S8-9012-TUVW-XY3456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {N3O4P5Q6-R7S8-9012-TUVW-XY3456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {N3O4P5Q6-R7S8-9012-TUVW-XY3456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {N3O4P5Q6-R7S8-9012-TUVW-XY3456789012}.Release|Any CPU.Build.0 = Release|Any CPU
- {Q7R8S9T0-U1V2-3456-WXYZ-AB4567890123}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {Q7R8S9T0-U1V2-3456-WXYZ-AB4567890123}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {Q7R8S9T0-U1V2-3456-WXYZ-AB4567890123}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {Q7R8S9T0-U1V2-3456-WXYZ-AB4567890123}.Release|Any CPU.Build.0 = Release|Any CPU
-
-
-
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {A1B2C3D4-E5F6-7890-ABCD-EF1234567890} = {D0E78B5A-0D39-4CE8-A836-5FC8C7D60478}
- {08F6A698-C457-4D0E-8618-28836ABF02FD} = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
- {B1C2D3E4-F5G6-7890-HIJK-LM1234567890} = {D0E78B5A-0D39-4CE8-A836-5FC8C7D60478}
- {C2D3E4F5-G6H7-8901-IJKL-MN2345678901} = {D0E78B5A-0D39-4CE8-A836-5FC8C7D60478}
- {E4F5G6H7-I8J9-0123-KLMN-OP4567890123} = {F6G7H8I9-J0K1-2345-MNOP-QR6789012345}
- {F5G6H7I8-J9K0-1234-LMNO-PQ5678901234} = {F6G7H8I9-J0K1-2345-MNOP-QR6789012345}
- {G6H7I8J9-K0L1-2345-NOPQ-RS6789012345} = {F6G7H8I9-J0K1-2345-MNOP-QR6789012345}
- {2099EB97-32CB-4403-BF84-AD7F965FA520} = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
- {J9K0L1M2-N3O4-5678-PQRS-TU9012345678} = {F6G7H8I9-J0K1-2345-MNOP-QR6789012345}
- {K0L1M2N3-O4P5-6789-QRST-UV0123456789} = {J9K0L1M2-N3O4-5678-PQRS-TU9012345678}
- {L1M2N3O4-P5Q6-7890-RSTU-VW1234567890} = {J9K0L1M2-N3O4-5678-PQRS-TU9012345678}
- {M2N3O4P5-Q6R7-8901-STUV-WX2345678901} = {F6G7H8I9-J0K1-2345-MNOP-QR6789012345}
- {N3O4P5Q6-R7S8-9012-TUVW-XY3456789012} = {M2N3O4P5-Q6R7-8901-STUV-WX2345678901}
- {Q7R8S9T0-U1V2-3456-WXYZ-AB4567890123} = {M2N3O4P5-Q6R7-8901-STUV-WX2345678901}
-
-
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "storage", "storage", "{D0E78B5A-0D39-4CE8-A836-5FC8C7D60478}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "afs", "afs", "{1213A069-D226-59B6-6383-4AD31C1DF055}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "embedded", "embedded", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Storage.Embedded", "storage\embedded\NebulaStore.Storage.Embedded.csproj", "{08F6A698-C457-4D0E-8618-28836ABF02FD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Storage.EmbeddedConfiguration", "storage\embedded-configuration\NebulaStore.Storage.EmbeddedConfiguration.csproj", "{43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Storage", "storage\storage\NebulaStore.Storage.csproj", "{EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Blobstore", "afs\blobstore\NebulaStore.Afs.Blobstore.csproj", "{84059610-AD39-FA20-9653-176A6CFEFACF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Storage.Embedded.Tests", "storage\embedded\tests\NebulaStore.Storage.Embedded.Tests.csproj", "{2099EB97-32CB-4403-BF84-AD7F965FA520}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Blobstore.Tests", "afs\blobstore\test\NebulaStore.Afs.Blobstore.Tests.csproj", "{957AEEFE-FE29-6397-7D08-297EF5D694BE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Tests", "afs\tests\NebulaStore.Afs.Tests.csproj", "{1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Examples.ConsoleApp", "examples\ConsoleApp\NebulaStore.Examples.ConsoleApp.csproj", "{D15783DF-B8ED-7DA0-3855-B4BD90314158}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.GigaMap", "gigamap\NebulaStore.GigaMap.csproj", "{E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.GigaMap.Tests", "gigamap\tests\NebulaStore.GigaMap.Tests.csproj", "{8DD374AE-8266-C419-D016-ABFC2424D8A4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "aws", "aws", "{E018A2F0-712D-E946-F173-BAD35C4AC283}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Aws.S3", "afs\aws\s3\NebulaStore.Afs.Aws.S3.csproj", "{AF6BA56B-2336-DCDD-CFCB-692755A5C692}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Aws.S3.Tests", "afs\aws\s3\test\NebulaStore.Afs.Aws.S3.Tests.csproj", "{E5ECD596-2A73-FF9D-F14A-8A0983C807CF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azure", "azure", "{C35B3F86-D513-DC96-F441-B40E8BE042A1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Azure.Storage", "afs\azure\storage\NebulaStore.Afs.Azure.Storage.csproj", "{451497DA-1269-BC92-0D1A-DC64CB39853E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Azure.Storage.Tests", "afs\azure\storage\test\NebulaStore.Afs.Azure.Storage.Tests.csproj", "{13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nio", "nio", "{01885DAA-D6B3-261D-26CC-40273AA28AE8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Nio", "afs\nio\NebulaStore.Afs.Nio.csproj", "{1EDD44A6-7440-4D73-907E-5B89EF199012}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{1704E723-975B-8E7A-0A72-66948CF308B6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaStore.Afs.Nio.Tests", "afs\nio\test\NebulaStore.Afs.Nio.Tests.csproj", "{DA9E1E64-1245-4E0D-9C15-80980DAF1623}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Debug|x64.Build.0 = Debug|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Debug|x86.Build.0 = Debug|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Release|x64.ActiveCfg = Release|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Release|x64.Build.0 = Release|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Release|x86.ActiveCfg = Release|Any CPU
+ {08F6A698-C457-4D0E-8618-28836ABF02FD}.Release|x86.Build.0 = Release|Any CPU
+ {43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}.Debug|x64.Build.0 = Debug|Any CPU
+ {43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}.Debug|x86.Build.0 = Debug|Any CPU
+ {43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}.Release|x64.ActiveCfg = Release|Any CPU
+ {43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}.Release|x64.Build.0 = Release|Any CPU
+ {43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}.Release|x86.ActiveCfg = Release|Any CPU
+ {43FE9E5F-E2C8-EBBE-70A7-9BCD3CC8F87A}.Release|x86.Build.0 = Release|Any CPU
+ {EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}.Debug|x64.Build.0 = Debug|Any CPU
+ {EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}.Debug|x86.Build.0 = Debug|Any CPU
+ {EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}.Release|x64.ActiveCfg = Release|Any CPU
+ {EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}.Release|x64.Build.0 = Release|Any CPU
+ {EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}.Release|x86.ActiveCfg = Release|Any CPU
+ {EB3AD552-AEF2-D7E0-AEA1-A7B5756DAB3D}.Release|x86.Build.0 = Release|Any CPU
+ {84059610-AD39-FA20-9653-176A6CFEFACF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {84059610-AD39-FA20-9653-176A6CFEFACF}.Debug|x64.Build.0 = Debug|Any CPU
+ {84059610-AD39-FA20-9653-176A6CFEFACF}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {84059610-AD39-FA20-9653-176A6CFEFACF}.Debug|x86.Build.0 = Debug|Any CPU
+ {84059610-AD39-FA20-9653-176A6CFEFACF}.Release|x64.ActiveCfg = Release|Any CPU
+ {84059610-AD39-FA20-9653-176A6CFEFACF}.Release|x64.Build.0 = Release|Any CPU
+ {84059610-AD39-FA20-9653-176A6CFEFACF}.Release|x86.ActiveCfg = Release|Any CPU
+ {84059610-AD39-FA20-9653-176A6CFEFACF}.Release|x86.Build.0 = Release|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Debug|x64.Build.0 = Debug|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Debug|x86.Build.0 = Debug|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Release|x64.ActiveCfg = Release|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Release|x64.Build.0 = Release|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Release|x86.ActiveCfg = Release|Any CPU
+ {2099EB97-32CB-4403-BF84-AD7F965FA520}.Release|x86.Build.0 = Release|Any CPU
+ {957AEEFE-FE29-6397-7D08-297EF5D694BE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {957AEEFE-FE29-6397-7D08-297EF5D694BE}.Debug|x64.Build.0 = Debug|Any CPU
+ {957AEEFE-FE29-6397-7D08-297EF5D694BE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {957AEEFE-FE29-6397-7D08-297EF5D694BE}.Debug|x86.Build.0 = Debug|Any CPU
+ {957AEEFE-FE29-6397-7D08-297EF5D694BE}.Release|x64.ActiveCfg = Release|Any CPU
+ {957AEEFE-FE29-6397-7D08-297EF5D694BE}.Release|x64.Build.0 = Release|Any CPU
+ {957AEEFE-FE29-6397-7D08-297EF5D694BE}.Release|x86.ActiveCfg = Release|Any CPU
+ {957AEEFE-FE29-6397-7D08-297EF5D694BE}.Release|x86.Build.0 = Release|Any CPU
+ {1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}.Debug|x64.Build.0 = Debug|Any CPU
+ {1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}.Debug|x86.Build.0 = Debug|Any CPU
+ {1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}.Release|x64.ActiveCfg = Release|Any CPU
+ {1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}.Release|x64.Build.0 = Release|Any CPU
+ {1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}.Release|x86.ActiveCfg = Release|Any CPU
+ {1BA08BC3-4B57-48D2-8DC8-88174BF9CBC5}.Release|x86.Build.0 = Release|Any CPU
+ {D15783DF-B8ED-7DA0-3855-B4BD90314158}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D15783DF-B8ED-7DA0-3855-B4BD90314158}.Debug|x64.Build.0 = Debug|Any CPU
+ {D15783DF-B8ED-7DA0-3855-B4BD90314158}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D15783DF-B8ED-7DA0-3855-B4BD90314158}.Debug|x86.Build.0 = Debug|Any CPU
+ {D15783DF-B8ED-7DA0-3855-B4BD90314158}.Release|x64.ActiveCfg = Release|Any CPU
+ {D15783DF-B8ED-7DA0-3855-B4BD90314158}.Release|x64.Build.0 = Release|Any CPU
+ {D15783DF-B8ED-7DA0-3855-B4BD90314158}.Release|x86.ActiveCfg = Release|Any CPU
+ {D15783DF-B8ED-7DA0-3855-B4BD90314158}.Release|x86.Build.0 = Release|Any CPU
+ {E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}.Debug|x64.Build.0 = Debug|Any CPU
+ {E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}.Debug|x86.Build.0 = Debug|Any CPU
+ {E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}.Release|x64.ActiveCfg = Release|Any CPU
+ {E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}.Release|x64.Build.0 = Release|Any CPU
+ {E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}.Release|x86.ActiveCfg = Release|Any CPU
+ {E7A0475A-23ED-EB6D-7120-11CD71A2FF7B}.Release|x86.Build.0 = Release|Any CPU
+ {8DD374AE-8266-C419-D016-ABFC2424D8A4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8DD374AE-8266-C419-D016-ABFC2424D8A4}.Debug|x64.Build.0 = Debug|Any CPU
+ {8DD374AE-8266-C419-D016-ABFC2424D8A4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8DD374AE-8266-C419-D016-ABFC2424D8A4}.Debug|x86.Build.0 = Debug|Any CPU
+ {8DD374AE-8266-C419-D016-ABFC2424D8A4}.Release|x64.ActiveCfg = Release|Any CPU
+ {8DD374AE-8266-C419-D016-ABFC2424D8A4}.Release|x64.Build.0 = Release|Any CPU
+ {8DD374AE-8266-C419-D016-ABFC2424D8A4}.Release|x86.ActiveCfg = Release|Any CPU
+ {8DD374AE-8266-C419-D016-ABFC2424D8A4}.Release|x86.Build.0 = Release|Any CPU
+ {AF6BA56B-2336-DCDD-CFCB-692755A5C692}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {AF6BA56B-2336-DCDD-CFCB-692755A5C692}.Debug|x64.Build.0 = Debug|Any CPU
+ {AF6BA56B-2336-DCDD-CFCB-692755A5C692}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AF6BA56B-2336-DCDD-CFCB-692755A5C692}.Debug|x86.Build.0 = Debug|Any CPU
+ {AF6BA56B-2336-DCDD-CFCB-692755A5C692}.Release|x64.ActiveCfg = Release|Any CPU
+ {AF6BA56B-2336-DCDD-CFCB-692755A5C692}.Release|x64.Build.0 = Release|Any CPU
+ {AF6BA56B-2336-DCDD-CFCB-692755A5C692}.Release|x86.ActiveCfg = Release|Any CPU
+ {AF6BA56B-2336-DCDD-CFCB-692755A5C692}.Release|x86.Build.0 = Release|Any CPU
+ {E5ECD596-2A73-FF9D-F14A-8A0983C807CF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E5ECD596-2A73-FF9D-F14A-8A0983C807CF}.Debug|x64.Build.0 = Debug|Any CPU
+ {E5ECD596-2A73-FF9D-F14A-8A0983C807CF}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E5ECD596-2A73-FF9D-F14A-8A0983C807CF}.Debug|x86.Build.0 = Debug|Any CPU
+ {E5ECD596-2A73-FF9D-F14A-8A0983C807CF}.Release|x64.ActiveCfg = Release|Any CPU
+ {E5ECD596-2A73-FF9D-F14A-8A0983C807CF}.Release|x64.Build.0 = Release|Any CPU
+ {E5ECD596-2A73-FF9D-F14A-8A0983C807CF}.Release|x86.ActiveCfg = Release|Any CPU
+ {E5ECD596-2A73-FF9D-F14A-8A0983C807CF}.Release|x86.Build.0 = Release|Any CPU
+ {451497DA-1269-BC92-0D1A-DC64CB39853E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {451497DA-1269-BC92-0D1A-DC64CB39853E}.Debug|x64.Build.0 = Debug|Any CPU
+ {451497DA-1269-BC92-0D1A-DC64CB39853E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {451497DA-1269-BC92-0D1A-DC64CB39853E}.Debug|x86.Build.0 = Debug|Any CPU
+ {451497DA-1269-BC92-0D1A-DC64CB39853E}.Release|x64.ActiveCfg = Release|Any CPU
+ {451497DA-1269-BC92-0D1A-DC64CB39853E}.Release|x64.Build.0 = Release|Any CPU
+ {451497DA-1269-BC92-0D1A-DC64CB39853E}.Release|x86.ActiveCfg = Release|Any CPU
+ {451497DA-1269-BC92-0D1A-DC64CB39853E}.Release|x86.Build.0 = Release|Any CPU
+ {13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}.Debug|x64.Build.0 = Debug|Any CPU
+ {13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}.Debug|x86.Build.0 = Debug|Any CPU
+ {13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}.Release|x64.ActiveCfg = Release|Any CPU
+ {13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}.Release|x64.Build.0 = Release|Any CPU
+ {13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}.Release|x86.ActiveCfg = Release|Any CPU
+ {13ACF2E0-A4EA-3D0E-D60E-D8CDA95FCF48}.Release|x86.Build.0 = Release|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Debug|x64.Build.0 = Debug|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Debug|x86.Build.0 = Debug|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Release|x64.ActiveCfg = Release|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Release|x64.Build.0 = Release|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Release|x86.ActiveCfg = Release|Any CPU
+ {1EDD44A6-7440-4D73-907E-5B89EF199012}.Release|x86.Build.0 = Release|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Debug|x64.Build.0 = Debug|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Debug|x86.Build.0 = Debug|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Release|x64.ActiveCfg = Release|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Release|x64.Build.0 = Release|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Release|x86.ActiveCfg = Release|Any CPU
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890} = {D0E78B5A-0D39-4CE8-A836-5FC8C7D60478}
+ {08F6A698-C457-4D0E-8618-28836ABF02FD} = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
+ {01885DAA-D6B3-261D-26CC-40273AA28AE8} = {1213A069-D226-59B6-6383-4AD31C1DF055}
+ {1EDD44A6-7440-4D73-907E-5B89EF199012} = {01885DAA-D6B3-261D-26CC-40273AA28AE8}
+ {1704E723-975B-8E7A-0A72-66948CF308B6} = {01885DAA-D6B3-261D-26CC-40273AA28AE8}
+ {DA9E1E64-1245-4E0D-9C15-80980DAF1623} = {1704E723-975B-8E7A-0A72-66948CF308B6}
+ EndGlobalSection
+EndGlobal
diff --git a/afs/nio/NebulaStore.Afs.Nio.csproj b/afs/nio/NebulaStore.Afs.Nio.csproj
new file mode 100644
index 0000000..b10fa09
--- /dev/null
+++ b/afs/nio/NebulaStore.Afs.Nio.csproj
@@ -0,0 +1,34 @@
+
+
+
+ net9.0
+ enable
+ enable
+ latest
+ true
+ true
+
+ CS1591
+
+
+
+ NebulaStore Abstract File System - NIO
+ .NET I/O Adapter for the NebulaStore Abstract File System
+ NebulaStore
+ NebulaStore
+ Copyright © NebulaStore 2025
+ 1.0.0.0
+ 1.0.0.0
+ NebulaStore.Afs.Nio
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/afs/nio/README.md b/afs/nio/README.md
new file mode 100644
index 0000000..e3c8577
--- /dev/null
+++ b/afs/nio/README.md
@@ -0,0 +1,241 @@
+# NebulaStore Abstract File System - NIO
+
+The NIO (New I/O) module provides a .NET I/O adapter for the NebulaStore Abstract File System. This implementation uses standard .NET file system APIs (`System.IO`) to provide file operations, making it the default and most straightforward storage backend for local file systems.
+
+## Overview
+
+The NIO module is a direct port of the Eclipse Store AFS NIO module from Java to .NET. It provides:
+
+- **Local File System Access**: Direct access to the local file system using .NET's `System.IO`
+- **File Stream Management**: Efficient file stream handling with automatic positioning
+- **Path Resolution**: Flexible path resolution with home directory expansion support
+- **Thread-Safe Operations**: All operations are thread-safe with proper synchronization
+- **Integration**: Seamless integration with the NebulaStore AFS infrastructure
+
+## Architecture
+
+### Core Components
+
+1. **NioFileSystem**: Main entry point for NIO file system operations
+2. **NioIoHandler**: Handles all I/O operations (read, write, copy, move, etc.)
+3. **NioConnector**: Implements `IBlobStoreConnector` for AFS integration
+4. **NioReadableFile**: Wrapper for read-only file access
+5. **NioWritableFile**: Wrapper for read-write file access
+6. **NioPathResolver**: Resolves path elements to file system paths
+
+### Class Hierarchy
+
+```
+INioFileSystem
+└── NioFileSystem
+
+INioIoHandler
+└── NioIoHandler
+
+INioFileWrapper
+├── INioReadableFile
+│ └── NioReadableFile
+└── INioWritableFile
+ └── NioWritableFile
+
+IBlobStoreConnector
+└── NioConnector
+```
+
+## Usage
+
+### Basic File System Operations
+
+```csharp
+using NebulaStore.Afs.Nio;
+using NebulaStore.Afs.Blobstore;
+
+// Create a NIO file system
+using var fileSystem = NioFileSystem.New();
+
+// Create a path
+var path = BlobStorePath.New("container", "folder", "file.txt");
+
+// Wrap for writing
+using var writableFile = fileSystem.WrapForWriting(path);
+
+// Write data
+var data = System.Text.Encoding.UTF8.GetBytes("Hello, NIO!");
+fileSystem.IoHandler.WriteBytes(writableFile, data);
+
+// Wrap for reading
+using var readableFile = fileSystem.WrapForReading(path);
+
+// Read data
+var readData = fileSystem.IoHandler.ReadBytes(readableFile);
+var content = System.Text.Encoding.UTF8.GetString(readData);
+Console.WriteLine(content); // Output: Hello, NIO!
+```
+
+### Using NioConnector with BlobStoreFileSystem
+
+```csharp
+using NebulaStore.Afs.Nio;
+using NebulaStore.Afs.Blobstore;
+
+// Create a NIO connector
+using var connector = NioConnector.New("./my-storage", useCache: false);
+
+// Create a blob store file system with NIO backend
+using var fileSystem = BlobStoreFileSystem.New(connector);
+
+// Use the file system
+var path = BlobStorePath.New("data", "users", "user1.dat");
+var userData = System.Text.Encoding.UTF8.GetBytes("User data");
+
+fileSystem.IoHandler.WriteData(path, userData);
+var retrievedData = fileSystem.IoHandler.ReadData(path, 0, -1);
+```
+
+### Integration with EmbeddedStorage
+
+```csharp
+using NebulaStore.Storage.Embedded;
+using NebulaStore.Storage.EmbeddedConfiguration;
+
+// Configure storage to use NIO backend
+var config = EmbeddedStorageConfiguration.New()
+ .SetStorageDirectory("./nio-storage")
+ .SetUseAfs(true)
+ .SetAfsStorageType("nio") // Use NIO backend
+ .Build();
+
+using var storage = EmbeddedStorage.Start(config);
+
+// Use storage normally
+var root = storage.Root();
+root.SomeProperty = "value";
+storage.StoreRoot();
+```
+
+### Advanced File Operations
+
+```csharp
+using NebulaStore.Afs.Nio;
+using NebulaStore.Afs.Blobstore;
+
+using var fileSystem = NioFileSystem.New();
+var ioHandler = fileSystem.IoHandler;
+
+// Create directory
+var dirPath = BlobStorePath.New("container", "subfolder");
+ioHandler.CreateDirectory(dirPath);
+
+// List files
+var filePath = BlobStorePath.New("container");
+var files = ioHandler.ListFiles(filePath);
+foreach (var file in files)
+{
+ Console.WriteLine($"File: {file}");
+}
+
+// Copy file
+var sourcePath = BlobStorePath.New("container", "source.txt");
+var targetPath = BlobStorePath.New("container", "target.txt");
+
+using var sourceFile = fileSystem.WrapForReading(sourcePath);
+using var targetFile = fileSystem.WrapForWriting(targetPath);
+
+ioHandler.CopyFile(sourceFile, targetFile);
+
+// Move file
+var newPath = BlobStorePath.New("container", "moved.txt");
+using var movableFile = fileSystem.WrapForWriting(targetPath);
+using var destinationFile = fileSystem.WrapForWriting(newPath);
+
+ioHandler.MoveFile(movableFile, destinationFile);
+```
+
+### Path Resolution
+
+```csharp
+using NebulaStore.Afs.Nio;
+
+var fileSystem = NioFileSystem.New();
+
+// Home directory expansion
+var pathElements = fileSystem.ResolvePath("~/Documents/data");
+// Returns: ["Users", "username", "Documents", "data"] (on Unix-like systems)
+
+// Regular path
+var elements = fileSystem.ResolvePath("/var/data/files");
+// Returns: ["var", "data", "files"]
+```
+
+## Features
+
+### File Stream Management
+
+- **Automatic Positioning**: File streams are automatically positioned at the end for append operations
+- **Stream Lifecycle**: Proper stream opening, closing, and disposal
+- **Reopen Support**: Ability to reopen streams with different options
+- **Validation**: Validates file access modes and options
+
+### Thread Safety
+
+All operations are thread-safe:
+- File wrapper operations use internal mutex for synchronization
+- I/O handler operations are stateless and thread-safe
+- File system operations properly handle concurrent access
+
+### Error Handling
+
+Comprehensive error handling:
+- `FileNotFoundException` for missing files
+- `InvalidOperationException` for retired file wrappers
+- `ArgumentException` for invalid parameters
+- `IOException` for I/O errors
+
+## Comparison with Other AFS Backends
+
+| Feature | NIO | BlobStore | AWS S3 | Azure | Redis |
+|---------|-----|-----------|--------|-------|-------|
+| Local Files | ✓ | ✓ | ✗ | ✗ | ✗ |
+| Cloud Storage | ✗ | ✗ | ✓ | ✓ | ✗ |
+| In-Memory | ✗ | ✗ | ✗ | ✗ | ✓ |
+| Caching | ✗ | ✓ | ✓ | ✓ | N/A |
+| Performance | High | High | Medium | Medium | Very High |
+| Setup Complexity | Low | Low | Medium | Medium | Low |
+
+## Performance Considerations
+
+- **Direct I/O**: Uses .NET's native file I/O for maximum performance
+- **No Overhead**: Minimal abstraction overhead compared to other backends
+- **Buffering**: Leverages .NET's built-in buffering mechanisms
+- **Streaming**: Supports efficient streaming for large files
+
+## Best Practices
+
+1. **Dispose Resources**: Always dispose file wrappers and file systems
+2. **Use Using Statements**: Leverage C#'s `using` statement for automatic disposal
+3. **Handle Exceptions**: Properly handle file I/O exceptions
+4. **Path Validation**: Validate paths before operations
+5. **Concurrent Access**: Be aware of file locking when multiple processes access the same files
+
+## Limitations
+
+- **Local Only**: Only supports local file system access
+- **No Caching**: Does not include built-in caching (use BlobStore with NioConnector for caching)
+- **Platform-Specific**: Path handling may vary across platforms (Windows vs. Unix-like)
+
+## Migration from Java Eclipse Store
+
+This module is a direct port of the Eclipse Store AFS NIO module. Key differences:
+
+- `FileChannel` → `FileStream`
+- `Path` (Java NIO) → `string` (file system path)
+- `OpenOption` → `FileMode`, `FileAccess`, `FileShare`
+- `ByteBuffer` → `byte[]`
+- Exception types adapted to .NET conventions
+
+## See Also
+
+- [AFS Overview](../README.md)
+- [BlobStore Module](../blobstore/README.md)
+- [Eclipse Store NIO Documentation](https://github.com/eclipse-store/store/tree/main/afs/nio)
+
diff --git a/afs/nio/src/INioFileWrapper.cs b/afs/nio/src/INioFileWrapper.cs
new file mode 100644
index 0000000..551d86c
--- /dev/null
+++ b/afs/nio/src/INioFileWrapper.cs
@@ -0,0 +1,88 @@
+using System;
+using System.IO;
+
+namespace NebulaStore.Afs.Nio;
+
+///
+/// Interface for NIO file wrappers that provide file channel access.
+///
+public interface INioFileWrapper : INioItemWrapper, IDisposable
+{
+ ///
+ /// Gets the file stream (equivalent to Java's FileChannel).
+ ///
+ FileStream? FileStream { get; }
+
+ ///
+ /// Gets the user context associated with this file.
+ ///
+ object? User { get; }
+
+ ///
+ /// Retires this file wrapper, preventing further operations.
+ ///
+ /// True if the file was retired, false if already retired
+ bool Retire();
+
+ ///
+ /// Gets a value indicating whether this file wrapper is retired.
+ ///
+ bool IsRetired { get; }
+
+ ///
+ /// Gets a value indicating whether the file stream is open.
+ ///
+ bool IsStreamOpen { get; }
+
+ ///
+ /// Checks if the file stream is open and validates the file is not retired.
+ ///
+ /// True if the stream is open
+ bool CheckStreamOpen();
+
+ ///
+ /// Ensures the file stream is open, opening it if necessary.
+ ///
+ /// The open file stream
+ FileStream EnsureOpenStream();
+
+ ///
+ /// Ensures the file stream is open with specific options.
+ ///
+ /// The file mode
+ /// The file access
+ /// The file share mode
+ /// The open file stream
+ FileStream EnsureOpenStream(FileMode mode, FileAccess access, FileShare share);
+
+ ///
+ /// Opens the file stream.
+ ///
+ /// True if the stream was opened, false if already open
+ bool OpenStream();
+
+ ///
+ /// Opens the file stream with specific options.
+ ///
+ /// The file mode
+ /// The file access
+ /// The file share mode
+ /// True if the stream was opened, false if already open
+ bool OpenStream(FileMode mode, FileAccess access, FileShare share);
+
+ ///
+ /// Reopens the file stream with specific options.
+ ///
+ /// The file mode
+ /// The file access
+ /// The file share mode
+ /// True if the stream was reopened
+ bool ReopenStream(FileMode mode, FileAccess access, FileShare share);
+
+ ///
+ /// Closes the file stream.
+ ///
+ /// True if the stream was closed, false if already closed
+ bool CloseStream();
+}
+
diff --git a/afs/nio/src/INioItemWrapper.cs b/afs/nio/src/INioItemWrapper.cs
new file mode 100644
index 0000000..5bb153b
--- /dev/null
+++ b/afs/nio/src/INioItemWrapper.cs
@@ -0,0 +1,20 @@
+using NebulaStore.Afs.Blobstore;
+
+namespace NebulaStore.Afs.Nio;
+
+///
+/// Interface for NIO item wrappers that provide access to file system paths.
+///
+public interface INioItemWrapper
+{
+ ///
+ /// Gets the file system path for this item.
+ ///
+ string Path { get; }
+
+ ///
+ /// Gets the blob store path representation.
+ ///
+ BlobStorePath BlobPath { get; }
+}
+
diff --git a/afs/nio/src/NioConnector.cs b/afs/nio/src/NioConnector.cs
new file mode 100644
index 0000000..bdfe01a
--- /dev/null
+++ b/afs/nio/src/NioConnector.cs
@@ -0,0 +1,500 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using NebulaStore.Afs.Blobstore;
+
+namespace NebulaStore.Afs.Nio;
+
+///
+/// NIO connector that implements blob store connector interface using local file system.
+///
+public class NioConnector : IBlobStoreConnector
+{
+ private readonly string _baseDirectory;
+ private readonly INioIoHandler _ioHandler;
+ private readonly bool _useCache;
+ private bool _disposed;
+
+ ///
+ /// Creates a new NIO connector.
+ ///
+ /// The base directory for storage
+ /// Whether to use caching
+ /// A new NIO connector instance
+ public static NioConnector New(string baseDirectory, bool useCache = false)
+ {
+ return new NioConnector(baseDirectory, useCache);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The base directory for storage
+ /// Whether to use caching
+ public NioConnector(string baseDirectory, bool useCache = false)
+ {
+ if (string.IsNullOrWhiteSpace(baseDirectory))
+ {
+ throw new ArgumentException("Base directory cannot be null or empty", nameof(baseDirectory));
+ }
+
+ _baseDirectory = Path.GetFullPath(baseDirectory);
+ _useCache = useCache;
+ _ioHandler = NioIoHandler.New();
+
+ // Ensure base directory exists
+ Directory.CreateDirectory(_baseDirectory);
+ }
+
+ ///
+ /// Gets the full file system path for a blob store path.
+ ///
+ /// The blob store path
+ /// The full file system path
+ private string GetFullPath(BlobStorePath path)
+ {
+ var relativePath = _ioHandler.ToPath(path);
+ return Path.Combine(_baseDirectory, relativePath);
+ }
+
+ ///
+ public bool FileExists(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+ return File.Exists(fullPath);
+ }
+
+ ///
+ public bool DirectoryExists(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+ return Directory.Exists(fullPath);
+ }
+
+ ///
+ public bool CreateDirectory(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (Directory.Exists(fullPath))
+ {
+ return false;
+ }
+
+ Directory.CreateDirectory(fullPath);
+ return true;
+ }
+
+ ///
+ public bool CreateFile(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (File.Exists(fullPath))
+ {
+ return false;
+ }
+
+ // Ensure parent directory exists
+ var parentDir = Path.GetDirectoryName(fullPath);
+ if (!string.IsNullOrEmpty(parentDir))
+ {
+ Directory.CreateDirectory(parentDir);
+ }
+
+ // Create empty file
+ using var fs = File.Create(fullPath);
+ return true;
+ }
+
+ ///
+ public bool DeleteFile(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (!File.Exists(fullPath))
+ {
+ return false;
+ }
+
+ File.Delete(fullPath);
+ return true;
+ }
+
+ ///
+ public byte[] ReadData(BlobStorePath path, long offset, long length)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (!File.Exists(fullPath))
+ {
+ throw new FileNotFoundException($"File not found: {path.FullQualifiedName}", fullPath);
+ }
+
+ using var fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+
+ if (offset < 0)
+ {
+ offset = 0;
+ }
+
+ if (length < 0)
+ {
+ length = fs.Length - offset;
+ }
+
+ if (offset >= fs.Length)
+ {
+ return Array.Empty();
+ }
+
+ var actualLength = Math.Min(length, fs.Length - offset);
+ var buffer = new byte[actualLength];
+
+ fs.Position = offset;
+ var bytesRead = fs.Read(buffer, 0, (int)actualLength);
+
+ if (bytesRead < actualLength)
+ {
+ Array.Resize(ref buffer, bytesRead);
+ }
+
+ return buffer;
+ }
+
+ ///
+ public long ReadData(BlobStorePath path, byte[] targetBuffer, long offset, long length)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (!File.Exists(fullPath))
+ {
+ throw new FileNotFoundException($"File not found: {path.FullQualifiedName}", fullPath);
+ }
+
+ if (targetBuffer == null)
+ {
+ throw new ArgumentNullException(nameof(targetBuffer));
+ }
+
+ using var fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+
+ if (offset < 0)
+ {
+ offset = 0;
+ }
+
+ if (length < 0)
+ {
+ length = fs.Length - offset;
+ }
+
+ if (offset >= fs.Length)
+ {
+ return 0;
+ }
+
+ var actualLength = Math.Min(length, fs.Length - offset);
+ actualLength = Math.Min(actualLength, targetBuffer.Length);
+
+ fs.Position = offset;
+ return fs.Read(targetBuffer, 0, (int)actualLength);
+ }
+
+ ///
+ public long WriteData(BlobStorePath path, IEnumerable dataChunks)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ // Ensure parent directory exists
+ var parentDir = Path.GetDirectoryName(fullPath);
+ if (!string.IsNullOrEmpty(parentDir))
+ {
+ Directory.CreateDirectory(parentDir);
+ }
+
+ long totalBytesWritten = 0;
+ using var fs = new FileStream(fullPath, FileMode.Create, FileAccess.Write, FileShare.None);
+
+ foreach (var chunk in dataChunks)
+ {
+ if (chunk != null && chunk.Length > 0)
+ {
+ fs.Write(chunk, 0, chunk.Length);
+ totalBytesWritten += chunk.Length;
+ }
+ }
+
+ fs.Flush();
+ return totalBytesWritten;
+ }
+
+ ///
+ /// Writes data to a file (convenience method).
+ ///
+ /// The file path
+ /// The data to write
+ public void WriteData(BlobStorePath path, byte[] data)
+ {
+ WriteData(path, new[] { data });
+ }
+
+ ///
+ public long GetFileSize(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (!File.Exists(fullPath))
+ {
+ return 0;
+ }
+
+ var fileInfo = new FileInfo(fullPath);
+ return fileInfo.Length;
+ }
+
+ ///
+ public IEnumerable ListFiles(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (!Directory.Exists(fullPath))
+ {
+ return Enumerable.Empty();
+ }
+
+ return Directory.EnumerateFiles(fullPath)
+ .Select(Path.GetFileName)
+ .Where(name => !string.IsNullOrEmpty(name))!;
+ }
+
+ ///
+ public IEnumerable ListDirectories(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (!Directory.Exists(fullPath))
+ {
+ return Enumerable.Empty();
+ }
+
+ return Directory.EnumerateDirectories(fullPath)
+ .Select(Path.GetFileName)
+ .Where(name => !string.IsNullOrEmpty(name))!;
+ }
+
+ ///
+ public void MoveFile(BlobStorePath sourcePath, BlobStorePath targetPath)
+ {
+ EnsureNotDisposed();
+ var sourceFullPath = GetFullPath(sourcePath);
+ var targetFullPath = GetFullPath(targetPath);
+
+ if (!File.Exists(sourceFullPath))
+ {
+ throw new FileNotFoundException($"Source file not found: {sourcePath.FullQualifiedName}", sourceFullPath);
+ }
+
+ // Ensure target directory exists
+ var targetDir = Path.GetDirectoryName(targetFullPath);
+ if (!string.IsNullOrEmpty(targetDir))
+ {
+ Directory.CreateDirectory(targetDir);
+ }
+
+ File.Move(sourceFullPath, targetFullPath, overwrite: true);
+ }
+
+ ///
+ public long CopyFile(BlobStorePath sourcePath, BlobStorePath targetPath, long offset, long length)
+ {
+ EnsureNotDisposed();
+ var sourceFullPath = GetFullPath(sourcePath);
+ var targetFullPath = GetFullPath(targetPath);
+
+ if (!File.Exists(sourceFullPath))
+ {
+ throw new FileNotFoundException($"Source file not found: {sourcePath.FullQualifiedName}", sourceFullPath);
+ }
+
+ // Ensure target directory exists
+ var targetDir = Path.GetDirectoryName(targetFullPath);
+ if (!string.IsNullOrEmpty(targetDir))
+ {
+ Directory.CreateDirectory(targetDir);
+ }
+
+ using var sourceStream = new FileStream(sourceFullPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ using var targetStream = new FileStream(targetFullPath, FileMode.Create, FileAccess.Write, FileShare.None);
+
+ if (offset < 0)
+ {
+ offset = 0;
+ }
+
+ if (length < 0)
+ {
+ length = sourceStream.Length - offset;
+ }
+
+ if (offset >= sourceStream.Length)
+ {
+ return 0;
+ }
+
+ var actualLength = Math.Min(length, sourceStream.Length - offset);
+ sourceStream.Position = offset;
+
+ var buffer = new byte[81920]; // 80KB buffer
+ long totalCopied = 0;
+ long remaining = actualLength;
+
+ while (remaining > 0)
+ {
+ var toRead = (int)Math.Min(buffer.Length, remaining);
+ var bytesRead = sourceStream.Read(buffer, 0, toRead);
+
+ if (bytesRead == 0)
+ {
+ break;
+ }
+
+ targetStream.Write(buffer, 0, bytesRead);
+ totalCopied += bytesRead;
+ remaining -= bytesRead;
+ }
+
+ targetStream.Flush();
+ return totalCopied;
+ }
+
+ ///
+ /// Copies a file (convenience method that copies the entire file).
+ ///
+ /// The source file path
+ /// The target file path
+ public void CopyFile(BlobStorePath sourcePath, BlobStorePath targetPath)
+ {
+ CopyFile(sourcePath, targetPath, 0, -1);
+ }
+
+ ///
+ public void VisitChildren(BlobStorePath path, IBlobStorePathVisitor visitor)
+ {
+ EnsureNotDisposed();
+
+ if (visitor == null)
+ {
+ throw new ArgumentNullException(nameof(visitor));
+ }
+
+ var fullPath = GetFullPath(path);
+
+ if (!Directory.Exists(fullPath))
+ {
+ return;
+ }
+
+ // Visit directories
+ foreach (var dir in Directory.EnumerateDirectories(fullPath))
+ {
+ var dirName = Path.GetFileName(dir);
+ if (!string.IsNullOrEmpty(dirName))
+ {
+ visitor.VisitDirectory(path, dirName);
+ }
+ }
+
+ // Visit files
+ foreach (var file in Directory.EnumerateFiles(fullPath))
+ {
+ var fileName = Path.GetFileName(file);
+ if (!string.IsNullOrEmpty(fileName))
+ {
+ visitor.VisitFile(path, fileName);
+ }
+ }
+ }
+
+ ///
+ public bool IsEmpty(BlobStorePath path)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (!Directory.Exists(fullPath))
+ {
+ return true;
+ }
+
+ return !Directory.EnumerateFileSystemEntries(fullPath).Any();
+ }
+
+ ///
+ public void TruncateFile(BlobStorePath path, long newLength)
+ {
+ EnsureNotDisposed();
+ var fullPath = GetFullPath(path);
+
+ if (!File.Exists(fullPath))
+ {
+ throw new FileNotFoundException($"File not found: {path.FullQualifiedName}", fullPath);
+ }
+
+ if (newLength < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(newLength), "New length must be non-negative");
+ }
+
+ using var fs = new FileStream(fullPath, FileMode.Open, FileAccess.Write, FileShare.None);
+ fs.SetLength(newLength);
+ fs.Flush();
+ }
+
+ private void EnsureNotDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases resources used by this connector.
+ ///
+ /// True if disposing managed resources
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ _ioHandler?.Dispose();
+ }
+
+ _disposed = true;
+ }
+}
+
diff --git a/afs/nio/src/NioFileSystem.cs b/afs/nio/src/NioFileSystem.cs
new file mode 100644
index 0000000..84f91fe
--- /dev/null
+++ b/afs/nio/src/NioFileSystem.cs
@@ -0,0 +1,250 @@
+using System;
+using System.IO;
+using NebulaStore.Afs.Blobstore;
+
+namespace NebulaStore.Afs.Nio;
+
+///
+/// Interface for NIO file system.
+///
+public interface INioFileSystem : IDisposable
+{
+ ///
+ /// Gets the I/O handler for this file system.
+ ///
+ INioIoHandler IoHandler { get; }
+
+ ///
+ /// Gets the default protocol for this file system.
+ ///
+ string DefaultProtocol { get; }
+
+ ///
+ /// Wraps a blob store path for reading.
+ ///
+ /// The blob store path
+ /// The user context
+ /// A readable file wrapper
+ INioReadableFile WrapForReading(BlobStorePath path, object? user = null);
+
+ ///
+ /// Wraps a blob store path for writing.
+ ///
+ /// The blob store path
+ /// The user context
+ /// A writable file wrapper
+ INioWritableFile WrapForWriting(BlobStorePath path, object? user = null);
+
+ ///
+ /// Converts a readable file to a writable file.
+ ///
+ /// The readable file
+ /// A writable file wrapper
+ INioWritableFile ConvertToWriting(INioReadableFile file);
+
+ ///
+ /// Converts a writable file to a readable file.
+ ///
+ /// The writable file
+ /// A readable file wrapper
+ INioReadableFile ConvertToReading(INioWritableFile file);
+
+ ///
+ /// Resolves a path string to path elements.
+ ///
+ /// The full path string
+ /// The path elements
+ string[] ResolvePath(string fullPath);
+}
+
+///
+/// Default implementation of NIO file system.
+///
+public class NioFileSystem : INioFileSystem
+{
+ private readonly string _defaultProtocol;
+ private readonly INioIoHandler _ioHandler;
+ private bool _disposed;
+
+ ///
+ /// Gets the default protocol string for file URIs.
+ ///
+ public const string DefaultFileProtocol = "file:///";
+
+ ///
+ /// Creates a new NIO file system with default settings.
+ ///
+ /// A new file system instance
+ public static NioFileSystem New()
+ {
+ return New(DefaultFileProtocol);
+ }
+
+ ///
+ /// Creates a new NIO file system with a custom protocol.
+ ///
+ /// The default protocol
+ /// A new file system instance
+ public static NioFileSystem New(string defaultProtocol)
+ {
+ return New(defaultProtocol, NioIoHandler.New());
+ }
+
+ ///
+ /// Creates a new NIO file system with a custom I/O handler.
+ ///
+ /// The I/O handler
+ /// A new file system instance
+ public static NioFileSystem New(INioIoHandler ioHandler)
+ {
+ return New(DefaultFileProtocol, ioHandler);
+ }
+
+ ///
+ /// Creates a new NIO file system with custom settings.
+ ///
+ /// The default protocol
+ /// The I/O handler
+ /// A new file system instance
+ public static NioFileSystem New(string defaultProtocol, INioIoHandler ioHandler)
+ {
+ return new NioFileSystem(
+ defaultProtocol ?? throw new ArgumentNullException(nameof(defaultProtocol)),
+ ioHandler ?? throw new ArgumentNullException(nameof(ioHandler)));
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The default protocol
+ /// The I/O handler
+ protected NioFileSystem(string defaultProtocol, INioIoHandler ioHandler)
+ {
+ _defaultProtocol = defaultProtocol ?? throw new ArgumentNullException(nameof(defaultProtocol));
+ _ioHandler = ioHandler ?? throw new ArgumentNullException(nameof(ioHandler));
+ }
+
+ ///
+ public string DefaultProtocol => _defaultProtocol;
+
+ ///
+ public INioIoHandler IoHandler => _ioHandler;
+
+ ///
+ public string[] ResolvePath(string fullPath)
+ {
+ if (string.IsNullOrEmpty(fullPath))
+ {
+ return Array.Empty();
+ }
+
+ // Handle home directory expansion
+ var resolved = fullPath;
+ if (fullPath.StartsWith("~/") || fullPath.StartsWith("~\\"))
+ {
+ var homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
+ resolved = System.IO.Path.Combine(homeDir, fullPath.Substring(2));
+ }
+
+ // Split path by directory separator
+ var separators = new[] { System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar };
+ return resolved.Split(separators, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ ///
+ public INioReadableFile WrapForReading(BlobStorePath path, object? user = null)
+ {
+ if (path == null)
+ {
+ throw new ArgumentNullException(nameof(path));
+ }
+
+ var fsPath = _ioHandler.ToPath(path);
+ return NioReadableFile