初心者-C#ファイルリストを作成するためのディレクトリを介したC#反復
-
02-10-2019 - |
質問
最終目標は、TXTファイルに保存されるディレクトリの階層構造を保存する何らかの形のデータ構造を持つことです。
私は次のコードを使用しており、これまでのところ、監督、サブディール、ファイルの組み合わせに苦労しています。
/// <summary>
/// code based on http://msdn.microsoft.com/en-us/library/bb513869.aspx
/// </summary>
/// <param name="strFolder"></param>
public static void TraverseTree ( string strFolder )
{
// Data structure to hold names of subfolders to be
// examined for files.
Stack<string> dirs = new Stack<string>( 20 );
if ( !System.IO.Directory.Exists( strFolder ) )
{
throw new ArgumentException();
}
dirs.Push( strFolder );
while ( dirs.Count > 0 )
{
string currentDir = dirs.Pop();
string[] subDirs;
try
{
subDirs = System.IO.Directory.GetDirectories( currentDir );
}
catch ( UnauthorizedAccessException e )
{
MessageBox.Show( "Error: " + e.Message );
continue;
}
catch ( System.IO.DirectoryNotFoundException e )
{
MessageBox.Show( "Error: " + e.Message );
continue;
}
string[] files = null;
try
{
files = System.IO.Directory.GetFiles( currentDir );
}
catch ( UnauthorizedAccessException e )
{
MessageBox.Show( "Error: " + e.Message );
continue;
}
catch ( System.IO.DirectoryNotFoundException e )
{
MessageBox.Show( "Error: " + e.Message );
continue;
}
// Perform the required action on each file here.
// Modify this block to perform your required task.
/*
foreach ( string file in files )
{
try
{
// Perform whatever action is required in your scenario.
System.IO.FileInfo fi = new System.IO.FileInfo( file );
Console.WriteLine( "{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime );
}
catch ( System.IO.FileNotFoundException e )
{
// If file was deleted by a separate application
// or thread since the call to TraverseTree()
// then just continue.
MessageBox.Show( "Error: " + e.Message );
continue;
}
}
*/
// Push the subdirectories onto the stack for traversal.
// This could also be done before handing the files.
foreach ( string str in subDirs )
dirs.Push( str );
foreach ( string str in files )
MessageBox.Show( str );
}
解決 3
に基づいてコードを使用して動作しました http://weblogs.asp.net/israelio/archive/2004/06/23/162913.aspx
// How much deep to scan. (of course you can also pass it to the method)
const int HowDeepToScan=20;
public static void ProcessDir ( string dirName, int recursionLvl, string strFileName)
{
string tabs = new String( '-', recursionLvl );
if ( recursionLvl<=HowDeepToScan )
{
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles( dirName );
TextWriter tw = new StreamWriter( strFileName, true );
tw.WriteLine( tabs + "<a href=\" " + System.IO.Path.GetFullPath( dirName ) + "\">" + System.IO.Path.GetFileName( dirName ) + "</a><br />" );
foreach ( string fileName in fileEntries )
{
// do something with fileName
tw.WriteLine( tabs + "<a href=\" " + System.IO.Path.GetFullPath( fileName ) + "\">" + System.IO.Path.GetFileName( fileName ) + "</a><br />" );
}
tw.Close();
// Recurse into subdirectories of this directory.
string [] subdirEntries = Directory.GetDirectories( dirName );
foreach ( string subdir in subdirEntries )
// Do not iterate through reparse points
if ( ( File.GetAttributes( subdir ) &
FileAttributes.ReparsePoint ) !=
FileAttributes.ReparsePoint )
ProcessDir( subdir, recursionLvl+1, strFileName );
}
}
出力
<a href=" C:\code">code</a><br />
<a href=" C:\code\group.zip">FluentPath (1).zip</a><br />
<a href=" C:\code\index.html">index.html</a><br />
他のヒント
ある種の使用できます 複合パターン 複合アイテム - フォルダーです。
ターゲットフォルダーのツリー構造を構築するサンプルコードは次のとおりです。それは再帰的に機能し、もう少しメモリを消費しますが、シンプルさはそれだけの価値があります。
class TreeItem
{
public string FolderName;
public List<TreeItem> SubFolders = new List<TreeItem>();
public string[] Files;
}
class Program
{
private static TreeItem FileTree(string rootFolder){
var item = new TreeItem();
item.FolderName = rootFolder;
item.Files = System.IO.Directory.GetFiles(rootFolder);
foreach(var folder in System.IO.Directory.GetDirectories(rootFolder))
{
item.SubFolders.Add(FileTree(folder));
}
return item;
}
//Traversal algorithm
private static void PrintComposite(TreeItem node, int ident)
{
var dirName = System.IO.Path.GetFileName(node.FolderName);
Console.WriteLine(@"{0}{1}", new string('-', ident), dirName);
foreach(var subNode in node.SubFolders)
{
PrintComposite(subNode, ident + 1);
}
}
public static void Main(string[] args)
{
var tree = FileTree(@"D:\Games");
PrintComposite(tree,0);
}
}
一つには、より多くのオブジェクトを作成する必要があると思います。 DirectoryElementInterfaceインターフェイスまたは抽象クラスとディレクトリセレメントオブジェクト、およびDirectoryElementInterfaceを実装するファイルエレメントオブジェクト。今、ハイラキーを繰り返すためにスタックを使用するのではなく、作成する DirectoryElementInterface root = new DirectoryElement(nameOfNode)
. 。次に、getFilesのすべてのファイルに対して、ようなことをします root.addElement(new FileElement(filename));
. 。 AddElementは、ディレクトリセレメント内のリストに追加する必要があります。ディレクトリについても同様に行います。 OK、これで1つのレベルを作成できます。
今、反復ステップのために。あなたが書いただけで作るルーチンを取りなさい root
パラメーター。あなたはそれを何でも呼ぶことができますが、この議論のために、私はこの新しいルーチンaddirectoryInformationと呼びます。あなたのメインは、ルートを通過するルートと呼び出しのaddirectoryInformationの作成になります。反復するには、要素のリストについてrootに記入されたルートを尋ねる必要があります。リストを介してforeachを実行し、ディレクトリである各要素のaddDirectoryInformationを呼び出します。その動作をしたら、ループをaddDirectoryInformationの終わりに移動します。これで、すべてのディレクトリを追加して、すべての子供を再帰的に追加します。
適切な再帰プログラムのもう1つのこと。再発を停止するタイミングを知る必要があります。この場合、それは簡単です。リストにディレクトリがない場合、AddDirectoryInformationは呼び出されません。だからあなたは終わった。
私は先週、私たちが同様のことをしたコースを行いました。出力はコンソールでしたが、それを.txtファイルにストリーミングすることができない理由はありません。
システムの使用。 System.collections.genericを使用しています。 System.linqを使用しています。 System.textを使用しています。
namespace showdirectory {class program {static void main(string [] args){console.writeline( "このプログラムは、ディレクトリ内のすべてのファイルをリストします。"); System.io.directoryInfo dir = new System.io.directoryInfo(@"c:"); foreach(system.io.fileinfoファイルdir.getfiles( ".")){console.writeline(" {0}、{1} "、file.name、file.length);} console.readline();}}}}
アプローチの1つは、このようなファイルツリーでイテレーターを使用することです。
// IncludeExcludeFileEnumerator(string baseDir, string includePattern, string excludePattern)
// Include pattern can include ** that means tree hierarchy
var myFiles = new IncludeExcludeFileEnumerable(@"C:\test\aaa", @"**.bmp,*.jpg", "*excl_bad*.*,*fu*");
foreach (var s in myFiles)
{
Console.Out.WriteLine(s);
}
ファイルIteratorのコード(IENUMERATOR、IENUMERABLE):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace IncludeExcludeFileEnumerator
{
public class IncludeExcludeFileEnumerator : IEnumerator<String>
{
private string excludeRegExPattern;
private readonly Regex regexSeparateFilePath;
private readonly Regex excludeRegex = null;
private int currentPatternIndex;
private IEnumerator<string> filesEnum;
private IEnumerable<string> files;
bool isNext = true;
private readonly List<Tuple<string, string, SearchOption>> incPatternsList;
public IncludeExcludeFileEnumerator(string baseDirectory, string includePattern, string excludePattern)
{
// Split comma separated string to array of include patterns
var initIncludePatterns = includePattern.Split(',');
regexSeparateFilePath = new Regex(@"(.*)[\\/]([^\\/]*$)", RegexOptions.Compiled);
// Prepare include patterns
incPatternsList = initIncludePatterns.ToList().ConvertAll(
(incPattern) =>
{
incPattern = incPattern.Trim();
var matches = regexSeparateFilePath.Matches(incPattern);
string pathPattern;
string filePattern;
if (matches.Count == 0)
{
pathPattern = "";
filePattern = incPattern;
}
else
{
pathPattern = matches[0].Groups[1].Value;
filePattern = matches[0].Groups[2].Value;
}
SearchOption searchOption = SearchOption.TopDirectoryOnly;
if (filePattern.Contains("**"))
{
filePattern = filePattern.Replace("**", "*");
searchOption = SearchOption.AllDirectories;
}
var fullPathPattern = Path.Combine(baseDirectory, pathPattern);
// Returns tuple {PathPattern, FilePattern, SearchOption}
return new Tuple<string, string, SearchOption>(fullPathPattern, filePattern, searchOption);
});
// Prepare regular expression for exclude case (all in one, concatinated by (| - or) separator)
if (!String.IsNullOrWhiteSpace(excludePattern))
{
var excPatterns = excludePattern.Replace(".", @"\.");
excPatterns = excPatterns.Replace("*", ".*");
excludeRegExPattern = excPatterns.Replace(",", "|");
excludeRegex = new Regex(excludeRegExPattern, RegexOptions.Compiled);
}
Reset();
}
public string Current
{
get { return filesEnum.Current; }
}
public void Dispose()
{
}
object System.Collections.IEnumerator.Current
{
get { return (Object)this.Current; }
}
public bool MoveNext()
{
do
{
if (( filesEnum == null ) && (incPatternsList.Count < currentPatternIndex + 2))
{
return false;
}
if ((filesEnum == null) || (isNext == false))
{
var tuple = incPatternsList[++currentPatternIndex];
files = Directory.EnumerateFiles(tuple.Item1, tuple.Item2, tuple.Item3);
filesEnum = files.GetEnumerator();
isNext = true;
}
while (isNext)
{
isNext = filesEnum.MoveNext();
if (isNext)
{
if (excludeRegex==null) return true;
if (!excludeRegex.Match(filesEnum.Current).Success) return true;
// else continue;
}
else
{
filesEnum = null;
}
}
} while (true);
}
public void Reset()
{
currentPatternIndex = -1;
filesEnum = null;
}
}
public class IncludeExcludeFileEnumerable : IEnumerable<string>
{
private string baseDirectory;
private string includePattern;
private string excludePattern;
public IncludeExcludeFileEnumerable(string baseDirectory, string includePattern, string excludePattern)
{
this.baseDirectory = baseDirectory;
this.includePattern = includePattern;
this.excludePattern = excludePattern;
}
public IEnumerator<string> GetEnumerator()
{
return new IncludeExcludeFileEnumerator(baseDirectory, includePattern, excludePattern);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return (IEnumerator)this.GetEnumerator();
}
}
}