c # не смог получить часть ошибки пути к файлу

2

Я пытаюсь рекурсивно копировать все файлы и каталоги, и вот мой код класса. Я получаю не могу найти часть пути. Я предполагаю, что это может быть потому, что в каталоги содержится около 20 подкаталогов (такие как\game\resour.zip\shared\effects\materials\и т.д.). Любая помощь будет оценена.

    static IEnumerable<string> GetFiles(string path)
    {
        Queue<string> queue = new Queue<string>();
        queue.Enqueue(path);
        while (queue.Count > 0)
        {
            path = queue.Dequeue();
            try
            {
                foreach (string subDir in Directory.GetDirectories(path))
                {
                    queue.Enqueue(subDir);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            string[] files = null;
            try
            {
                files = Directory.GetFiles(path);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            if (files != null)
            {
                for (int i = 0; i < files.Length; i++)
                {
                    yield return files[i];
                }
            }
        }
    }
  • 0
    Извините, я неправильно набрал название. Я пытаюсь получить список всех файлов в каталоге (подкаталоги и их файлы также)
Теги:

3 ответа

2
Лучший ответ

чтобы скопировать рекурсивно этот метод

static public void CopyFolder( string sourceFolder, string destFolder )
{
     if (!Directory.Exists( destFolder ))
     Directory.CreateDirectory( destFolder );
     string[] files = Directory.GetFiles( sourceFolder );
     foreach (string file in files)
     {
        string name = Path.GetFileName( file );
        string dest = Path.Combine( destFolder, name );
        File.Copy( file, dest );
     }
     string[] folders = Directory.GetDirectories( sourceFolder );
     foreach (string folder in folders)
     {
         string name = Path.GetFileName( folder );
         string dest = Path.Combine( destFolder, name );
         CopyFolder( folder, dest );
   }

}

  • 0
    Извините, я неправильно набрал название. Я пытаюсь получить список всех файлов в каталоге (подкаталоги и их файлы также)
3

В .NET полный путь к файлу не может быть длиннее 260 символов, если вы не используете более длинные пути, вы должны напрямую вызвать Win API с помощью UNC-путей, а ваши пути к файлам могут быть 32 767 символов, я добавили .NET-класс, который делает это, я не писал этот код изначально, но, к сожалению, я не нашел оригинальную статью при поиске ее сегодня, поэтому я просто введу свой модифицированный код здесь для демонстрационных целей, код немного изменен от исходный код и имеет дополнительную функциональность.

/* 
All sample code is provided by the Inge Henriksen for illustrative purposes only. These examples have not been thoroughly tested under all conditions. Inge Henriksen, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs.
 */
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.IO;
using log4net;

namespace MyStuff.DAL.Services.IO.File
{
    /// <summary>
    /// Class for communicating with the Windows kernel library for low-level disk access.
    /// The main purpose of this class is to allow for longer file paths than System.IO.File,
    /// this class handles file paths up to 32,767 characters. 
    /// Note: Always be careful when accessing this class from a managed multi-threaded application
    /// as the unmanaged Windows kernel is different, this "crash" causes application unstability 
    /// if not handled properly.
    /// TODO: Look into if there are any significant gains on 64-bit systems using another kind of 
    /// core component than kernel32.dll.
    /// </summary>
    public class Win32File
    {
        ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        #region DLLImport's
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool MoveFile(string lpExistingFileName, string lpNewFileName);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool DeleteFile(string lpFileName);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool CreateDirectoryW(string lpPathName, IntPtr lpSecurityAttributes);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern SafeFileHandle CreateFileW(string lpFileName, uint dwDesiredAccess,
                                              uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
                                              uint dwFlagsAndAttributes, IntPtr hTemplateFile);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern uint SetFilePointer(SafeFileHandle hFile, long lDistanceToMove, IntPtr lpDistanceToMoveHigh, uint dwMoveMethod);

        #endregion

        // uint GetMode( FileMode mode )
        // Converts the filemode constant to win32 constant
        #region GetMode
        private uint GetMode(FileMode mode)
        {
            Log.Debug("Get Win32 file mode");
            uint umode = 0;
            switch (mode)
            {
                case FileMode.CreateNew:
                    umode = Win32FileAttributes.CREATE_NEW;
                    break;
                case FileMode.Create:
                    umode = Win32FileAttributes.CREATE_ALWAYS;
                    break;
                case FileMode.Append:
                    umode = Win32FileAttributes.OPEN_ALWAYS;
                    break;
                case FileMode.Open:
                    umode = Win32FileAttributes.OPEN_EXISTING;
                    break;
                case FileMode.OpenOrCreate:
                    umode = Win32FileAttributes.OPEN_ALWAYS;
                    break;
                case FileMode.Truncate:
                    umode = Win32FileAttributes.TRUNCATE_EXISTING;
                    break;
            }
            return umode;
        }
        #endregion

        // uint GetAccess(FileAccess access)
        // Converts the FileAccess constant to win32 constant
        #region GetAccess
        private uint GetAccess(FileAccess access)
        {
            Log.Debug("Get Win32 file access");
            uint uaccess = 0;
            switch (access)
            {
                case FileAccess.Read:
                    uaccess = Win32FileAttributes.GENERIC_READ;
                    break;
                case FileAccess.ReadWrite:
                    uaccess = Win32FileAttributes.GENERIC_READ | Win32FileAttributes.GENERIC_WRITE;
                    break;
                case FileAccess.Write:
                    uaccess = Win32FileAttributes.GENERIC_WRITE;
                    break;
            }
            return uaccess;
        }
        #endregion

        // uint GetShare(FileShare share)
        // Converts the FileShare constant to win32 constant
        #region GetShare
        private uint GetShare(FileShare share)
        {
            Log.Debug("Get Win32 file share");
            uint ushare = 0;
            switch (share)
            {
                case FileShare.Read:
                    ushare = Win32FileAttributes.FILE_SHARE_READ;
                    break;
                case FileShare.ReadWrite:
                    ushare = Win32FileAttributes.FILE_SHARE_READ | Win32FileAttributes.FILE_SHARE_WRITE;
                    break;
                case FileShare.Write:
                    ushare = Win32FileAttributes.FILE_SHARE_WRITE;
                    break;
                case FileShare.Delete:
                    ushare = Win32FileAttributes.FILE_SHARE_DELETE;
                    break;
                case FileShare.None:
                    ushare = 0;
                    break;

            }
            return ushare;
        }
        #endregion

        public bool Move(string existingFile, string newFile)
        {
            Log.Debug(String.Format("Rename the file \"{0}\" to \"{1}\"", existingFile, newFile) );
            return Win32File.MoveFile(existingFile, newFile);
        }

        public bool CreateDirectory(string filepath)
        {
            Log.Debug(String.Format("Create the directory \"{0}\"", filepath));
            // If file path is disk file path then prepend it with \\?\
            // if file path is UNC prepend it with \\?\UNC\ and remove \\ prefix in unc path.
            if (filepath.StartsWith(@"\\"))
                filepath = @"\\?\UNC\" + filepath.Substring(2, filepath.Length - 2);
            else
                filepath = @"\\?\" + filepath;
            return CreateDirectoryW(filepath, IntPtr.Zero);
        }

        public FileStream Open(string filepath, FileMode mode, uint uaccess)
        {
            Log.Debug(String.Format("Open the file \"{0}\"", filepath));

            //opened in the specified mode and path, with read/write access and not shared
            FileStream fs = null;
            uint umode = GetMode(mode);
            uint ushare = 0;    // Not shared
            if (mode == FileMode.Append) uaccess = Win32FileAttributes.FILE_APPEND_DATA;

            // If file path is disk file path then prepend it with \\?\
            // if file path is UNC prepend it with \\?\UNC\ and remove \\ prefix in unc path.
            if (filepath.StartsWith(@"\\"))
                filepath = @"\\?\UNC\" + filepath.Substring(2, filepath.Length - 2);
            else filepath = @"\\?\" + filepath;

            SafeFileHandle sh = CreateFileW(filepath, uaccess, ushare, IntPtr.Zero, umode, Win32FileAttributes.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
            int iError = Marshal.GetLastWin32Error();
            if ((iError > 0 && !(mode == FileMode.Append && iError == Win32FileAttributes.ERROR_ALREADY_EXISTS)) || sh.IsInvalid)
            {
                Log.Error(String.Format("Error opening file; Win32 Error: {0}", iError));
                throw new Exception("Error opening file; Win32 Error:" + iError);
            }
            else
            {
                fs = new FileStream(sh, FileAccess.ReadWrite);
            }

            // if opened in append mode
            if (mode == FileMode.Append)
            {
                if (!sh.IsInvalid)
                {
                    SetFilePointer(sh, 0, IntPtr.Zero, Win32FileAttributes.FILE_END);
                }
            }

            Log.Debug(String.Format("The file \"{0}\" is now open", filepath));
            return fs;
        }

        public FileStream Open(string filepath, FileMode mode, FileAccess access)
        {
            Log.Debug(String.Format("Open the file \"{0}\"", filepath));

            //opened in the specified mode and access and not shared
            FileStream fs = null;
            uint umode = GetMode(mode);
            uint uaccess = GetAccess(access);
            uint ushare = 0;    // Exclusive lock of the file

            if (mode == FileMode.Append) uaccess = Win32FileAttributes.FILE_APPEND_DATA;

            // If file path is disk file path then prepend it with \\?\
            // if file path is UNC prepend it with \\?\UNC\ and remove \\ prefix in unc path.
            if (filepath.StartsWith(@"\\"))
                filepath = @"\\?\UNC\" + filepath.Substring(2, filepath.Length - 2);
            else
                filepath = @"\\?\" + filepath;

            SafeFileHandle sh = CreateFileW(filepath, uaccess, ushare, IntPtr.Zero, umode, Win32FileAttributes.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
            int iError = Marshal.GetLastWin32Error();
            if ((iError > 0 && !(mode == FileMode.Append && iError != Win32FileAttributes.ERROR_ALREADY_EXISTS)) || sh.IsInvalid)
            {
                Log.Error(String.Format("Error opening file; Win32 Error: {0}", iError));
                throw new Exception("Error opening file; Win32 Error:" + iError);
            }
            else
            {
                fs = new FileStream(sh, access);
            }

            // if opened in append mode
            if (mode == FileMode.Append)
            {
                if (!sh.IsInvalid)
                {
                    SetFilePointer(sh, 0, IntPtr.Zero, Win32FileAttributes.FILE_END);
                }
            }

            Log.Debug(String.Format("The file \"{0}\" is now open", filepath));
            return fs;
        }

        public FileStream Open(string filepath, FileMode mode, FileAccess access, FileShare share)
        {
            //opened in the specified mode , access and  share
            FileStream fs = null;
            uint umode = GetMode(mode);
            uint uaccess = GetAccess(access);
            uint ushare = GetShare(share);
            if (mode == FileMode.Append) uaccess = Win32FileAttributes.FILE_APPEND_DATA;

            // If file path is disk file path then prepend it with \\?\
            // if file path is UNC prepend it with \\?\UNC\ and remove \\ prefix in unc path.
            if (filepath.StartsWith(@"\\"))
                filepath = @"\\?\UNC\" + filepath.Substring(2, filepath.Length - 2);
            else
                filepath = @"\\?\" + filepath;
            SafeFileHandle sh = CreateFileW(filepath, uaccess, ushare, IntPtr.Zero, umode, Win32FileAttributes.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
            int iError = Marshal.GetLastWin32Error();
            if ((iError > 0 && !(mode == FileMode.Append && iError != Win32FileAttributes.ERROR_ALREADY_EXISTS)) || sh.IsInvalid)
            {
                throw new Exception("Error opening file Win32 Error:" + iError);
            }
            else
            {
                fs = new FileStream(sh, access);
            }
            // if opened in append mode
            if (mode == FileMode.Append)
            {
                if (!sh.IsInvalid)
                {
                    SetFilePointer(sh, 0, IntPtr.Zero, Win32FileAttributes.FILE_END);
                }
            }
            return fs;
        }

        public FileStream OpenRead(string filepath)
        {
            Log.Debug(String.Format("Open the file \"{0}\"", filepath));
            // Open readonly file mode open(String, FileMode.Open, FileAccess.Read, FileShare.Read)
            return Open(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
        }

        public FileStream OpenWrite(string filepath)
        {
            Log.Debug(String.Format("Open the file \"{0}\" for writing", filepath));
            //open writable open(String, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None).
            return Open(filepath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
        }

        public bool Delete(string filepath)
        {
            Log.Debug(String.Format("Delete the file \"{0}\"", filepath));
            // If file path is disk file path then prepend it with \\?\
            // if file path is UNC prepend it with \\?\UNC\ and remove \\ prefix in unc path.
            if (filepath.StartsWith(@"\\"))
                filepath = @"\\?\UNC\" + filepath.Substring(2, filepath.Length - 2);
            else
                filepath = @"\\?\" + filepath;
            Log.Debug(String.Format("The file \"{0}\" has been deleted", filepath));
            return DeleteFile(filepath);
        }
    }
}
  • 2
    Невероятно. Каждый день вы узнаете что-то новое о .Net (и иногда это ужасно, например ограничение в 260 символов на пути).
  • 0
    Почти дал вам -1 за наличие там log4net. Каждому свое, наверное. :)
Показать ещё 2 комментария
0

Не уверен, что это будет полезно:

/// <summary>
/// Operates just like GetFileSystemInfos except it is recursive, operates on more than
/// one FileSystemInfo, ensures no paths are duplicateed, and includes the original
/// items in the return.
/// </summary>
/// <param name="files">A collection of files and/or directories to expand.</param>
/// <returns>A Dictionary of all file, directories, and subfiles and subdirectories of 
/// those directories and subdirectories.  The key is the fullpath, and the value
/// is the FileSystemInfo.</returns>
public static Dictionary<string, FileSystemInfo> ExpandFileSystemInfos(FileSystemInfo[] files)
{
  Dictionary<string, FileSystemInfo> resultingFiles = new Dictionary<string,FileSystemInfo>();

  //GetFileSystemInfosRecursively will expand everything, except it may contain duplicates
  foreach (FileSystemInfo file in GetFileSystemInfosRecursively(files))
  {//so we just go through adding them to the Dictionary
    if (!resultingFiles.ContainsKey(file.FullName))
    {
      resultingFiles.Add(file.FullName, file);
    }
  }
  return resultingFiles;
}

//helper method for ExpandFileSystemInfos
private static List<FileSystemInfo> GetFileSystemInfosRecursively(FileSystemInfo[] files)
{
  List<FileSystemInfo> resultingFiles = new List<FileSystemInfo>();
  foreach (FileSystemInfo file in files)
  {
    if (file is DirectoryInfo)
    {
      //get its sub items and pass to another function to process
      DirectoryInfo dir = (DirectoryInfo)file;

      //recursive call, passing in subdirectories and files of current directory.  
      //The result returned will be all subdirectories and files nested within the current
      //dir.  So we add them to our collection of results for each directory we encounter.
      resultingFiles.AddRange(GetFileSystemInfosRecursively(dir.GetFileSystemInfos()));          
    }
    //else do nothing, it is a file we already know about
  }
  //resultingFiles now contains all sub items
  //It does not include the directories and files in files however, so we add them as well
  resultingFiles.AddRange(files);

  return resultingFiles;
}

Я использовал это с программой, в которой пользователь мог выбрать несколько каталогов или файлов для сжатия. Мне пришлось обработать случай, когда они явно добавили каталог, а затем добавили подкаталог/подфайл (бессмысленно) этого каталога. Поэтому я написал это для того, чтобы вы могли передавать несколько каталогов и файлов в массиве, и, поскольку он расширяет их, он будет уверен, что ни один из них не дублируется.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню