我目前正在开发一个遍历各种目录的程序,以确保使用File.Exists()
存在特定文件。
应用程序声称某些文件实际存在时不存在,我最近发现此错误是由于路径太长。
我发现SO上有一些问题可以解决File.Exists()
返回错误值的问题,但似乎都没有解决这个问题。
重命名目录和文件以缩短路径实际上不是一个选项,所以我不知道此时该怎么做。有解决这个问题的解决办法吗?
正在使用的代码没有什么特别之处(我已经删除了一些不相关的代码),但我会将其包含在下面以防它有用。
private void checkFile(string path)
{
if (!File.Exists(path))
Console.WriteLine(" * File: " + path + " does not exist.");
}
答案 0 :(得分:12)
来自MSDN - Naming Files, Paths, and Namespaces:
在Windows API中(以下讨论了一些例外情况) 段落),路径的最大长度是MAX_PATH,即 定义为260个字符。
...
Windows API具有许多也具有Unicode版本的函数 允许一个扩展长度的路径,最大总路径长度为 32,767个字符。这种类型的路径由组件组成 用反斜杠分隔,每个都取决于返回的值 GetVolumeInformation的lpMaximumComponentLength参数 function(此值通常为255个字符)。 指定 扩展长度路径,使用
"\\?\"
前缀。例如,"\\?\D:\very long path"
。...
因为您不能将
"\\?\"
前缀与相对路径一起使用, 相对路径始终限制为总共MAX_PATH个字符。
(强调补充)
如果所有路径都是完整路径,则可以更新代码以使用扩展长度路径说明符,如下所示:
const longPathSpecifier = @"\\?";
private void checkFile(string path)
{
// Add the long-path specifier if it's missing
string longPath = (path.StartsWith(longPathSpecifier) ? path : longPathSpecifier + path);
if (!File.Exists(longPath))
{
// Print the original path
Console.WriteLine(" * File: " + path + " does not exist.");
}
}
<强>更新强>
对于文件I / O,&#34; \?\&#34;路径字符串的前缀告诉Windows 用于禁用所有字符串解析并发送后续字符串的API 它直接到文件系统。例如,如果是文件系统 支持大路径和文件名,可以超过MAX_PATH Windows API强制执行的限制。
至少在我的系统上(使用Windows 7),不支持长文件名,因此我无法验证上述解决方案是否适合您。
更新:我找到了一个可行的解决方案,但它相当难看。这是我在伪代码中所做的:
dir.GetDirectories()
并检查结果中是否包含下一个目录
湾如果是这样,请将dir
设置为DirectoryInfo
并继续挖掘
C。如果没有,则路径不存在dir.GetFiles()
并查看我们的文件是否存在于返回的FileInfo
对象中。 答案 1 :(得分:10)
这是丑陋而低效的,但它可以绕过MAX_PATH限制:
const int MAX_PATH = 260;
private static void checkPath(string path)
{
if (path.Length >= MAX_PATH)
{
checkFile_LongPath(path);
}
else if (!File.Exists(path))
{
Console.WriteLine(" * File: " + path + " does not exist.");
}
}
这是checkFile_LongPath函数:
private static void checkFile_LongPath(string path)
{
string[] subpaths = path.Split('\\');
StringBuilder sbNewPath = new StringBuilder(subpaths[0]);
// Build longest subpath that is less than MAX_PATH characters
for (int i = 1; i < subpaths.Length; i++)
{
if (sbNewPath.Length + subpaths[i].Length >= MAX_PATH)
{
subpaths = subpaths.Skip(i).ToArray();
break;
}
sbNewPath.Append("\\" + subpaths[i]);
}
DirectoryInfo dir = new DirectoryInfo(sbNewPath.ToString());
bool foundMatch = dir.Exists;
if (foundMatch)
{
// Make sure that all of the subdirectories in our path exist.
// Skip the last entry in subpaths, since it is our filename.
// If we try to specify the path in dir.GetDirectories(),
// We get a max path length error.
int i = 0;
while(i < subpaths.Length - 1 && foundMatch)
{
foundMatch = false;
foreach (DirectoryInfo subDir in dir.GetDirectories())
{
if (subDir.Name == subpaths[i])
{
// Move on to the next subDirectory
dir = subDir;
foundMatch = true;
break;
}
}
i++;
}
if (foundMatch)
{
foundMatch = false;
// Now that we've gone through all of the subpaths, see if our file exists.
// Once again, If we try to specify the path in dir.GetFiles(),
// we get a max path length error.
foreach (FileInfo fi in dir.GetFiles())
{
if (fi.Name == subpaths[subpaths.Length - 1])
{
foundMatch = true;
break;
}
}
}
}
// If we didn't find a match, write to the console.
if (!foundMatch)
{
Console.WriteLine(" * File: " + path + " does not exist.");
}
}
答案 2 :(得分:5)
我自己从未遇到过这个问题,另一个SO帖子的人建议打开文件的句柄,从而首先避免整个“存在”检查。不确定这是否还有“长文件名”问题:
这是第二个答案:
Check if a file/directory exists: is there a better way?
不确定这是否有用:P
答案 3 :(得分:2)
您需要P / Invoke Win32 API才能使其正常工作:
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern uint GetFileAttributes(string lpFileName);
public static bool DirectoryExists(string path)
{
uint attributes = GetFileAttributes(path.StartsWith(@"\\?\") ? path : @"\\?\" + path);
if (attributes != 0xFFFFFFFF)
{
return ((FileAttributes)attributes).HasFlag(FileAttributes.Directory);
}
else
{
return false;
}
}
public static bool FileExists(string path)
{
uint attributes = GetFileAttributes(path.StartsWith(@"\\?\") ? path : @"\\?\" + path);
if (attributes != 0xFFFFFFFF)
{
return !((FileAttributes)attributes).HasFlag(FileAttributes.Directory);
}
else
{
return false;
}
}
答案 4 :(得分:0)
检查
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="your_package.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_list" />
</provider>
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>