2009-12-07 30 views
6

Có cách nào được chuẩn hóa/kiểm tra/kiểm tra trong .NET để lấy chuỗi tùy ý và xâu chuỗi theo cách sao cho nó đại diện cho tên tệp hợp lệ không?Tên tập tin an toàn/cho phép của .NET

Việc cuộn chức năng thay thế char của riêng mình là đủ dễ dàng, nhưng tôi muốn thứ gì đó mạnh mẽ hơn và được phục hồi lại.

Trả lời

9

Vấn đề này không đơn giản như bạn nghĩ. Không chỉ là các ký tự trong Path.GetInvalidFileNameChars bất hợp pháp, có một số tên tệp, chẳng hạn như "PRN" và "CON", được dành riêng cho Windows và không thể tạo được. Bất kỳ tên nào kết thúc bằng "." cũng là bất hợp pháp trong Windows. Hơn nữa, có những giới hạn độ dài khác nhau. Đọc toàn bộ danh sách here.

Nếu không đủ, hệ thống tệp khác nhau có các giới hạn khác nhau, ví dụ: tên tệp ISO 9660 không thể bắt đầu bằng "-" nhưng có thể chứa nó.

+0

Đây là * chính xác * lý do tại sao tôi không muốn thử lăn của riêng tôi với một thay thế regex đơn giản. Cảm ơn. –

1

Bạn đã xem Path.GetInvalidFileNameChars chưa?

Tìm thấy tại Really Useful .NET Classes Part 1 - System.IO.Path

+0

Đó cộng với một regex là dự phòng của tôi; lý tưởng tôi muốn một cái gì đó mà thay thế là tốt. –

13

Bạn có thể sử dụng Path.GetInvalidFileNameChars kiểm tra mà ký tự của chuỗi không hợp lệ, và một trong hai chuyển đổi chúng sang một char có giá trị như một gạch nối, hoặc (nếu bạn cần chuyển đổi hai chiều) thay thế chúng bằng một mã thông báo thoát như %, theo sau biểu diễn thập lục phân mã unicode của chúng (tôi đã thực sự sử dụng kỹ thuật này một lần nhưng không có mã ngay bây giờ).

EDIT: Chỉ trong trường hợp ai đó quan tâm, đây là mã.

/// <summary> 
/// Escapes an object name so that it is a valid filename. 
/// </summary> 
/// <param name="fileName">Original object name.</param> 
/// <returns>Escaped name.</returns> 
/// <remarks> 
/// All characters that are not valid for a filename, plus "%" and ".", are converted into "%uuuu", where uuuu is the hexadecimal 
/// unicode representation of the character. 
/// </remarks> 
private string EscapeFilename(string fileName) 
{ 
    char[] invalidChars=Path.GetInvalidFileNameChars(); 

    // Replace "%", then replace all other characters, then replace "." 

    fileName=fileName.Replace("%", "%0025"); 
    foreach(char invalidChar in invalidChars) 
    { 
     fileName=fileName.Replace(invalidChar.ToString(), string.Format("%{0,4:X}", Convert.ToInt16(invalidChar)).Replace(' ', '0')); 
    } 
    return fileName.Replace(".", "%002E"); 
} 

/// <summary> 
/// Unescapes an escaped file name so that the original object name is obtained. 
/// </summary> 
/// <param name="escapedName">Escaped object name (see the EscapeFilename method).</param> 
/// <returns>Unescaped (original) object name.</returns> 
public string UnescapeFilename(string escapedName) 
{ 
    //We need to temporarily replace %0025 with %! to prevent a name 
    //originally containing escaped sequences to be unescaped incorrectly 
    //(for example: ".%002E" once escaped is "%002E%0025002E". 
    //If we don't do this temporary replace, it would be unescaped to "..") 

    string unescapedName=escapedName.Replace("%0025", "%!"); 
    Regex regex=new Regex("%(?<esc>[0-9A-Fa-f]{4})"); 
    Match m=regex.Match(escapedName); 
    while(m.Success) 
    { 
     foreach(Capture cap in m.Groups["esc"].Captures) 
      unescapedName=unescapedName.Replace("%"+cap.Value, Convert.ToChar(int.Parse(cap.Value, NumberStyles.HexNumber)).ToString()); 
     m=m.NextMatch(); 
    } 
    return unescapedName.Replace("%!", "%"); 
} 
+0

Và -1 vì ...? – Konamiman

2

Bạn có thể cung cấp thêm chi tiết về ý nghĩa của từ "tạo ra từ chuỗi tùy ý" không? Dựa trên những gì bạn nói, có vẻ như bạn đang yêu cầu

Có cách nào để lấy chuỗi tùy ý và mang theo một cách sao cho nó đại diện cho tên tệp hợp lệ không?

Nếu trường hợp đó xảy ra thì không có chức năng chuẩn nào mà tôi biết. Tuy nhiên, bạn có thể sử dụng những điều sau đây cần thực hiện thủ thuật

public static string MakeValidFileName(string name) { 
    var invalid = Path.GetInvalidFileNameChars(); 
    var builder = new StringBuilder(); 
    foreach (var cur in name) { 
    builder.Append(invalid.Contains(cur) ? '_' : cur); 
    } 
    return builder.ToString(); 
} 
+0

Đã chỉnh sửa câu hỏi để sử dụng cách phát âm của bạn ... cảm ơn! –

0

Chỉ cần cho những niềm vui của nó, tôi đã làm điều đó trong một dòng ..

Regex.Replace("http://codereview.stackexchange.com/questions/33851/how-can-i-improve-my-code/33857#33857", "[" + string.Join("", Path.GetInvalidFileNameChars().Select (p => p.ToString())) + "]", "_") 
Các vấn đề liên quan