5

私はC#でさまざまなファイル機能を使用しようとしてFile.GetLastWriteTimeいます。たとえば、Windows 7で許可されている最大パスよりも大きいパス(260)に配置されたファイルにコマンドをコピーします。長いパス名でエラーが発生します。MSDNサポートでは\\?\、パスの前にbeforeを使用するように依頼されました。同じことをしましたが、それでも同じエラーが発生しました。何も変更されていないようです。以下は私のコードです。私がそれを正しく使用しているか、何かを追加する必要があるかどうかを教えてください:
コードが他のものも持っているので私が使用しているこれらのすべてのlib:

以下はそれぞれのコードです:

filesToBeCopied = Directory.GetFiles(path,"*",SearchOption.AllDirectories);
for (int j = 0; j < filesToBeCopied.Length; j++)
{
    try
    {
        String filepath = @"\\?\" + filesToBeCopied[j];
        File.GetLastWriteTime(filepath);
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error Inside the single file iteration for the path:" +
            filesToBeCopied[j] + " . The exception is :" + ex.Message);
    }
}

ここで、pathは、ドライブ文字で始まるWindowsマシンのフォルダへのパスです。例:d:\abc\bcd\cd\cdc\dc\..........

4

4 に答える 4

7

リクエストの少なくともコピー部分の解決策は次のとおりです(pinvoke.netに感謝します):

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);

そして、実際にファイルをコピーするには:

// Don't forget the '\\?\' for long paths
string reallyLongPath = @"\\?\d:\abc\bcd\cd\cdc\dc\..........";
string destination = @"C:\some\other\path\filename.txt";
CopyFile(reallyLongPath , destination, false);
于 2012-08-30T20:46:40.783 に答える
3

私の知る限り、パスが長すぎる場合、ファイルに直接アクセスすることはできません (直接とは、 のメソッドを使用するか、コンストラクターを介してFileを作成するか、 .FileInfoDirectory.GetFiles(string fileName)

このようなファイルにアクセスできるようにする唯一の方法は、パスが長くなりすぎる前にパスのどこかにあるディレクトリにアクセスし、次に示すように、ファイルに到達するまでプログラムでツリーをたどることです

そこからコードを取得FileInfoし、パスが「長すぎる」ファイルのオブジェクトを返すように少し変更しました。このコードを使用すると、返されたオブジェクト ( など) の必要なプロパティにアクセスできます。 ただし、 や などの機能を使用できないなど、まだいくつかの制限がありますFileInfoLastWriteTimeCopyTo()OpenText()

// Only call GetFileWithLongPath() if the path is too long
// ... otherwise, new FileInfo() is sufficient
private static FileInfo GetFile(string path)
{
    if (path.Length >= MAX_FILE_PATH)
    {
        return GetFileWithLongPath(path);
    }
    else return new FileInfo(path);
}

static int MAX_FILE_PATH = 260;
static int MAX_DIR_PATH = 248;

private static FileInfo GetFileWithLongPath(string path)
{
    string[] subpaths = path.Split('\\');
    StringBuilder sbNewPath = new StringBuilder(subpaths[0]);
    // Build longest sub-path that is less than MAX_PATH characters 
    for (int i = 1; i < subpaths.Length; i++)
    {
        if (sbNewPath.Length + subpaths[i].Length >= MAX_DIR_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)
        {
            // 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])
                {
                    return fi;
                }
            }
        }
    }
    // If we didn't find a match, return null;
    return null;
}

それを見たので、目をすすぎ、道を短くしてください。

于 2012-08-30T20:03:29.070 に答える
1

このコードで試してください

var path = Path.Combine(@"\\?\", filesToBeCopied[j]); //don't forget extension

パス文字列の "\?\" プレフィックスは、すべての文字列解析を無効にし、それに続く文字列をファイル システムに直接送信するよう Windows API に指示します。

重要 : すべてのファイル I/O API が「\?\」をサポートしているわけではありません。各 API のリファレンス トピックを参照してください。

于 2012-08-30T19:39:33.300 に答える
-1

http://www.codinghorror.com/blog/2006/11/filesystem-paths-how-long-is-too-long.html

最近、パスの最大制限である 256 文字を超えた顧客のソース コードをインポートしました。

貼り付けたパスの長さは 285 文字でした。

コメントで指摘したように、ここの MSDN のリンク ( http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#maximum%5Fpath%5Flength ) は、この長さをより詳細に説明しています。

Windows API (次の段落で説明するいくつかの例外を除く) では、パスの最大長は MAX_PATH であり、260 文字として定義されています。ローカル パスは、ドライブ文字、コロン、バックスラッシュ、バックスラッシュで区切られた名前コンポーネント、および終端のヌル文字の順序で構成されます。たとえば、ドライブ D の最大パスは "D:\some 256-character path string" です。"" は、現在のシステム コードページの非表示の終了ヌル文字を表します。(文字 < > は視覚的にわかりやすくするためにここで使用されており、有効なパス文字列の一部にすることはできません。)

機能に関して\\?\

すべてではありませんが、多くのファイル I/O API が "\?\" をサポートしています。各 API のリファレンス トピックを確認してください。

于 2012-08-30T19:46:22.090 に答える