views:

2926

answers:

6

My program will take arbitrary strings from the internet and use them for file names. Is there a simple way to remove the bad characters from these strings or do I need to write a custom function for this?

+21  A: 

Ugh, I hate it when people try to guess at which characters are valid. Besides being completely non-portable (always thinking about Mono), both of the earlier comments missed more 25 invalid characters.

 'Clean just a filename
 Dim filename As String = "salmnas dlajhdla kjha;dmas'lkasn"
 For Each c In IO.Path.GetInvalidFileNameChars
  filename = filename.Replace(c, "")
 Next

 'See also IO.Path.GetInvalidPathChars
Jonathan Allen
It would be unlikely make much difference in this situation. The Windows error only complains about that handful of characters. Thanks for pointing out the GetInvalidFileNameChars though, I'd not come across that before. I'll keep it in mind.
BenAlabaster
The C# version: foreach (var c in Path.GetInvalidFileNameChars()) { fileName=fileName.Replace(c, '-'); }
jcollum
+7  A: 

I agree with Grauenwolf and would highly recommend the Path.GetInvalidFileNameChars()

Here's my C# contribution:

string file = @"38?/.\}[+=n a882 a.a*/|n^%$ ad#(-))";
Array.ForEach(Path.GetInvalidFileNameChars(), 
      c => file = file.Replace(c.ToString(), String.Empty));

p.s. -- this is more cryptic than it should be -- I was trying to be concise.

Aaron Wagner
A: 

If you want to quickly strip out all special characters which is sometimes more user readable for file names this works nicely:

string myCrazyName = "q`w^e!r@t#y$u%i^o&p*a(s)d_f-g+h=j{k}l|z:x\"c<v>b?n[m]q\\w;e'r,t.y/u";
string safeName = Regex.Replace(
    myCrazyName,
    "\W",  /*Matches any nonword character. Equivalent to '[^A-Za-z0-9_]'*/
    "",
    RegexOptions.IgnoreCase);
// safeName == "qwertyuiopasd_fghjklzxcvbnmqwertyu"
Keith
+1  A: 

Here's the function that I am using now (thanks jcollum for the C# example):

public static string MakeSafeFilename(string filename, char replaceChar)
{
    foreach (char c in System.IO.Path.GetInvalidFileNameChars())
    {
        filename = filename.Replace(c, replaceChar);
    }
    return filename;
}

I just put this in a "Helpers" class for convenience.

sidewinderguy
+1  A: 

How about:

static readonly IList invalidFileNameChars = Path.GetInvalidFileNameChars();
var validFilename = new string(filename.Where(ch => !invalidFileNameChars.Contains(ch)).ToArray());
Squirrel
A: 

This question has been asked many times before and, as pointed out many times before, IO.Path.GetInvalidFileNameChars is not adequate.

First, there are many names like PRN and CON that are reserved and not allowed for filenames. There are other names not allowed only at the root folder. Names that end in a period are also not allowed.

Second, there are a variety of length limitations. Read the full list for NTFS here.

Third, you can attach to filesystems that have other limitations. For example, ISO 9660 filenames cannot start with "-" but can contain it.

Fourth, what do you do if two processes "arbitrarily" pick the same name?

In general, using externally-generated names for file names is a bad idea. I suggest generating your own private file names and storing human-readable names internally.

Dour High Arch