2011-07-22 9 views
0

ファイル名とその同等のハッシュコードをXMLから読み込むアプリケーションがあります(同じアプリケーションを使用してXMLを作成した後) 1つのXML(ファイルとそのハッシュコード)を別のXMLに変換します(おそらく異なるファイルとハッシュコードを使用します)。私は2つのXMLの間で最初にファイル名を比較し、ファイルが両方のXMLに存在する場合、ハッシュコードを比較できるように、比較関数を作成しようとしています。C#複数の配列を比較のために複数の配列に格納する

(基本的に達成しようとしていることを理解するのに役立つように、2つのリストボックスがxmlごとに1つずつあります。同じファイルでも内容は異なるか、またはそのファイルが他のXMLには存在しないかどうかに応じて色を変えてマークする)。

ファイル名を保存する方法を見つけるのが難しいおよびそのハッシュコード。

コードは(私は私が仕事の一部を行うために作成したC++ DLLを使用しています):

private String[] ProjOne() 
     { 
      //Intialize the functions in the DLL 
      DllTest.Funtions Functions = new DllTest.Funtions(); 

      //Set the location where the XMLs can be found 
      String Directory = "C:\\Users\\brandonm\\Desktop\\Backup\\XML\\"; 

      //Get and set the number of items in the directory 
      int NumFiles = Functions.GetNumFiles(Directory); 

      //Create a search string to be used to determine the fullpath name of the file 
      //selected from the combobox 
      String SelectedFile = comboBox1.SelectedItem.ToString(); 
      String SearchString = "*" + SelectedFile + "*.XML"; 

      //Get and set the TC that will be used to get the filenames and hashcodes 
      int SelectedTC = int.Parse(comboBox2.SelectedItem.ToString()); 

      //Get and set an array containing a full path structure to the item selected from 
      //the combobox using the search string created earlier. Get files returns an array 
      //thus needs to be stored in an array 
      String[] FullPaths = new String[NumFiles]; 
      FullPaths = System.IO.Directory.GetFiles("C:\\Users\\brandonm\\Desktop\\Backup\\XML", SearchString, System.IO.SearchOption.AllDirectories); 
      int number = FullPaths.GetLength(0); 

      // The number of items in the XML ie. Number of Filenames in a particular TC 
      int NumXMLItems = NumXMLItemsListOne(); 

      // Initialize the array that will hold the Filenames and their equivalent Hashcodes 
      String[] FileNames = new String[NumXMLItems]; 
      String[] HashCode = new String[NumXMLItems]; 
      String[,] ProjectOne = new String[HashCode.Length, HashCode.Length]; 

      //Itteration through the all the XMLs in the location to add the current items into their arrays 
      for (int x = 0; x < NumFiles; x++) 
      { 
       String FullPath = FullPaths[x]; 

       XPathNavigator Root = new XPathDocument(FullPath).CreateNavigator(); 

       foreach (XPathNavigator Cycle in Root.Select(String.Format(@"//TestCycle[@Number = '{0}']", SelectedTC))) 
       { 
        foreach (XPathNavigator Nav in Cycle.Select(@"Files/FileName/@File")) 
        { 
         int y = 0; 
         FileNames[y] = Nav.Value; 
         y = y + 1; 
        } 
        foreach (XPathNavigator Nav in Cycle.Select(@"Files/HashCode/@Code")) 
        { 
         int z = 0; 
         HashCode[z] = Nav.Value; 
         z = z + 1; 
        } 
       } 
      } 
      return FileNames; 
     } 

XML:私は現在、とても1以上のものと同一の別の機能を持っている

<?xml version="1.0" encoding="utf-8"?> 
<Projects> 
    <Project Name="tfasdtyf"> 
    <TestCycle Number="2387468"> 
     <Files> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" /> 
     <HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" /> 
     <HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" /> 
     <HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" /> 
     </Files> 
    </TestCycle> 
    </Project> 
    <Project Name="tfasdtyf"> 
    <TestCycle Number="23423"> 
     <Files> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" /> 
     <HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" /> 
     <HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" /> 
     <HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" /> 
     </Files> 
    </TestCycle> 
    </Project> 
    <Project Name="tfasdtyf"> 
    <TestCycle Number="1112"> 
     <Files> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" /> 
     <HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" /> 
     <HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" /> 
     <HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" /> 
     </Files> 
    </TestCycle> 
    </Project> 
    <Project Name="tfasdtyf"> 
    <TestCycle Number="999"> 
     <Files> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" /> 
     <HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" /> 
     <HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" /> 
     <HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" /> 
     </Files> 
    </TestCycle> 
    </Project> 
    <Project Name="tfasdtyf"> 
    <TestCycle Number="34534"> 
     <Files> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" /> 
     <HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" /> 
     <HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" /> 
     <FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" /> 
     <HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" /> 
     </Files> 
    </TestCycle> 
    </Project> 
    <Project Name="Music"> 
    <TestCycle Number="12312"> 
     <Files> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Shut Ya Mouth.mp3" /> 
     <HashCode Code="3E-92-80-93-D5-64-19-16-26-8D-39-2A-C7-0B-C8-EB" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Snake Eater.mp3" /> 
     <HashCode Code="8B-DF-19-AE-87-52-64-2E-85-CF-57-4B-85-4D-CC-E9" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Stuck in the System.mp3" /> 
     <HashCode Code="6A-30-A7-53-FF-29-A5-DF-6D-24-DF-41-74-EE-06-4D" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 Martin Solveig - Hello (Featuring Dragonette).mp3" /> 
     <HashCode Code="93-90-A3-9C-BE-81-63-03-D7-96-1F-72-E4-ED-2D-32" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 Stimming - Funkworm.mp3" /> 
     <HashCode Code="8F-E1-7A-F1-B7-80-C6-2F-DC-34-FD-82-A0-DA-35-5E" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\1. Downlink - Ignition.mp3" /> 
     <HashCode Code="3D-89-B3-C2-73-A6-A0-85-02-C0-B4-F9-C8-09-14-C7" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02 B1 Psychedelic Runway.mp3" /> 
     <HashCode Code="00-72-5C-CE-25-73-98-31-69-71-68-48-31-A1-A3-5A" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02 B1 Rapture.mp3" /> 
     <HashCode Code="1E-A6-53-07-10-FD-A3-4C-EF-D6-92-7F-CE-97-88-6E" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02_Digital-Controller.mp3" /> 
     <HashCode Code="94-E0-CA-5F-2B-D2-56-7B-AF-2E-04-50-58-38-4D-B4" /> 
     <FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\2. Downlink - Gamma Ray.mp3" /> 
     <HashCode Code="3C-7A-76-AD-A6-2C-D1-7E-61-24-C0-40-BD-A7-A9-41" /> 
     </Files> 
    </TestCycle> 
    </Project> 
</Projects> 

各リストボックスの唯一の違いは、ファイルとテストサイクル番号で、XMLのどこでファイルとハッシュコードを取得するかを決定します。それらは4つの別々の配列、関数ごとに2つの配列に格納されます。しかし明らかに私の関数は2つの配列を返すことができないので、現在はその配列を返すだけです。

2次元配列は私をたくさん混乱させ、どうすれば私が必要とする情報が得られるか分かりません。誰かが私にこれを行うより良い方法を指示できますか?

実際に、ファイル名の各セットと、その後の各ハッシュコードセットについて、上記のような4つの関数を作成したくありません。しかし、私はまだ初心者ですので多分それは私の最高の選択肢ですか?

答えて

1

の機能を複製しない方が良いでしょう。ここではすべてのケースで使用できる単一の関数を作成したいと考えています。

.NETには、ファイル名とハッシュコードを格納するために、使用できるコレクションクラスがたくさんあります。たとえば、次のようなDictionary<string, string>を使用することができます。

 Dictionary<string, string> dictionary = new Dictionary<string, string>(); 

     for (int i = 0; i < NumFiles; i++) 
     { 
      dictionary.Add(FileNames[i], HashCode[i]); 
     } 

上記のコードは、あなたが提供する機能であなたのreturn文の前に右置くことができます。その後、辞書を返します。もちろん、関数を辞書に直接格納することで関数全体を短くすることもできますが、決めることはできます。

ここで、この関数が呼び出された場所であれば、この辞書をループする必要があります。これを行う方法は次のとおりです。

 foreach (var pair in dictionary) 
     { 
      string filename = pair.Key; 
      string hashcode = pair.Value; 

      // Do whatever you want with them here 
     } 

疑問に思っていることはほかにありません。あなたの全体的な目標が何であるかは完全にはわかりません。 List<T>など、他の一般的なコレクションも試してみる必要があります。

+0

ありがとうございました。私のアプリケーションでは、ファイルが変更されたか変更されたかどうかを確認するために、2つのファイルのハッシュコードを比較することによってこれを行います。私はテスターですので、テストサイクルごとにリリースされたファイルがリリースされる可能性がありますが、バックグラウンドの変更があったか、ベースラインがTC間で変更されている可能性があります。ファイルが同じであれば比較はファイル名の間でなければなりません。ハッシュコードをチェックし、ファイルが同じ場合は緑色に、オレンジ色の新しいファイルならば赤色に、ファイルが存在する場合は赤色に、ハッシュは異なります。私はこれを試して、それが私を助けた場合のフィードバックを与えます:) – Brandonm

1

HashCodeがファイルに属している場合、それはなぜそれのサブ要素/属性ではありませんか?解析するのが簡単になります。

ファイルを作成するので、私は同じような構造を作成したい:その後、いくつかのXElementの魔法で、あなたが使用することができ

<Project Name="tfasdtyf"> 
    <TestCycle Number="23423"> 
     <Files> 
     <File Name="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" HashCode="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" /> 
     <File Name="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" HashCode="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" /> 
     <File Name="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" HashCode="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" /> 
     </Files> 
    </TestCycle> 
</Project> 

public class Project 
{ 
    XElement self; 
    public Project(XElement project) 
    { 
     self = project; 
    } 

    public TestCycle TestCycle 
    { 
     get 
     { 
      // If there are more than one TestCycle per project, you may end 
      // up creating something similar to TestCycle.Files (see TestCycle class below) 

      XElement testCycle = self.Element("TestCycle"); 
      if(null == testCycle) 
       self.Add(testCycle = new XElement("TestCycle")); 
      return new TestCycle(testCycle); 
     } 
    } 

    public string Name 
    { 
     get { return return self.GetString("Name", string.Empty, ATTRIBUTE); } 
     set { self.Set("Name", value, ATTRIBUTE); } // see Set Extension method below 
    } 

    public static IEnumerable<Project> Load(string filename) 
    { 
     return XElement.Load(filename)).Elements("Project").Select(xp => new Project(xp)); 
    } 
} 

public class TestCycle 
{ 
    XElement self; 
    public TestCycle(XElement testCycle) 
    { 
     self = testCycle; 
    } 

    private XElement XFiles 
    { 
     get 
     { 
      XElement files = self.Element("Files"); 
      if(null == files) 
       self.Add(files = new XElement("Files")); 
      return files; 
     } 
    } 

    public IEnumerable<FileHash> Files 
    { 
     get 
     { 
      return XFiles.Elements("File").Select(xf => new FileHash(xf)); 
     } 
    } 

    public int Number 
    { 
     get { return self.GetInt("Number", 0, ATTRIBUTE); } 
     set { self.Set("Number", value, ATTRIBUTE); } // see Set Extension method below 
    } 

    public FileHash AddFile(string name, string hashCode) 
    { 
     FileHash file = Files.FirstOrDefault(xf => xf.Name == name); 
     if(null != file) 
      file.self.Remove(); // replacing (but could throw an exception saying already exists instead) 
     XElement xFile = new XElement("File"); 
     self.Add(xFile); 
     file = new FileHash(xFile) 
     { 
      Name = name, 
      HashCode = hashCode 
     }; 
     return file; 
    } 
} 

public class FileHash 
{ 
    internal XElement self; 
    public FileHash(XElement fileHash) 
    { 
     self = fileHash; 
    } 

    public string Name 
    { 
     get { return self.GetString("Name", string.Empty, ATTRIBUTE); } 
     set { self.Set("Name", value, ATTRIBUTE); } // see Set Extension method below 
    } 

    public string HashCode 
    {     
     get { return return self.GetString("HashCode", string.Empty, ATTRIBUTE); } 
     set { self.Set("HashCode", value, ATTRIBUTE); } // see Set Extension method below 
    } 
} 

拡張メソッド:

public static XElementExtensions 
{ 
    public const bool ATTRIBUTE = true; 
    public const bool ELEMENT = false; 
    public const bool? BOTH = null; 

public void Set(this XElement self, string name, object value, bool isAttribute) 
{ 
    string sValue = value.ToString(); 
    XElement eValue = self.Element(name); 
    XAttribute aValue = self.Attribute(name); 
    if(null != eValue) 
     eValue.ReplaceWith(new XElement(name, sValue)); 
    else if(null != aValue) 
     aValue.ReplaceWith(new XAttribute(name, sValue)); 
    else if(isAttribute) 
     self.Add(new XAttribute(name, sValue)); 
    else 
     self.Add(new XElement(name, sValue)); 
} 

public string GetString(this XElement self, string name, string @default, bool? isAttribute) 
{ 
    XAttribute aValue = self.Attribute(name); 
    XElement eValue = self.Element(name); 
    if(null == isAttribute) // try both 
    { 
     if(null != aValue) return (string)aValue; 
     if(null != eValue) return (string)eValue; 
     return @default; 
    } 
    if(isAttribute && null != aValue) 
     return (string)aValue; 
    if(!isAttribute && null != eValue) 
     return (string)eValue); 
    return @default; 
} 

public int GetInt(this XElement self, string name, int @default, bool? isAttribute) 
{ 
    return Convert 
     .ToInt32(GetString(self, name, null, isAttribute) ?? @default.ToString()); 
} 

} 

次に、次のようなコードを使用できます。

つのXMLファイルを比較する
Project[] projects = Project.Load(filename).ToArray(); 

foreach(Project project in projects) 
{ 
    Console.WriteLine("Project: " + project.Name); 
    Console.WriteLine("TestCycle: " + project.TestCycle.Number.ToString()); 
    Console.WriteLine("Files:"); 
    foreach(FileHash file in project.TestCycle.Files) 
     Console.WriteLine(string.Format(" Name: {0}, HashCode: {1}", file.Name, file.HashCode)); 
} 

またはあなたのアプリケーションのために、:

var fileA = Project.Load(fileAname); 
var fileB = Project.Load(fileBname); 

私はあなたが意味するかはかなりわからないんだけど、すべてのファイルが、私はそれをしようとします。

これらの拡張メソッドを使用して
File[] filesA = fileA.SelectMany(project => project.TestCycle.Files).ToArray(); 
File[] filesB = fileB.SelectMany(project => project.TestCycle.Files).ToArray(); 

public static IEnumerable<TSource> Except<TSource> 
(
    this IEnumerable<TSource> first, 
    IEnumerable<TSource> second, 
    Func<TSource, TSource, bool> comparer 
) 
{ 
    return first.Except(second, new LambdaComparer<TSource>(comparer)); 
} 

public static IEnumerable<TSource> Intersect<TSource> 
(
    this IEnumerable<TSource> first, 
    IEnumerable<TSource> second, 
    Func<TSource, TSource, bool> comparer 
) 
{ 
    return first.Intersect(second, new LambdaComparer<TSource>(comparer)); 
} 

そしてLambdaComparerクラス:

public class LambdaComparer<T> : IEqualityComparer<T> 
{ 
    private readonly Func<T, T, bool> equals; 
    private readonly Func<T, int> getHashCode; 

    public LambdaComparer(Func<T, T, bool> lambdaComparer) : 
     this(lambdaComparer, o => o.GetHashCode()) 
    { 
    } 

    public LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash) 
    { 
     if (lambdaComparer == null) 
      throw new ArgumentNullException("lambdaComparer"); 
     if (lambdaHash == null) 
      throw new ArgumentNullException("lambdaHash"); 

     equals = lambdaComparer; 

     getHashCode = lambdaHash; 
    } 

    public bool Equals(T x, T y) 
    { 
     return equals(x, y); 
    } 

    public int GetHashCode(T obj) 
    { 
     return getHashCode(obj); 
    } 
} 

File[] filesInA_butNotInB = filesA.Except(filesB, (a,b) => a.Name == b.Name).ToArray(); 
File[] filesInBoth = filesA.Intersect(filesB, (a,b) => a.Name == b.Name).ToArray(); 
File[] filesInBoth_butDifferentHash = FilesA.Intersect(filesB, (a,b) => a.Name == b.Name && a.HashCode != b.HashCode).ToArray(); 

"あなたが始める" 必要があります...

PS:Iコンパイラを介さずに手作業で書いていますので、プロがありますコンパイラがキャッチするいくつかのタイプミス。

PS:.ToArray()'sは、File[]IEnumerable<File>よりも読みやすくなっているからです。読むのは簡単ですが、どちらかといえば同じタイプの入力です。

PSS:これが便利だと思います。私は物事を処理するXML Linqの方法を愛しているので、funこれを書いていました。

+0

あなたの答えのチャックに感謝:)これは私のレベルをはるかに超えているが、病気はあなたが前にラムダを見たことがないので、それは私の問題の多くを解決するかもしれませんが、私はそれを試してみましょう。 – Brandonm

+0

また、私はそれが可能であることを知っていなかったサブ要素/属性に対するコメントをありがとう。しかし、私はそれが制限されるかもしれませんが、私はXMLを作成するためにC++/CLIのXMLDocumentを使用していますし、次にDLLを介して関数を呼び出しています。私は既にそれをコード化していたので、私はC# – Brandonm

関連する問題