IT

C #에서 공유 파일 경로를 만드는 방법이 있습니까?

lottoking 2020. 9. 17. 08:09
반응형

C #에서 공유 파일 경로를 만드는 방법이 있습니까?


내 프로그램은 인터넷에서 임의의 패키지를 가져 오기 파일 이름으로 사용합니다. 어디에서나 잘못된 문자를 제거하는 간단한 방법이 있습니까? 아니면 이에 대한 사용자 지정 함수를 작성해야합니까?


어, 사람들이 어떤 문자가 유효한지 추측하려고 할 때요. 완전히 이식 할 수없는 것 외에도 (항상 Mono에 대해 생각 함) 이전 주석 모두 25 개 이상의 유효하지 않은 문자를 놓쳤습니다.

'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

질문은이 이전에 여러 요청 고객되었으며 이전에 여러 지적했듯이 IO.Path.GetInvalidFileNameChars적절하지 않습니다.

첫째, PRN 및 CON과 같이 예약되어 있고 파일 이름에 허용되지 않는 이름이 많이 있습니다. 루트 폴더에는 허용되지 않는 다른 이름이 있습니다. 마침표로 끝나는 이름도 허용되지 않습니다.

둘째, 다양한 길이 제한이 있습니다. 여기 에서 NTFS에 대한 전체 목록을 읽어 .

셋째, 다른 제한이있는 파일 시스템에 있습니다. 예를 들어 ISO 9660 파일 이름은 "-"로 시작할 수 없지만 할 수 있습니다.

넷째, 두 프로세스가 "임의로"같은 이름을 선택하면 어떻게됩니까?

일반적으로 외부에서 생성 된 이름을 사용하는 것이 좋지 않습니다. 자신의 개인 파일 이름을 생성하고 사람이 읽을 수있는 이름을 내부적으로 저장하는 것이 좋습니다.


유효하지 않은 문자를 제거 비용 :

static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();

// Builds a string out of valid chars
var validFilename = new string(filename.Where(ch => !invalidFileNameChars.Contains(ch)).ToArray());

유효하지 않은 문자를 바꾸려면 :

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());

유효하지 않은 문자를 바꾸려면 (그리고 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());

나는 Grauenwolf에 동의하며 Path.GetInvalidFileNameChars()

내 C # 기여는 다음과 가변합니다.

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

추신-이건 당연한 것보다 더 은밀합니다-저는 간결하게되었습니다.


내 버전은 다음과 달라집니다.

static string GetSafeFileName(string name, char replace = '_') {
  char[] invalids = Path.GetInvalidFileNameChars();
  return new string(name.Select(c => invalids.Contains(c) ? replace : c).ToArray());
}

GetInvalidFileNameChars의 결과가 어떻게 계산되는지 잘 모르겠지만 "Get"은 그것이 사소하지 않다고 제안하므로 결과를 캐시합니다. 또한 이것은 잘못된 문자 집합을 반복하는 위의 솔루션과 같이 입력 문자열을 여러 번 대신 한 번만 탐색하여 소스 문자열에서 한 번에 하나씩 대체합니다. 또한 Where 기반 솔루션을 좋아하지만 유효하지 않은 문자를 제거하는 대신 대체하는 것을 선호합니다. 마지막으로, 문자열을 반복 할 때 문자를 문자열로 변환하지 않도록 정확히 한 문자를 대체합니다.

나는 프로파일 링을하지 않고 모든 것을 말한다. 이것은 나에게 단지 "느낌"이었다. :)


지금 사용하고있는 함수는 다음과 같습니다 (C # 예제의 jcollum에게 감사드립니다).

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

편의를 위해 "Helpers"클래스에 넣었습니다.


파일 이름에 대해 사용자가 더 쉽게 읽을 수있는 모든 특수 문자를 빠르게 제거하려면 다음과 같이 잘 작동합니다.

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"

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);
    }
}

다음 은 위의 Dour High Arch가 게시 한 관련 스택 오버플로 질문에 대한 링크에서 수집 한 정보를 기반으로 ClipFlair의 ( http://github.com/Zoomicon/ClipFlair ) StringExtensions 정적 클래스 (Utils.Silverlight 프로젝트)에 방금 추가 한 내용입니다.

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)
}

문자열을 다음과 같이 Base64로 변환하지 않는 이유 :

string UnsafeFileName = "salmnas dlajhdla kjha;dmas'lkasn";
string SafeFileName = Convert.ToBase64String(Encoding.UTF8.GetBytes(UnsafeFileName));

읽을 수 있도록 다시 변환하려면 :

UnsafeFileName = Encoding.UTF8.GetString(Convert.FromBase64String(SafeFileName));

무작위 설명에서 고유 한 이름으로 PNG 파일을 저장하는 데 사용했습니다.


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;            
}

이 방법을 사용하면 빠르고 쉽게 이해할 수 있습니다.

<Extension()>
Public Function MakeSafeFileName(FileName As String) As String
    Return FileName.Where(Function(x) Not IO.Path.GetInvalidFileNameChars.Contains(x)).ToArray
End Function

a가 있기 때문 작품 stringIEnumerableA와 char배열하고있다 string소요 생성자 문자열 char배열.


많은 사람들 Path.GetInvalidFileNameChars()이 나에게 나쁜 해결책처럼 보이는 사용 제안합니다 . 해커는 항상이를 우회 할 방법을 찾기 때문에 블랙리스트 대신 화이트리스트를 사용하는 것이 좋습니다.

다음은 사용할 수있는 코드의 예입니다.

    string whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.";
    foreach (char c in filename)
    {
        if (!whitelist.Contains(c))
        {
            filename = filename.Replace(c, '-');
        }
    }

이전 프로젝트에서 2 년 동안 완벽하게 작동하는이 솔루션을 찾았습니다. 불법 문자를 "!"로 바꾸고 이중 !!를 확인하고 자신의 문자를 사용합니다.

    public string GetSafeFilename(string filename)
    {
        string res = string.Join("!", filename.Split(Path.GetInvalidFileNameChars()));

        while (res.IndexOf("!!") >= 0)
            res = res.Replace("!!", "!");

        return res;
    }

참고 URL : https://stackoverflow.com/questions/333175/is-there-a-way-of-making-strings-file-path-safe-in-c

반응형