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?
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?
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
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());
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.
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.
Array.ForEach
alih-alih hanya di foreach
sini
Path.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. :)
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.
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"
\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);
}
}
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:
UnsafeFileName = Encoding.UTF8.GetString(Convert.FromBase64String(SafeFileName));
Saya menggunakan ini untuk menyimpan file PNG dengan nama unik dari deskripsi acak.
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)
}
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;
}
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
adalah IEnumerable
sebagai char
array dan ada string
string konstruktor yang mengambil char
array.
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;
}
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, '-');
}
}