Skip to content

Instantly share code, notes, and snippets.

@JohanLarsson
Last active December 30, 2015 11:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JohanLarsson/7824311 to your computer and use it in GitHub Desktop.
Save JohanLarsson/7824311 to your computer and use it in GitHub Desktop.
[TestCase("Test", "Test")]
[TestCase("%Test", "%037Test")]
[TestCase("%037Test", "%037037Test")]
[TestCase(":Test", "%058Test")]
[TestCase(":Test", "%058Test")]
[TestCase(@":Test : kasgfd % askjfg \", "%058Test %058 kasgfd %037 askjfg %092")]
[TestCase(@":Test : kasgfd % askjfg \kjsafgikahfg:oadsfhoaefihlajksbfa,das", "%058Test %058 kasgfd %037 askjfg %092kjsafgikahfg%058oadsfhoaefihlajksbfa,das")]
public void FileNameEncodeDecodeTest(string fileName, string expected)
{
for (int i = 0; i < 2; i++) // Slow the first time maybe the ctor is expensive
{
Stopwatch stopwatch = Stopwatch.StartNew();
string encoded = FileUtility.FilenameEncode(fileName);
Console.WriteLine(stopwatch.GetTimeString());
Assert.AreEqual(expected, encoded);
stopwatch.Restart();
string decoded = FileUtility.FilenameDecode(encoded);
Console.WriteLine(stopwatch.GetTimeString());
Assert.AreEqual(fileName, decoded);
}
}
public static class FileUtility
{
private const char PrefixChar = '%';
private static readonly int MaxLength;
private static readonly Dictionary<char,char[]> Illegals;
static FileUtility()
{
List<char> illegal = new List<char> { PrefixChar };
illegal.AddRange(Path.GetInvalidFileNameChars());
MaxLength = illegal.Select(x => ((int)x).ToString().Length).Max();
Illegals = illegal.ToDictionary(x => x, x => ((int)x).ToString("D" + MaxLength).ToCharArray());
}
public static string FilenameEncode(string s)
{
var builder = new StringBuilder();
char[] replacement;
using (var reader = new StringReader(s))
{
while (true)
{
int read = reader.Read();
if (read == -1)
break;
char c = (char)read;
if(Illegals.TryGetValue(c,out replacement))
{
builder.Append(PrefixChar);
builder.Append(replacement);
}
else
{
builder.Append(c);
}
}
}
return builder.ToString();
}
public static string FilenameDecode(string s)
{
var builder = new StringBuilder();
char[] buffer = new char[MaxLength];
using (var reader = new StringReader(s))
{
while (true)
{
int read = reader.Read();
if (read == -1)
break;
char c = (char)read;
if (c == PrefixChar)
{
reader.Read(buffer, 0, MaxLength);
var encoded =(char) ParseCharArray(buffer);
builder.Append(encoded);
}
else
{
builder.Append(c);
}
}
}
return builder.ToString();
}
public static int ParseCharArray(char[] buffer)
{
int result = 0;
foreach (char t in buffer)
{
int digit = t - '0';
if ((digit < 0) || (digit > 9))
{
throw new ArgumentException("Input string was not in the correct format");
}
result *= 10;
result += digit;
}
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment