using System.Collections.Generic;
using System.IO.Compression;
using VPO = VirtualPathObject;
public static void Main()
new System.Net.WebClient().DownloadFile(@"https://www.dropbox.com/s/spwfx62e7d26mr3/test.zip?dl=1", p);
VPO v = new VPO(p, true);
Console.WriteLine(v.ToString());
Console.WriteLine("Success");
Console.WriteLine(new VPO("test2.zip", true).ToString());
public class VirtualPathObject
public VirtualPathObject()
public VirtualPathObject(string path, bool isZip = false)
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
ZipArchive za = ZipFile.Open(path, ZipArchiveMode.Read, System.Text.Encoding.GetEncoding(850));
foreach (ZipArchiveEntry e in za.Entries)
if (e.Name == string.Empty)
_ = GetChildFromPath(e.FullName);
SetChildFromPath(e.FullName, new VirtualPathObject<byte[]>(ReadFully(e.Open())));
public void Zip(string zipPath)
using FileStream fs = new FileStream(zipPath, FileMode.Create);
using ZipArchive za = new ZipArchive(fs, ZipArchiveMode.Update);
private void CreateEntries(ZipArchive za, string path = null)
foreach (var c in Children)
if (c.Value.GetType().IsGenericType)
za.CreateEntry(path + c.Key);
c.Value.CreateEntries(za, path + c.Key);
private static byte[] ReadFully(Stream input)
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
ms.Write(buffer, 0, read);
public VirtualPathObject MakeDir(string name)
Children = new ICDict<VirtualPathObject>();
VirtualPathObject vpo = new VirtualPathObject();
public VirtualPathObject this[params string[] path]
set => SetChild(path, value);
public VirtualPathObject GetChild(string name)
if (Children != null && Children.ContainsKey(name))
public void SetChild(string name, VirtualPathObject value)
Children = new ICDict<VirtualPathObject>();
private readonly char[] cDefSep = {'/', '\\'};
public VirtualPathObject GetChildFromPath(string path) => GetChildFromPath(path, cDefSep);
public VirtualPathObject GetChildFromPath(string path, char[] sep) => GetChild(path.Split(sep, StringSplitOptions.RemoveEmptyEntries));
public VirtualPathObject GetChild(string[] path)
throw new ArgumentException();
else if (path.Length == 1)
return GetChild(path[0]);
string[] newPath = new string[path.Length - 1];
for (int i = 0; i < newPath.Length; i++)
newPath[i] = path[i + 1];
return GetChild(path[0])[newPath];
public void SetChildFromPath(string path, VirtualPathObject value) => SetChildFromPath(path, value, cDefSep);
public void SetChildFromPath(string path, VirtualPathObject value, char[] sep) => SetChild(path.Split(sep, StringSplitOptions.RemoveEmptyEntries), value);
public void SetChild(string[] path, VirtualPathObject value)
throw new ArgumentException();
else if (path.Length == 1)
SetChild(path[0], value);
string[] newPath = new string[path.Length - 1];
for (int i = 0; i < newPath.Length; i++)
newPath[i] = path[i + 1];
GetChild(path[0]).SetChild(newPath, value);
public override string ToString() => ToString(base.ToString());
public string ToString(string name)
foreach (var c in Children)
s += "\n" + ((c.Key + ": ").PadRight(25) + c.Value.ToString() + "").Shift(4);
if ((o = Content) != null)
if (GetType().IsGenericType)
foreach (PropertyInfo pi in GetType().GetProperties())
if (pi.Name == nameof(Content) && pi.DeclaringType.IsGenericType)
return pi.GetValue(this);
throw new InvalidOperationException("Content can only be received from objects of the inherited type VirtualPathObject<T>.");
public ICDict<VirtualPathObject> Children
public class VirtualPathObject<T> : VirtualPathObject
public VirtualPathObject()
public VirtualPathObject(T content)
public interface ISavable
public class ICDict<T> : Dictionary<string, T>
public ICDict(): base(StringComparer.OrdinalIgnoreCase)
public static string Shift(this string s, int n)
string[] l = s.Split('\n');
for (int i = 0; i < l.Length; i++)
r += (i == 0 ? string.Empty : "\n") + string.Empty.PadRight(n) + l[i];
public static string AsString(this byte[] b) => System.Text.Encoding.Default.GetString(b ?? new byte[0]);