parsingFtpWebRequest的ListDirectoryDetails行
我需要一些帮助parsing来自C#中的ListDirectoryDetails
响应。
我只需要以下字段。
- 文件名/目录名称
- 创builddate
- 和文件大小。
当我运行ListDirectoryDetails
时,下面是一些行的样子:
d--x--x--x 2 ftp ftp 4096 Mar 07 2002 bin -rw-r--r-- 1 ftp ftp 659450 Jun 15 05:07 TEST.TXT -rw-r--r-- 1 ftp ftp 101786380 Sep 08 2008 TEST03-05.TXT drwxrwxr-x 2 ftp ftp 4096 May 06 12:24 dropoff
提前致谢。
不知道你是否仍然需要这个,但这是我想出的解决scheme:
Regex 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 );
比赛组:
- 对象types:
- d:目录
- – :文件
- 数组[3]权限(rwx-)
- 文件大小
- 上次修改date
- 上次修改时间
- 文件/目录名称
对于这个具体的清单,下面的代码将做到:
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/"); request.Credentials = new NetworkCredential("user", "password"); request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream()); string pattern = @"^([\w-]+)\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+" + @"(\w+\s+\d+\s+\d+|\w+\s+\d+\s+\d+:\d+)\s+(.+)$"; Regex regex = new Regex(pattern); IFormatProvider culture = CultureInfo.GetCultureInfo("en-us"); string[] hourMinFormats = new[] { "MMM dd HH:mm", "MMM dd H:mm", "MMM d HH:mm", "MMM d H:mm" }; string[] yearFormats = new[] { "MMM dd yyyy", "MMM d yyyy" }; while (!reader.EndOfStream) { string line = reader.ReadLine(); Match match = regex.Match(line); string permissions = match.Groups[1].Value; int inode = int.Parse(match.Groups[2].Value, culture); string owner = match.Groups[3].Value; string group = match.Groups[4].Value; long size = long.Parse(match.Groups[5].Value, culture); DateTime modified; string s = Regex.Replace(match.Groups[6].Value, @"\s+", " "); if (s.IndexOf(':') >= 0) { modified = DateTime.ParseExact(s, hourMinFormats, culture, DateTimeStyles.None); } else { modified = DateTime.ParseExact(s, yearFormats, culture, DateTimeStyles.None); } string name = match.Groups[7].Value; Console.WriteLine( "{0,-16} permissions = {1} size = {2, 9} modified = {3}", name, permissions, size, modified.ToString("yyyy-MM-dd HH:mm")); }
你会得到(截至2016年):
bin permissions = d--x--x--x size = 4096 modified = 2002-03-07 00:00 TEST.TXT permissions = -rw-r--r-- size = 659450 modified = 2016-06-15 05:07 TEST03-05.TXT permissions = -rw-r--r-- size = 101786380 modified = 2008-09-08 00:00 dropoff permissions = drwxrwxr-x size = 4096 modified = 2016-05-06 12:24
但是,实际上试图parsingListDirectoryDetails
返回的ListDirectoryDetails
是不正确的。
您希望使用支持现代MLSD
命令的FTP客户端,该命令返回RFC 3659中指定的机器可读格式的目录列表。 当与不支持MLSD
命令的废弃FTP服务器通话时,应该使用parsing由古代LIST
命令返回的可读格式(由FtpWebRequest
在其ListDirectoryDetails
方法内部使用)作为最后的选项,如Microsoft IIS FTP服务器)。
许多服务器对LIST
命令响应使用不同的格式。 特别是IIS可以使用DOS格式。 请参阅C#类来parsingWebRequestMethods.Ftp.ListDirectoryDetails FTP响应 。
例如对于WinSCP .NET程序集 ,您可以使用其Session.ListDirectory
或Session.EnumerateRemoteFiles
方法。
他们在内部使用MLSD
命令,但可以回退到LIST
命令并支持数十种不同的可读格式的列表格式。
返回的列表是作为具有以下属性的RemoteFileInfo
实例的集合呈现的:
-
Name
-
LastWriteTime
(带有正确的时区) -
Length
-
FilePermissions
(parsing成个人权利) -
Group
-
Owner
-
IsDirectory
-
IsParentDirectory
-
IsThisDirectory
(我是WinSCP的作者)
大多数其他第三方库也会这样做。 为此,使用FtpWebRequest
类是不可靠的。 不幸的是,.NET框架中没有其他内置的FTP客户端。
这是我的algorithm来获取文件/目录名称,创builddate,属性(文件/目录),大小。 希望这可以帮助…
FtpWebRequest _fwr = FtpWebRequest.Create(uri) as FtpWebRequest _fwr.Credentials = cred; _fwr.UseBinary = true; _fwr.UsePassive = true; _fwr.KeepAlive = true; _fwr.Method = WebRequestMethods.Ftp.ListDirectoryDetails; StreamReader _sr = new StreamReader(_fwr.GetResponse().GetResponseStream()); List<object> _dirlist = new List<object>(); List<object> _attlist = new List<object>(); List<object> _datelist = new List<object>(); List<long> _szlist = new List<long>(); while (!_sr.EndOfStream) { string[] buf = _sr.ReadLine().Split(' '); //string Att, Dir; int numcnt = 0, offset = 4; ; long sz = 0; for (int i = 0; i < buf.Length; i++) { //Count the number value markers, first before the ftp markers and second //the file size. if (long.TryParse(buf[i], out sz)) numcnt++; if (numcnt == 2) { //Get the attribute string cbuf = "", dbuf = "", abuf = ""; if (buf[0][0] == 'd') abuf = "Dir"; else abuf = "File"; //Get the Date if (!buf[i+3].Contains(':')) offset++; for (int j = i + 1; j < i + offset; j++) { dbuf += buf[j]; if (j < buf.Length - 1) dbuf += " "; } //Get the File/Dir name for (int j = i + offset; j < buf.Length; j++) { cbuf += buf[j]; if (j < buf.Length - 1) cbuf += " "; } //Store to a list. _dirlist.Add(cbuf); _attlist.Add(abuf); _datelist.Add(dbuf); _szlist.Add(sz); offset = 0; break; } } }
基于Ryan Conrad的正则expression式,这是我最后的阅读代码:
protected static Regex m_FtpListingRegex = new Regex(@"^([d-])((?:[rwxt-]{3}){3})\s+(\d{1,})\s+(\w+)?\s+(\w+)?\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); protected static readonly String Timeformat = "MMM dd yyyy HH:mm"; /// <summary> /// Handles file info given in the form of a string in standard unix ls output format. /// </summary> /// <param name="filesListing">The file listing string.</param> /// <returns>A list of FtpFileInfo objects</returns> public static List<FtpFileInfo> GetFilesListFromFtpListingUnix(String filesListing) { List<FtpFileInfo> files = new List<FtpFileInfo>(); MatchCollection matches = m_FtpListingRegex.Matches(filesListing); if (matches.Count == 0 && filesListing.Trim('\r','\n','\t',' ').Length != 0) return null; // parse error. Could throw some kind of exception here too. foreach (Match match in matches) { FtpFileInfo fileInfo = new FtpFileInfo(); Char dirchar = match.Groups[1].Value.ToLowerInvariant()[0]; fileInfo.IsDirectory = dirchar == 'd'; fileInfo.Permissions = match.Groups[2].Value.ToCharArray(); // No clue what "inodes" actually means... Int32 inodes; fileInfo.NrOfInodes = Int32.TryParse(match.Groups[3].Value, out inodes) ? inodes : 1; fileInfo.User = match.Groups[4].Success ? match.Groups[4].Value : null; fileInfo.Group = match.Groups[5].Success ? match.Groups[5].Value : null; Int64 fileSize; Int64.TryParse(match.Groups[6].Value, out fileSize); fileInfo.FileSize = fileSize; String month = match.Groups[7].Value; String day = match.Groups[8].Value.PadLeft(2, '0'); String year = match.Groups[9].Success ? match.Groups[9].Value : DateTime.Now.Year.ToString(CultureInfo.InvariantCulture); String time = match.Groups[10].Success ? match.Groups[10].Value.PadLeft(5, '0') : "00:00"; String timeString = month + " " + day + " " + year + " " + time; DateTime lastModifiedDate; if (!DateTime.TryParseExact(timeString, Timeformat, CultureInfo.InvariantCulture, DateTimeStyles.None, out lastModifiedDate)) lastModifiedDate = DateTime.MinValue; fileInfo.LastModifiedDate = lastModifiedDate; fileInfo.FileName = match.Groups[11].Value; files.Add(fileInfo); } return files; }
和填充的FtpFileInfo类:
public class FtpFileInfo { public Boolean IsDirectory { get; set; } public Char[] Permissions { get; set; } public Int32 NrOfInodes { get; set; } public String User { get; set; } public String Group { get; set; } public Int64 FileSize { get; set; } public DateTime LastModifiedDate { get; set; } public String FileName { get; set; } }
- 如何将Int转换为C#中的string而不使用ToString()?
- Moq +unit testing – System.Reflection.TargetParameterCountException:参数计数不匹配
- 链接时可以混合静态和共享对象库吗?
- 通过非const指针修改一个const
- macros中的代字符(〜)是什么意思?
- 我如何使一个combobox在.NET中不可编辑?
- 在ASP.NET Core中将Razor View渲染为string
- parsingC#中的SQL代码
- 控制台应用程序:每个configuration文件只允许有一个<configSections>元素,如果存在,则必须是根<configuration>元素的第一个子元素