问题
I need to create folders with trailing dots (.) using C#. Here is my code:
System.IO.Directory.CreateDirectory("d:\\MyCorp Inc.");
But the folder is created without the final dot. Is there a solution?
I am using .NET Framework 4.5/C#. My file system is NTFS, on Windows 8.
回答1:
Try:
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);
}
And refer to You cannot delete a file or a folder on an NTFS file system volume.
回答2:
Microsoft clearly states that this is something that should not be done: http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx
Do not end a file or directory name with a space or a period. Although the underlying file system may support such names, the Windows shell and user interface does not. However, it is acceptable to specify a period as the first character of a name. For example, ".temp".
回答3:
That is not a limitation of .NET, but of the Win32 API. Try to create one in a command 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
See MSDN for naming reccomendations. To quote:
•Do not end a file or directory name with a space or a period. Although the underlying file system may support such names, the Windows shell and user interface does not. However, it is acceptable to specify a period as the first character of a name. For example, ".temp".
If you are really quite insistent on using a trailing dot, use \\?\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.
Edit: The requirement as listed in the contents is that no additional files are created, so don't use a file. You can create a "name" stream on the directory and store data there. See the following for an example:
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
Or in .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;
}
}
回答4:
Updated:
I have noticed two things!
1) Your requirement:
I have many customers that name their folders according to company name, for example "Some Corp Ltd.", these names often contain trailing dots. I can not store names anywhere else, I do not have database and I can not create extra files, this is the requirement.
2) You haven't got an answer
My suggestion is to add an extra character at the end of directory name, which will be hidden to normal view, but still exist! Which makes us happy!
Try this
You have to append a special character at the end of the directory name
System.IO.Directory.CreateDirectory
(@"D:\Sync.inc." + (char)(128));
Note:(char)(128) to (char)(158) may help
Try a blast!
for (int i = 128; i <= 158; i++)
{
System.IO.Directory.CreateDirectory
(@"D:\Sync.inc." + (char)(i));
}
Anyway as from MS:
If the dot is at the end of the name, Windows will ignore the dot(s) by default.
Have a look at http://social.technet.microsoft.com/Forums/en-US/w7itproui/thread/84978c71-8203-404b-94cf-b05b14be99db/
回答5:
If you attempt to do this manually in Windows Explorer even Explorer does not allow the trailing dot and removes it for you.
I imagine this is a limitation of Windows itself owing to a period at the end usually signifying a file extension.
At this time I would say it is not possible.
来源:https://stackoverflow.com/questions/15775867/how-to-create-folder-with-trailing-dot-in-net-c