Я пытаюсь создать программу, которая будет рекурсивно удалять все файлы и папки с определенного FTP-пути. Моя программа работает хорошо, если в заданном пути есть только несколько файлов или каталогов. По какой-то причине, хотя, если в каталоге несколько файлов, оно просто зависает на линии ReadLine()
и в итоге получает ошибку ввода-вывода. Вот мой код:Рекурсивно удалять все файлы и папки с определенного FTP-пути
class Program
{
private const string FtpSite = "myftpsite.com";
private const string FtpUserName = "myusername";
private const string FtpPassword = "mypassword";
static void Main(string[] args)
{
DeleteFilesAndFolders("/");
}
private static void DeleteFilesAndFolders(string path)
{
if (path != null && (path.StartsWith(@"\\") || path.StartsWith("//")))
path = path.Remove(0, 1);
List<FileObject> files = DirectoryListing(path);
foreach (FileObject file in files.Where(file => !file.IsDirectory))
{
DeleteFile(path, file.FileName);
}
foreach (FileObject file in files.Where(file => file.IsDirectory))
{
DeleteFilesAndFolders(path + "/" + file.FileName);
DeleteFolder(path + "/" + file.FileName);
}
}
private static void DeleteFile(string path, string file)
{
var clsRequest = (FtpWebRequest)WebRequest.Create("ftp://" + FtpSite + path + "/" + file);
clsRequest.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
clsRequest.Method = WebRequestMethods.Ftp.DeleteFile;
using (var response = (FtpWebResponse) clsRequest.GetResponse())
{
using (Stream datastream = response.GetResponseStream())
{
if (datastream == null)
return;
using (var sr = new StreamReader(datastream))
{
sr.ReadToEnd();
sr.Close();
}
datastream.Close();
response.Close();
}
}
}
private static void DeleteFolder(string path)
{
var clsRequest = (FtpWebRequest)WebRequest.Create("ftp://" + FtpSite + path);
clsRequest.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
clsRequest.Method = WebRequestMethods.Ftp.RemoveDirectory;
using (var response = (FtpWebResponse)clsRequest.GetResponse())
{
using (Stream datastream = response.GetResponseStream())
{
if (datastream == null)
return;
using (var sr = new StreamReader(datastream))
{
sr.ReadToEnd();
sr.Close();
}
datastream.Close();
response.Close();
}
}
}
private static List<FileObject> DirectoryListing(string path)
{
var regex = new Regex(@"^([d-])([rwxt-]{3}){3}\s+\d{1,}\s+.*?(\d{1,})\s+(\w+\s+\d{1,2}\s+(?:\d{4})?)(\d{1,2}:\d{2})?\s+(.+?)\s?$",
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
var request = (FtpWebRequest)WebRequest.Create("ftp://" + FtpSite + path);
request.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
var result = new List<FileObject>();
using (var response = (FtpWebResponse) request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream == null)
return null;
using (var reader = new StreamReader(responseStream))
{
while (!reader.EndOfStream)
{
string r = reader.ReadLine();
if (string.IsNullOrWhiteSpace(r))
continue;
var reg = regex.Match(r);
var c = new FileObject
{
FileName = reg.Groups[6].Value,
IsDirectory = reg.Groups[1].Value.ToLower() == "d"
};
result.Add(c);
}
reader.Close();
}
response.Close();
}
}
return result;
}
}
И это мой простой класс контейнер FileObject:
internal class FileObject
{
public bool IsDirectory { get; set; }
public string FileName { get; set; }
}
Ваши вызовы .Close() являются избыточными с помощью блока 'using'. IDisposable.Dispose() позаботится об этом для каждого из этих методов (если не будет ошибки, о которой я не знаю). –
Попробуйте включить трассировку http://msdn.microsoft.com/en-us/library/bw00b1dc(v=vs.110).aspx и http://msdn.microsoft.com/en-us/library/hyb3xww8(v = vs.110) .aspx Также попробуйте –
@EricJ. - Я пошел вперед и удалил вызовы метода Close(). Это не исправить мою проблему, но вы правы в том, что они не нужны. – Icemanind