Как создать папку с конечной точкой (.) В.NET/C#?

Мне нужно создать папки с конечными точками (.), Используя C#. Вот мой код:

System.IO.Directory.CreateDirectory("d:\\MyCorp Inc.");

Но папка создается без конечной точки. Есть ли решение?

Я использую.NET Framework 4.5/C#. Моя файловая система NTFS в Windows 8.

5 ответов

Решение

Пытаться:

using System.Runtime.InteropServices;
class Program
{
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CreateDirectory(string lpPathName, IntPtr lpSecurityAttributes);

    private static void Main(string[] args)
    {
        CreateDirectory(@"\\?\c:\temp\MyCorp Inc.", IntPtr.Zero);
    }

И обратитесь к Вы не можете удалить файл или папку на томе файловой системы NTFS.

Microsoft clearly states that this is something that should not be done: http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx

Не заканчивайте имя файла или каталога пробелом или точкой. Хотя базовая файловая система может поддерживать такие имена, оболочка Windows и пользовательский интерфейс этого не делают. However, it is acceptable to specify a period as the first character of a name. For example, ".temp".

Это не ограничение.NET, а Win32 API. Попробуйте создать его в командной оболочке:

c:\drop>mkdir test.

c:\drop>dir
 Volume in drive C has no label.
 Volume Serial Number is C0F3-338B

 Directory of c:\drop

2013-04-02  17:54    <DIR>          .
2013-04-02  17:54    <DIR>          ..
2013-04-02  17:54    <DIR>          test

См. MSDN для именования рекомендаций. Цитировать:

• Не заканчивайте имя файла или каталога пробелом или точкой. Хотя базовая файловая система может поддерживать такие имена, оболочка Windows и пользовательский интерфейс этого не делают. Однако допустимо указывать точку в качестве первого символа имени. Например, ".temp".

Если вы действительно настаиваете на использовании конечной точки, используйте \\?\C:\path.,

c:\drop>mkdir \\?\c:\drop\test2.

c:\drop>dir
 Volume in drive C has no label.
 Volume Serial Number is C0F3-338B

 Directory of c:\drop

2013-04-02  17:58    <DIR>          .
2013-04-02  17:58    <DIR>          ..
2013-04-02  17:54    <DIR>          test
2013-04-02  17:58    <DIR>          test2.

Редактировать: как указано в содержимом, дополнительные файлы не создаются, поэтому не используйте файл. Вы можете создать поток "name" в каталоге и хранить там данные. Смотрите следующий пример:

c:\drop>mkdir "Example Company Name"
c:\drop>notepad "Example Company Name:name.txt"
c:\drop>dir
 Volume in drive C has no label.
 Volume Serial Number is C0F3-338B

 Directory of c:\drop

2013-04-02  18:25    <DIR>          .
2013-04-02  18:25    <DIR>          ..
2013-04-02  18:25    <DIR>          Example Company Name
               0 File(s)              0 bytes
               3 Dir(s)  77,336,379,392 bytes free
c:\drop>dir "Example Company Name"
 Volume in drive C has no label.
 Volume Serial Number is C0F3-338B

 Directory of c:\drop\Example Company Name

2013-04-02  18:25    <DIR>          .
2013-04-02  18:25    <DIR>          ..
               0 File(s)              0 bytes
               2 Dir(s)  77,336,313,856 bytes free

Или в.NET:

class Program
{
    static void Main(string[] args)
    {
        string companyName = "Example Company?*, Inc.";

        //Example Company Inc
        var sanitizedName = sanitize(companyName);

        //Create the directory
        Directory.CreateDirectory(sanitizedName);

        //Create the name store
        var nameStreamPath = sanitizedName + ":Name";
        writeFileContent(companyName, nameStreamPath);

        //Try to return the name
        Console.WriteLine(getFileContent(nameStreamPath));
        Console.ReadLine();
    }

    private static string getFileContent(string path)
    {
        using (var sr = new StreamReader(new FileStream(
            // we have to call CreateFile directly to avoid overzealous path validation
            NativeMethods.CreateFileOrFail(path, false), FileAccess.Read)))
        {
            return sr.ReadToEnd();
        }
    }

    private static void writeFileContent(string companyName, string path)
    {
        using (var sw = new StreamWriter(new FileStream(
            // We have to call CreateFile directly to avoid overzealous path validation
            NativeMethods.CreateFileOrFail(path, true), FileAccess.Write)))
        {
            sw.Write(companyName);
        }
    }

    private static string sanitize(string path)
    {
        char[] newPath = new char[path.Length];
        int newPathLoc = 0;
        for (int i = 0; i < path.Length; i++)
        {
            if (char.IsLetter(path[i]) || char.IsDigit(path[i]))
            {
                newPath[newPathLoc] = path[i];
                newPathLoc++;
            }
        }
        return new string(newPath, 0, newPathLoc);
    }
}

class NativeMethods
{
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern SafeFileHandle CreateFile(
        string fileName,
        [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
        [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
        IntPtr securityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        [MarshalAs(UnmanagedType.U4)] FileAttributes flags,
        IntPtr template);

    public static SafeFileHandle CreateFileOrFail(string path, bool write)
    {
        var handle = CreateFile(path,
            write ? FileAccess.Write : FileAccess.Read,
            write ? FileShare.None : FileShare.Read,
            IntPtr.Zero,
            write ? FileMode.Create : FileMode.Open,
            FileAttributes.Normal,
            IntPtr.Zero);

        if (handle.IsInvalid)
            throw new System.ComponentModel.Win32Exception();

        return handle;
    }
}

Обновлено:

Я заметил две вещи!

1) Ваше требование:

У меня есть много клиентов, которые называют свои папки в соответствии с названием компании, например, "Some Corp Ltd.", эти имена часто содержат конечные точки. Я не могу хранить имена в другом месте, у меня нет базы данных и я не могу создавать дополнительные файлы, это требование.

2) у вас нет ответа

Я предлагаю добавить дополнительный символ в конце имени каталога, который будет скрыт для обычного просмотра, но все еще существует! Что делает нас счастливыми!

Попробуй это

Вы должны добавить специальный символ в конце имени каталога

System.IO.Directory.CreateDirectory
                    (@"D:\Sync.inc." + (char)(128));

Примечание:(символ)(128) - (символ)(158) может помочь

Попробуйте взрыв!

for (int i = 128; i <= 158; i++)
{
    System.IO.Directory.CreateDirectory
        (@"D:\Sync.inc." + (char)(i));
}

Во всяком случае, как от MS:

Если точка находится в конце имени, Windows по умолчанию будет игнорировать точку (точки).

Взгляните на http://social.technet.microsoft.com/Forums/en-US/w7itproui/thread/84978c71-8203-404b-94cf-b05b14be99db/

Если вы попытаетесь сделать это вручную в Проводнике Windows, даже Проводник не разрешит конечную точку и удалит ее для вас.

Я предполагаю, что это ограничение самой Windows из-за периода в конце, обычно означающего расширение файла.

В это время я бы сказал, что это невозможно.

Другие вопросы по тегам