2

我需要使用 C# 创建带有尾随点 (.) 的文件夹。这是我的代码:

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

但是该文件夹是在没有最后一个点的情况下创建的。有解决办法吗?

我正在使用 .NET Framework 4.5/C#。我的文件系统是 Windows 8 上的 NTFS。

4

5 回答 5

7

微软明确指出这是不应该做的事情:http: //msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx

不要以空格或句点结尾的文件或目录名称。尽管底层文件系统可能支持此类名称,但 Windows shell 和用户界面不支持。但是,可以将句点指定为名称的第一个字符。例如,“.temp”。

于 2013-04-02T23:03:31.623 回答
4

这不是 .NET 的限制,而是Win32 API 的限制。尝试在命令 shell 中创建一个:

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 shell 和用户界面不支持。但是,可以将句点指定为名称的第一个字符。例如,“.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.

编辑:内容中列出的要求是不创建其他文件,因此不要使用文件。您可以在目录上创建一个“名称”流并将数据存储在那里。有关示例,请参见以下内容:

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;
    }
}
于 2013-04-02T22:55:50.280 回答
1

尝试:

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 文件系统卷上的文件或文件夹

于 2013-04-02T22:59:14.370 回答
1

更新:

我注意到了两件事!

1)您的要求:

我有很多客户根据公司名称命名他们的文件夹,例如“Some Corp Ltd.”,这些名称通常包含尾随点。我不能在其他任何地方存储名称,我没有数据库,也不能创建额外的文件,这是要求。

2) 你没有得到答案

我的建议是在目录名称的末尾添加一个额外的字符,这将对普通视图隐藏,但仍然存在!这让我们很高兴!

试试这个

您必须在目录名称的末尾附加一个特殊字符

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

注意:(char)(128) 到 (char)(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/

于 2013-04-02T23:09:02.220 回答
0

如果您尝试在 Windows 资源管理器中手动执行此操作,即使资源管理器也不允许尾随点并为您删除它。

我想这是 Windows 本身的限制,因为末尾的句点通常表示文件扩展名。

在这个时候我会说这是不可能的。

于 2013-04-02T22:56:21.720 回答