索引的作用(为什么要有索引?):
当要对大数据文件进行随机 读取时,一种方法是先全部读入内存,以数组形式存储,通过数组索引下标形式进行访问,
缺点是要占用大量的内存,我们知道对计算机而言内存是相当宝贵的。
另一种方法就是建立文件索引,通过文件索引查找数据。思路:把每一行字符串的数据首地址记录下来,存入数组,再通过文件指针访问数组中的存储地址所指向的数据。
程序步骤
1.读取文件中一共有多少行数据
2.得到每行数据在文件中的地址
3.写入索引文件
4.载入索引文件到内存或者直接从索引文件读取每行数据所在的地址
5.随机读取想要读取的行数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char path[256] = "D:\\C++\\test.txt";
char indexpath[256] = "D:\\C++\\index.txt";
#define N 8000000 //通过getN()得到行数
struct index
{
int *pindex; //地址
int length; //长度
}allindex;
int getN() //得到行数
{
int i = 0;
FILE *pf = fopen(path, "rb");
if (pf == NULL)
{
return -1;
}
else
{
int i = 0;
int alllength = 0;
while (!feof(pf))
{
char str[50] = { 0 };
fgets(str, 50, pf);
i++;
}
//printf("\n all = %d", alllength);
fclose(pf);
return i;
}
}
void init(char *path) // 生成索引并写入到文件
{
printf("索引数组开始分配 \n");
allindex.length = N;
allindex.pindex = calloc(N, sizeof(int));
printf("索引数组完成分配 \n");
printf("开始读取 \n");
FILE *pf = fopen(path, "rb");
if (pf == NULL)
{
return -1;
}
else
{
int alllength = 0;
for (int i = 0; i < N; i++)
{
char str[50] = { 0 };
fgets(str, 50, pf);
allindex.pindex[i] = alllength;
int length = strlen(str);
alllength += length;
}
fclose(pf);
}
printf("\n 结束读取");
printf("\n 开始写入");
FILE *pfw = fopen(indexpath, "wb"); //写入索引
fwrite(allindex.pindex, sizeof(int), allindex.length, pfw);
fclose(pfw);
printf("\n 结束写入");
free(allindex.pindex);
}
void readindex() // 读取索引文件到内存
{
printf("索引数组开始分配 \n");
allindex.length = N;
allindex.pindex = calloc(N, sizeof(int));
printf("索引数组完成分配 \n");
printf("\n 开始读取");
FILE *pfw = fopen(indexpath, "rb"); //写入索引
fread(allindex.pindex, sizeof(int), allindex.length, pfw);
fclose(pfw);
printf("\n 结束读取");
}
void main() //通过读索引到内存,再访问大数据文件读取数据
{
init(path);
readindex();
FILE *pf = fopen(path, "rb");
while (1)
{
printf("请输入要读取的行数");
int num = 0;
scanf("%d", &num);
fseek(pf, allindex.pindex[num], SEEK_SET);
char str[128] = { 0 };
fgets(str, 128, pf);
printf("%s", str);
}
printf("%d", getN());
system("pause");
}
void main1() //生成好索引后,直接从索引文件读取数据地址,再访问大数据文件读取数据
{
FILE *pf1 = fopen(indexpath, "rb");
FILE *pf2 = fopen(path, "rb");
while (1)
{
printf("请输入要读取的行数");
int num = 0;
scanf("%d", &num);
int indexnum = 0;
fseek(pf1,num *sizeof(int), SEEK_SET);
fread(&indexnum, sizeof(int), 1, pf1);//读索引
fseek(pf2, indexnum, SEEK_SET);
char str[128] = { 0 };
fgets(str, 128, pf2);
printf("%s", str);
}
system("pause");
}