直接上代码,现在用时大约在2分钟以上static void ParseTxt()
{
/*
* a.txt 数据
* 操作系统确定程序是否成功执行完毕
* 函数体函数定义的最后部分
* 程序编写完后需要进行编译
* 标准库定义了 4 个 IO 对象
* 系统将这些对象与执行程序的窗口联系起来
* 编译器要使用库
*
* b.txt 数据
* 讲解
* 函数部分
* 程序编译
* 标准库对象
* 系统窗口
* 编译器讲解
*
* 解析后新生成的newa.txt应该是这样的
* 操作系统确定程序是否成功执行完毕 【未找到】
* 函数体函数定义的最后部分 体函数定义的最后部分
* 程序编写完后需要进行编译 编写完后需要进行编译
* 标准库定义了 4 个 IO 对象 定义了 4 个 IO 对象
* 系统将这些对象与执行程序的窗口联系起来 将这些对象与执行程序的窗口联系起来
* 编译器要使用库 要使用库
*/
string aPath = "a.txt";//16W+数据
string bPath = "b.txt";//2000+数据
string newaPath = "newa.txt";//与a.txt数据量相同
string[] arrA = File.ReadAllLines(aPath);
string[] arrB = File.ReadAllLines(bPath);
StringBuilder sb = new StringBuilder();
bool isHave = false;
string titleTrim = string.Empty;
string subTitle = string.Empty;
char[] sChar = new char[] { ' ', '[', '[', '(', '『', '(', '{', '【' };
char[] eChar = new char[] { ' ', ']', '+', '/', '』', ']', ')', '-', '}', '】' };
foreach (string title in arrA)
{
titleTrim = title.TrimStart(sChar);
for (int i = 2; i < titleTrim.Length; i++)
{
isHave = false;
subTitle = titleTrim.Substring(0, i);
foreach (string b in arrB)
{
if (b.Contains(subTitle))
{
isHave = true;
break;
}
}
if (!isHave)
{
if (i == 2)
{
sb.Append(title + "\t【未找到】\r\n");
}
else
{
sb.Append(title + "\t" + titleTrim.Substring(i - 1, titleTrim.Length - i + 1).TrimStart(eChar) + "\r\n");
}
break;
}
}
}
File.WriteAllText(newaPath, sb.ToString());
}
{
/*
* a.txt 数据
* 操作系统确定程序是否成功执行完毕
* 函数体函数定义的最后部分
* 程序编写完后需要进行编译
* 标准库定义了 4 个 IO 对象
* 系统将这些对象与执行程序的窗口联系起来
* 编译器要使用库
*
* b.txt 数据
* 讲解
* 函数部分
* 程序编译
* 标准库对象
* 系统窗口
* 编译器讲解
*
* 解析后新生成的newa.txt应该是这样的
* 操作系统确定程序是否成功执行完毕 【未找到】
* 函数体函数定义的最后部分 体函数定义的最后部分
* 程序编写完后需要进行编译 编写完后需要进行编译
* 标准库定义了 4 个 IO 对象 定义了 4 个 IO 对象
* 系统将这些对象与执行程序的窗口联系起来 将这些对象与执行程序的窗口联系起来
* 编译器要使用库 要使用库
*/
string aPath = "a.txt";//16W+数据
string bPath = "b.txt";//2000+数据
string newaPath = "newa.txt";//与a.txt数据量相同
string[] arrA = File.ReadAllLines(aPath);
string[] arrB = File.ReadAllLines(bPath);
StringBuilder sb = new StringBuilder();
bool isHave = false;
string titleTrim = string.Empty;
string subTitle = string.Empty;
char[] sChar = new char[] { ' ', '[', '[', '(', '『', '(', '{', '【' };
char[] eChar = new char[] { ' ', ']', '+', '/', '』', ']', ')', '-', '}', '】' };
foreach (string title in arrA)
{
titleTrim = title.TrimStart(sChar);
for (int i = 2; i < titleTrim.Length; i++)
{
isHave = false;
subTitle = titleTrim.Substring(0, i);
foreach (string b in arrB)
{
if (b.Contains(subTitle))
{
isHave = true;
break;
}
}
if (!isHave)
{
if (i == 2)
{
sb.Append(title + "\t【未找到】\r\n");
}
else
{
sb.Append(title + "\t" + titleTrim.Substring(i - 1, titleTrim.Length - i + 1).TrimStart(eChar) + "\r\n");
}
break;
}
}
}
File.WriteAllText(newaPath, sb.ToString());
}
好像在循环内部,你考虑把它移到外部行不行,这个应该很占时间的,IO操纵很费时
多长时间?
Linq没试,不会Linq,.net2.0下
或者用C++是否会提高效率?
将数据量较大的txt分成多个操作。
subTitle = titleTrim.Substring(0, i);
foreach (string b in arrB)
{
if (b.Contains(subTitle))
{
isHave = true;
break;
}
}
这里最浪费时间,要优化
我想过把据量较大的txt分成10个,然后分10条线程操作,理论上会快10倍?
那样的话多线程要传参并且有返回值,不太好弄啊。
正则表达式不知道写合适,就想着怎么优化(好昵称都被占用了) 说的那段代码,我是这么优化的,就是把arrB换成了string b static void ParseTxt()
{
string aPath = "a.txt";//16W+数据
string bPath = "b.txt";//2000+数据
string newaPath = "newa.txt";//与a.txt数据量相同
string[] arrA = File.ReadAllLines(aPath);
string b = File.ReadAllText(bPath);
StringBuilder sb = new StringBuilder();
bool isHave = false;
string titleTrim = string.Empty;
string subTitle = string.Empty;
char[] sChar = new char[] { ' ', '[', '[', '(', '『', '(', '{', '【' };
char[] eChar = new char[] { ' ', ']', '+', '/', '』', ']', ')', '-', '}', '】' };
foreach (string title in arrA)
{
titleTrim = title.TrimStart(sChar);
for (int i = 2; i < titleTrim.Length; i++)
{
isHave = false;
subTitle = titleTrim.Substring(0, i);
if (b.Contains(subTitle))
{
isHave = true;
}
if (!isHave)
{
if (i == 2)
{
sb.Append(title + "\t【未找到】\r\n");
}
else
{
sb.Append(title + "\t" + titleTrim.Substring(i - 1, titleTrim.Length - i + 1).TrimStart(eChar) + "\r\n");
}
break;
}
}
}
File.WriteAllText(newaPath, sb.ToString());
}
string[] arrA = File.ReadAllLines(aPath);这个数据比较大(16W+),建立10个线程,
每一个线程读取16000的数据,每个线程里的arrB(2000)都是全部数据,
这样处理的话,初步估计在30秒内可以完成
你可以看一下notepad这个软件,开源的,
它打开8M左右的txt文件只要2秒左右,
用的是多线程,还有内存映射文件技术,
你用上了估计能减少到5秒以内
{
private delegate string FuncHandle(string[] arrA, string b);
//调用方法
public void ParseTxt()
{
string aPath = "a.txt";//16W+数据
string bPath = "b.txt";//2000+数据
string newaPath = "newa.txt";//与a.txt数据量相同
string[] arrA = File.ReadAllLines(aPath);
string b = File.ReadAllText(bPath);
int threadCount = 10;
string[][] a = SplitArray(arrA, threadCount);
StringBuilder sbb = new StringBuilder();
FuncHandle[] fhs = new FuncHandle[threadCount];
IAsyncResult[] ars = new IAsyncResult[threadCount];
for (int i = 0; i < threadCount; i++)
{
fhs[i] = new FuncHandle(this.ParseThreadMethod);
ars[i] = fhs[i].BeginInvoke(a[i], b, null, null);
}
for (int j = 0; j < threadCount; j++)
{
ars[j].AsyncWaitHandle.WaitOne();
sbb.Append(fhs[j].EndInvoke(ars[j]));
}
File.WriteAllText(newaPath, sbb.ToString());
}
//处理方法
private string ParseThreadMethod(string[] arrA, string b)
{
StringBuilder sb = new StringBuilder();
string subTitle = string.Empty;
bool isHave = false;
string titleTrim = string.Empty;
char[] sChar = new char[] { ' ', '[', '[', '(', '『', '(', '{', '【' };
char[] eChar = new char[] { ' ', ']', '+', '/', '』', ']', ')', '-', '}', '】' };
foreach (string title in arrA)
{
titleTrim = title.TrimStart(sChar); for (int i = 2; i < titleTrim.Length; i++)
{
isHave = false;
subTitle = titleTrim.Substring(0, i);
if (b.Contains(subTitle))
{
isHave = true;
}
if (!isHave)
{
if (i == 2)
{
sb.Append(title + "\t【未找到】\r\n");
}
else
{
sb.Append(title + "\t" + titleTrim.Substring(i - 1, titleTrim.Length - i + 1).TrimStart(eChar) + "\r\n");
}
break;
}
}
}
return sb.ToString();
}
//数组拆分
private string[][] SplitArray(string[] arr, int splitCount)
{
int arrLength = arr.Length;
int newArrLenth = arrLength / splitCount;
string[][] reArr = new string[splitCount][];
string[] tempArr;
int tempArrIndex = 0;
for (int j = 0; j < splitCount; j++)
{
tempArrIndex = 0;
if (j == splitCount - 1)
{
tempArr = new string[arrLength - newArrLenth * (splitCount - 1)];
}
else
{
tempArr = new string[newArrLenth];
}
for (int i = j * newArrLenth; i < arr.Length; i++)
{
tempArr[tempArrIndex] = arr[i];
if (j != splitCount - 1 && tempArrIndex == newArrLenth - 1)
break;
tempArrIndex++;
}
reArr[j] = tempArr;
}
return reArr;
}
}
string[] arrB = File.ReadAllLines(bPath);
不用数组,这个查找效率O(n),改为HashSet存储字符串值再查找比较,内部采用hash算法比较时间为O(1),改为这两个数据结构,应该会快蛮多。你测试看看
读盘速度 用不用多线程都一样的。。
先一次txt映射到内存在处理。。