/*
多线程索引
*/
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<process.h>
#include<Windows.h>
#define LINE 13180806
//获取文件有多少行
int getLine(char *path)
{
printf("开始统计文件行数.....\n");
int sum = 0;
FILE *pfr = fopen(path, "rb");
if (pfr == NULL)
{
printf("文件打开失败!\n");
return -1;
}
while (!feof(pfr))
{
char str[1024] = { 0 };
fgets(str, 1024, pfr);
sum++;
}
fclose(pfr);
printf("文件行数统计结束。\n");
return sum;
}
//索引结构体
struct indexinfo
{
int *pindex; //计录每行的首地址,做索引用
int length; //计录文件行数
}allindex;
//索引初始化
void init(char *path, char *indexpath)
{
//要使用 rb 因为 \n 写到文件中会转换成 \r\n 占二个字节,而 \r读时只占一个字节,这样会有误差
FILE *pfr = fopen(path, "rb");
FILE *pfw = fopen(indexpath, "wb");
printf("内存空间分配...\n");
allindex.pindex = calloc(LINE,sizeof(int));
printf("内存空间分配结束。\n");
int alllength = 0; //记录每行的长度
int i = 0;
if (pfr == NULL||pfw ==NULL)
{
printf("文件打开失败!\n");
return;
}
while (!feof(pfr))
{
char str[1024] = { 0 };
fgets(str, 1024, pfr);
alllength += strlen(str);
i++;
}
fclose(pfr);
//把索引写入到文件
printf("开始写入索引...\n");
fwrite(allindex.pindex, sizeof(int), LINE, pfw);
fclose(pfw);
printf("索引写入结束.\n");
}
//快速索引查询,即把索引文件加载到内存中进行查询
void quickindex(char *indexpath)
{
//先他配内存空间给索引结构体
allindex.pindex = calloc(LINE, sizeof(int));
FILE *pfr = fopen(indexpath, "rb");
fread(allindex.pindex, sizeof(int), LINE, pfr);
fclose(pfr);
}
char *path = "e:\\dd.txt";
char *indexpath = "e:\\indxedd.txt";
//这是生成索引文件,下面可以测试按排查询。
void main1()
{
//getLineString(path);
//printf("%d\n", getLine(path)); //得到行数.要注意的是这儿使用的是 rb 进行的读取。
//init(path, indexpath); //初始索引,并把索引写进文件中。
//下面是把索引加载到内存,然后输入行数,即可查出相应行的数据。
quickindex(indexpath); //把索引文件加载到内存这样查询速度更快。
FILE *pfr = fopen(path, "rb");
while (1)
{
int num = 0;
printf("输入要查询的行数:");
scanf("%d", &num);
char info[256] = { 0 };
fseek(pfr, allindex.pindex[num], SEEK_SET);
fgets(info, 256, pfr);
printf("%s\n", info);
}
fclose(pfr);
system("pause");
}
//多线程结构所需要的信息
struct threadinfo
{
int *start; //线程开始查询的地址
int length; //线程查询的长度
char findstr[20]; //要查询的字符串
int id; //线程编号
};
void runthread(void *p)
{
struct threadinfo *pinfo = p;
FILE *pfr = fopen(path, "rb");
for (int i = 0; i < pinfo->length;i++)
{
int tempnum = pinfo->start[i]; //获取行的首地址(即离文件指针的距离)
fseek(pfr, tempnum, SEEK_SET);
char str[256] = { 0 };
fgets(str, 256, pfr);
char *px = strstr(str, pinfo->findstr);
if (px)
{
printf("\n线程:%d 查询到信息:\n%s", pinfo->id, str);
}
}
printf("\n线程:%d查询结束。\n", pinfo->id);
fclose(pfr);
}
void main()
{
#define T 10 //分成多少个线程
quickindex(indexpath); //把索引文件载入到内存
struct threadinfo thread[T]; //创建线程使用的信息数组
char str[20] = { 0 }; //要查询的字符串
printf("输入要查询的姓名或电话:");
scanf("%s", str);
HANDLE hd[T];
if (LINE % T)
{
for (int i = 0; i < T; i++)
{
strcpy(thread[i].findstr, str);
thread[i].start = allindex.pindex + i*(LINE / T);
thread[i].length = LINE / T;
thread[i].id = i + 1;
hd[i] = _beginthread(runthread, 0, &thread[i]);
}
}
else
{
for (int i = 0; i < T-1; i++)
{
strcpy(thread[i].findstr, str);
thread[i].start = thread[i].start + i*LINE / (T-1);
thread[i].length = LINE /(T-1);
thread[i].id = i + 1;
hd[i]= _beginthread(runthread, 0, &thread[i]);
}
int i = T -1;
strcpy(thread[i].findstr, str);
thread[i].start = thread[i].start + i*LINE / (T - 1);
thread[i].length = LINE % (T-1);
thread[i].id = i + 1;
hd[i] = _beginthread(runthread, 0, &thread[i]);
}
WaitForMultipleObjects(T, hd, TRUE, INFINITE); //等待所有的线程退出
system("pause");
}