2009-08-08 7 views
2

Ich versuche, alle Dateien und Verzeichnisse rekursiv zu kopieren, und hier ist mein Klassencode. Ich bekomme keinen Teil des Pfades. Ich nehme an, es kann sein, weil es etwa 20 Unterverzeichnisse zu Verzeichnissen gibt (Pfade wie \ game \ resources.zip \ shared \ effects \ materials \ und solche). Jede Hilfe wäre willkommen.C# konnte nicht Teil des Dateipfadfehlers

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

Sorry, ich habe den Titel falsch eingegeben. Ich versuche, eine Liste aller Dateien im Verzeichnis (Unterverzeichnisse und ihre Dateien auch) zu bekommen – Steven

Antwort

2

kopieren rekursiv diese Methode verwenden

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

Sorry, ich habe den Titel falsch eingegeben. Ich versuche, eine Liste aller Dateien im Verzeichnis (Unterverzeichnisse und ihre Dateien auch) zu bekommen – Steven

0

Nicht sicher, ob dies von Nutzen sein:

/// <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; 
} 

habe ich dies mit einem Programm, in dem der Benutzer könnte mehrere Verzeichnisse oder Dateien auswählen, die komprimiert werden sollen. Ich musste den Fall behandeln, in dem sie explizit ein Verzeichnis hinzufügten, und dann ein Unterverzeichnis/eine Unterdatei (sinnlos) dieses Verzeichnisses hinzufügte. Also habe ich das geschrieben, damit Sie mehrere Verzeichnisse und Dateien in einem Array übergeben können, und wenn sie erweitert werden, wird sichergestellt, dass keine dupliziert werden.

3

In .NET darf der vollständige Pfad zu einer Datei nicht länger als 260 Zeichen sein, wenn Sie längere Pfade verwenden möchten, müssen Sie die Win API direkt über UNC-Pfade aufrufen und Ihre Dateipfade können 32.767 Zeichen lang sein. Ich habe eine .NET-Klasse hinzugefügt, die das tut, ich habe diesen Code ursprünglich nicht geschrieben, aber leider habe ich den Originalartikel nicht gefunden, wenn ich heute nach ihm suche, also gebe ich meinen modifizierten Code hier zu Demonstrationszwecken ein, der Code ist leicht verändert aus dem ursprünglichen Code und hat einige zusätzliche Funktionen.

/* 
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

Unglaublich. Sie lernen jeden Tag etwas Neues über .Net (und manchmal ist es schrecklich, wie eine Grenze von 260 Zeichen auf Pfaden). – MusiGenesis

+0

Fast gab es eine -1 für log4net dort. Zu jedem ihren eigenen, schätze ich. :) – MusiGenesis

+1

Hallo, MusiGenesis. Die 260-Zeichen-Grenze ist nicht wirklich eine .NET-Einschränkung, sondern eine in Windows. Weitere Informationen finden Sie unter http://en.wikipedia.org/wiki/Path_%28computing%29. –

Verwandte Themen