Program saya akan mengambil string sewenang-wenang dari internet dan menggunakannya untuk nama file. Apakah ada cara sederhana untuk menghapus karakter jahat dari string ini atau apakah saya perlu menulis fungsi kustom untuk ini?
94
Jawaban:
Ugh, aku benci kalau orang mencoba menebak karakter mana yang valid. Selain benar-benar tidak portabel (selalu memikirkan Mono), kedua komentar sebelumnya melewatkan lebih dari 25 karakter tidak valid.
'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
sumber
Untuk menghapus karakter yang tidak valid:
static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); // Builds a string out of valid chars var validFilename = new string(filename.Where(ch => !invalidFileNameChars.Contains(ch)).ToArray());
Untuk mengganti karakter yang tidak valid:
static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); // Builds a string out of valid chars and an _ for invalid ones var validFilename = new string(filename.Select(ch => invalidFileNameChars.Contains(ch) ? '_' : ch).ToArray());
Untuk mengganti karakter yang tidak valid (dan menghindari potensi konflik nama seperti Hell * vs Hell $):
static readonly IList<char> invalidFileNameChars = Path.GetInvalidFileNameChars(); // Builds a string out of valid chars and replaces invalid chars with a unique letter (Moves the Char into the letter range of unicode, starting at "A") var validFilename = new string(filename.Select(ch => invalidFileNameChars.Contains(ch) ? Convert.ToChar(invalidFileNameChars.IndexOf(ch) + 65) : ch).ToArray());
sumber
Pertanyaan ini telah berkali- kali diajukan sebelumnya dan, seperti yang telah disebutkan beberapa kali sebelumnya,
IO.Path.GetInvalidFileNameChars
tidaklah memadai.Pertama, ada banyak nama seperti PRN dan CON yang dicadangkan dan tidak diperbolehkan untuk nama file. Ada nama lain yang tidak diperbolehkan hanya di folder root. Nama yang diakhiri dengan titik juga tidak diperbolehkan.
Kedua, ada berbagai batasan panjang. Baca daftar lengkap NTFS di sini .
Ketiga, Anda dapat melampirkan ke sistem file yang memiliki batasan lain. Misalnya, nama file ISO 9660 tidak boleh dimulai dengan "-" tetapi dapat memuatnya.
Keempat, apa yang Anda lakukan jika dua proses "sembarangan" memilih nama yang sama?
Secara umum, menggunakan nama yang dibuat secara eksternal untuk nama file adalah ide yang buruk. Saya sarankan membuat nama file pribadi Anda sendiri dan menyimpan nama yang dapat dibaca manusia secara internal.
sumber
Saya setuju dengan Grauenwolf dan akan sangat merekomendasikan
Path.GetInvalidFileNameChars()
Ini kontribusi C # saya:
string file = @"38?/.\}[+=n a882 a.a*/|n^%$ ad#(-))"; Array.ForEach(Path.GetInvalidFileNameChars(), c => file = file.Replace(c.ToString(), String.Empty));
ps - ini lebih samar dari yang seharusnya - Saya mencoba untuk ringkas.
sumber
Array.ForEach
alih-alih hanya diforeach
siniPath.GetInvalidFileNameChars().Aggregate(file, (current, c) => current.Replace(c, '-'))
Ini versi saya:
static string GetSafeFileName(string name, char replace = '_') { char[] invalids = Path.GetInvalidFileNameChars(); return new string(name.Select(c => invalids.Contains(c) ? replace : c).ToArray()); }
Saya tidak yakin bagaimana hasil dari GetInvalidFileNameChars dihitung, tetapi "Get" menyarankan itu tidak sepele, jadi saya cache hasilnya. Lebih lanjut, ini hanya melintasi string input sekali, bukan beberapa kali, seperti solusi di atas yang mengulangi rangkaian karakter yang tidak valid, menggantikannya dalam string sumber satu per satu. Juga, saya suka solusi berbasis Di mana, tetapi saya lebih suka mengganti karakter yang tidak valid daripada menghapusnya. Akhirnya, penggantian saya persis satu karakter untuk menghindari konversi karakter menjadi string saat saya mengulang string.
Saya mengatakan semua itu tanpa melakukan pembuatan profil - yang ini hanya "terasa" baik bagi saya. :)
sumber
new HashSet<char>(Path.GetInvalidFileNameChars())
untuk menghindari pencacahan O (n) - optimasi mikro.Inilah fungsi yang saya gunakan sekarang (terima kasih jcollum untuk contoh C #):
public static string MakeSafeFilename(string filename, char replaceChar) { foreach (char c in System.IO.Path.GetInvalidFileNameChars()) { filename = filename.Replace(c, replaceChar); } return filename; }
Saya hanya meletakkan ini di kelas "Pembantu" untuk kenyamanan.
sumber
Jika Anda ingin segera menghapus semua karakter khusus yang terkadang lebih mudah dibaca pengguna untuk nama file, ini berfungsi dengan baik:
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"
sumber
\W
lebih cocok daripada non-alpha-numerics ([^A-Za-z0-9_]
). Semua karakter 'kata' Unicode (русский 中文 ..., dll.) Juga tidak akan diganti. Tapi ini hal yang bagus..
sehingga Anda harus mengekstrak ekstensi terlebih dahulu, dan menambahkannya lagi setelahnya.static class Utils { public static string MakeFileSystemSafe(this string s) { return new string(s.Where(IsFileSystemSafe).ToArray()); } public static bool IsFileSystemSafe(char c) { return !Path.GetInvalidFileNameChars().Contains(c); } }
sumber
Mengapa tidak mengonversi string menjadi setara Base64 seperti ini:
string UnsafeFileName = "salmnas dlajhdla kjha;dmas'lkasn"; string SafeFileName = Convert.ToBase64String(Encoding.UTF8.GetBytes(UnsafeFileName));
Jika Anda ingin mengubahnya kembali sehingga Anda dapat membacanya:
Saya menggunakan ini untuk menyimpan file PNG dengan nama unik dari deskripsi acak.
sumber
Inilah yang baru saja saya tambahkan ke kelas statis ClipFlair ( http://github.com/Zoomicon/ClipFlair ) StringExtensions (proyek Utils.Silverlight), berdasarkan info yang dikumpulkan dari tautan ke pertanyaan stackoverflow terkait yang diposting oleh Dour High Arch di atas:
public static string ReplaceInvalidFileNameChars(this string s, string replacement = "") { return Regex.Replace(s, "[" + Regex.Escape(new String(System.IO.Path.GetInvalidPathChars())) + "]", replacement, //can even use a replacement string of any length RegexOptions.IgnoreCase); //not using System.IO.Path.InvalidPathChars (deprecated insecure API) }
sumber
private void textBoxFileName_KeyPress(object sender, KeyPressEventArgs e) { e.Handled = CheckFileNameSafeCharacters(e); } /// <summary> /// This is a good function for making sure that a user who is naming a file uses proper characters /// </summary> /// <param name="e"></param> /// <returns></returns> internal static bool CheckFileNameSafeCharacters(System.Windows.Forms.KeyPressEventArgs e) { if (e.KeyChar.Equals(24) || e.KeyChar.Equals(3) || e.KeyChar.Equals(22) || e.KeyChar.Equals(26) || e.KeyChar.Equals(25))//Control-X, C, V, Z and Y return false; if (e.KeyChar.Equals('\b'))//backspace return false; char[] charArray = Path.GetInvalidFileNameChars(); if (charArray.Contains(e.KeyChar)) return true;//Stop the character from being entered into the control since it is non-numerical else return false; }
sumber
Saya merasa menggunakan ini cepat dan mudah dimengerti:
<Extension()> Public Function MakeSafeFileName(FileName As String) As String Return FileName.Where(Function(x) Not IO.Path.GetInvalidFileNameChars.Contains(x)).ToArray End Function
Ini berfungsi karena a
string
adalahIEnumerable
sebagaichar
array dan adastring
string konstruktor yang mengambilchar
array.sumber
Dari proyek lama saya, saya telah menemukan solusi ini, yang telah bekerja dengan sempurna selama 2 tahun. Saya mengganti karakter ilegal dengan "!", Lalu periksa double !!, gunakan karakter Anda sendiri.
public string GetSafeFilename(string filename) { string res = string.Join("!", filename.Split(Path.GetInvalidFileNameChars())); while (res.IndexOf("!!") >= 0) res = res.Replace("!!", "!"); return res; }
sumber
Banyak jawaban yang menyarankan untuk menggunakan
Path.GetInvalidFileNameChars()
yang sepertinya solusi yang buruk bagi saya. Saya mendorong Anda untuk menggunakan daftar putih daripada daftar hitam karena peretas pada akhirnya akan selalu menemukan cara untuk melewatinya.Berikut adalah contoh kode yang dapat Anda gunakan:
string whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ."; foreach (char c in filename) { if (!whitelist.Contains(c)) { filename = filename.Replace(c, '-'); } }
sumber