C# 字符串是否存在检查20k次
我有一个ITunes库XML文件备份文件-大约15MB 我的C盘上有20K个音乐文件,E盘上有25K个文件,文件夹结构完全相同 我正在遍历第一个位置,逐个文件,并检查文件是否存在于第二个位置。那部分对我有用 现在,对于所有这些重复文件,如果XML中存在E驱动器的文件路径,但XML中不存在C驱动器路径,那么我想从C驱动器中删除该文件C# 字符串是否存在检查20k次,c#,string,search,C#,String,Search,我有一个ITunes库XML文件备份文件-大约15MB 我的C盘上有20K个音乐文件,E盘上有25K个文件,文件夹结构完全相同 我正在遍历第一个位置,逐个文件,并检查文件是否存在于第二个位置。那部分对我有用 现在,对于所有这些重复文件,如果XML中存在E驱动器的文件路径,但XML中不存在C驱动器路径,那么我想从C驱动器中删除该文件 检查XML文件中是否存在字符串的最佳方法是什么(我必须至少执行20K次)?根据您是否要计算字符串出现的次数,或者如果您只是检查字符串是否存在,您的方法会略有不同。但是
检查XML文件中是否存在字符串的最佳方法是什么(我必须至少执行20K次)?根据您是否要计算字符串出现的次数,或者如果您只是检查字符串是否存在,您的方法会略有不同。但是,这是我要考虑的两种方式: 如果您想用最少的内存执行此操作: 逐行加载文件(或者,如果XML不是这样格式化的,则使用XML解析器逐节点加载文件……我相信有XML解析器可以做到这一点)。对每个字符串的行执行搜索操作。如果正确覆盖最后一行,内存中一次最多只能有一行/节点。这样做的缺点是需要更长的时间,文件打开的时间也更长 如果您想快速完成: 将整个文件加载到内存中,不必解析它,只需搜索每个字符串 编辑
根据您的说明,我将首先收集数组中所有重复的文件名,然后使用我的第一个方法(如上)继续扫描XML文件的每一行。如果您已经在内存中存储了20K文件名,我会犹豫是否同时加载整个15MB XML。建议:加载为文本,使用正则表达式提取所需字符串(我认为它们包含一个特定的标记),并用它们构建一个哈希列表。您可以使用列表来检查是否存在。按字母顺序对您要匹配的字符串列表进行排序,然后构建一个索引数组,告诉您每个字符串的起始字符列表的起始位置,可能索引到第二个字符,这取决于种类的广度以及匹配是否区分大小写 使用流逐个字符读取文件以最小化内存占用,检查索引数组以查看该字符在字符串列表中的起始位置和结束位置,以便您可以拉出该字符页(如果有任何以这些字符组合开头的内容)。然后继续在页面内部进行筛选,直到剩下一个匹配项,而下一个字符将匹配项设置为0 从要匹配的字符串列表中删除该字符串,如果需要,将其放入另一个列表中。然后开始检查下一个字符的索引,并在每次没有匹配时继续这样做 该索引为您提供了一个更有效的聚合,以最小化对其进行迭代的项数 这可以为您提供两个字符的深度索引:
Dictionary<string,int> stringIndex = new Dictionary<char,int>();
for(int i = 0; i < sortedSearchStrings.Length; i++;)
{
if (!stringIndex.Keys.Contains(sortedSearchStrings[i][0])) stringIndex[sortedSearchStrings[i][0]] = i;
if (!stringIndex.Keys.Contains(sortedSearchStrings[i][0] + sortedSearchStrings[i][1])) stringIndex[sortedSearchStrings[i][0] + sortedSearchStrings[i][1]] = i;
}
从XML中读取每个字符串,并将它们写入
哈希集
。如果要查找字符串,请在哈希集中查找它。读取XML的成本是O(n),对哈希集进行n次查找的成本是O(n)。不要尝试在XML中重复搜索(而是在哈希集中进行20000次搜索),因为XML没有索引/优化以进行搜索。是否可以直接从XML文档中搜索并跳过第一步
如果是这样,您可以使用Xml.XmlDocument,然后使用Xml.XmlNode.SelectNodes(字符串),使用xpath导航文档。我不知道文档中存在什么类型的信息,但您对第二阶段的措辞方式表明,有时C:\上的路径和E:\上的路径都存在?如果是这样的话,只需检查两个IO.File.Exists,然后检查一个IO.File.Delete()
我的意思是,与其在XML文档中搜索N次字符串,不如在文档中搜索并删除重复项,以便只在文档中运行一次
不过,我不使用iTunes,也没有现成的库备份来判断它是否可以工作。这里有一个使用Linq的简单解决方案。运行速度足够快,可一次性使用:
using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
class ITunesChecker
{
static void Main(string[] args)
{
// retrieve file names
string baseFolder = @"E:\My Music\";
string[] filesM4a = Directory.GetFiles(baseFolder, "*.m4a", SearchOption.AllDirectories);
string[] filesMp3 = Directory.GetFiles(baseFolder, "*.mp3", SearchOption.AllDirectories);
string[] files = new string[filesM4a.Length + filesMp3.Length];
Array.Copy(filesM4a, 0, files, 0, filesM4a.Length);
Array.Copy(filesMp3, 0, files, filesM4a.Length, filesMp3.Length);
// convert to the format used by iTunes
for (int i = 0; i < files.Length; i++)
{
Uri uri = null;
if (Uri.TryCreate(files[i], UriKind.Absolute, out uri))
{
files[i] = uri.AbsoluteUri.Replace("file:///", "file://localhost/");
}
}
// read the files from iTunes library.xml
XDocument library = XDocument.Load(@"E:\My Music\iTunes\iTunes Music Library.xml");
var q = from node in library.Document.Descendants("string")
where node.ElementsBeforeSelf("key").Where(n => n.Parent == node.Parent).Last().Value == "Location"
select node.Value;
// do the set operations you are interested in
var missingInLibrary = files.Except(q, StringComparer.InvariantCultureIgnoreCase);
var missingInFileSystem = q.Except(files, StringComparer.InvariantCultureIgnoreCase);
var presentInBoth = files.Intersect(q, StringComparer.InvariantCultureIgnoreCase);
}
}
使用系统;
使用System.IO;
使用System.Linq;
使用System.Xml.Linq;
类ITunesChecker
{
静态void Main(字符串[]参数)
{
//检索文件名
string baseFolder=@“E:\My Music\”;
字符串[]filesM4a=Directory.GetFiles(baseFolder,*.m4a),SearchOption.AllDirectories);
字符串[]filesm3=Directory.GetFiles(baseFolder,*.mp3),SearchOption.AllDirectories);
string[]files=新字符串[filesM4a.Length+filesm3.Length];
复制(filesM4a,0,files,0,filesM4a.Length);
复制(filesm3,0,files,filesM4a.Length,filesm3.Length);
//转换为iTunes使用的格式
for(int i=0;in.Parent==node.Parent.Last().Value==Location”
选择节点值;
//进行您感兴趣的集合操作
var missingInLibrary=files.Except(q,StringComparer.InvariantCultureInogoreCase);
var missingInFileSystem=q.Except(文件,StringComparer.InvariantCultureI
using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
class ITunesChecker
{
static void Main(string[] args)
{
// retrieve file names
string baseFolder = @"E:\My Music\";
string[] filesM4a = Directory.GetFiles(baseFolder, "*.m4a", SearchOption.AllDirectories);
string[] filesMp3 = Directory.GetFiles(baseFolder, "*.mp3", SearchOption.AllDirectories);
string[] files = new string[filesM4a.Length + filesMp3.Length];
Array.Copy(filesM4a, 0, files, 0, filesM4a.Length);
Array.Copy(filesMp3, 0, files, filesM4a.Length, filesMp3.Length);
// convert to the format used by iTunes
for (int i = 0; i < files.Length; i++)
{
Uri uri = null;
if (Uri.TryCreate(files[i], UriKind.Absolute, out uri))
{
files[i] = uri.AbsoluteUri.Replace("file:///", "file://localhost/");
}
}
// read the files from iTunes library.xml
XDocument library = XDocument.Load(@"E:\My Music\iTunes\iTunes Music Library.xml");
var q = from node in library.Document.Descendants("string")
where node.ElementsBeforeSelf("key").Where(n => n.Parent == node.Parent).Last().Value == "Location"
select node.Value;
// do the set operations you are interested in
var missingInLibrary = files.Except(q, StringComparer.InvariantCultureIgnoreCase);
var missingInFileSystem = q.Except(files, StringComparer.InvariantCultureIgnoreCase);
var presentInBoth = files.Intersect(q, StringComparer.InvariantCultureIgnoreCase);
}
}