体会代码,有二种方式。第一种是初始化索引,第二种是在第一种建立好索引的基础上使用的移动文件指针的方式,减少读入内存数据的方式移动指针。详见下面代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
#define N 84357484
//读取大数据有多少行(不知道行数,无法开辟内存空间)
//把索引读入到 int a[n] 在堆上
//写入到文件
//索引文件载入到内存
//随机读
char *path = "E:\\qq.txt";
char *index = "E:\\qqindex.txt";
struct index //索引的数据结构
{
int *pindex; //每行的首地址
int length; //行数
}allindex;
int getLine(char *path)
{
int line = 0;
FILE *pfr = fopen(path, "rb");
if (pfr == NULL)
{
printf("文件打开失败!\n");
return -1;
}
else
{
while (!feof(pfr))
{
char str[256] = { 0 };
fgets(str, 256, pfr);
line++;
}
fclose(pfr);
}
return line;
}
//初始化数据
void initindex(char *path)
{
printf("索引数组开始分配...\n");
allindex.length = getLine(path);
allindex.pindex = calloc(N, sizeof(int)); //开辟内存空间
printf("索引数组完成分配。\n");
printf("开始读取...\n");
FILE *pfr = fopen(path, "rb");
FILE *pfw = fopen(index, "wb"); //索引文件
if (pfr == NULL || pfw == NULL)
{
printf("文件打开失败!\n");
return;
}
else
{
int alllength = 0;
int i = 0;
while (!feof(pfr))
{
char str[256] = { 0 };
fgets(str, 256, pfr);
//记录每行数据所占用的长度,方便后面指针查询的跳转
allindex.pindex[i] = alllength;
int length = strlen(str);
alllength += length;
i++;
}
fclose(pfr);
}
printf("结束读取...\n");
//把索引写入到文件中
printf("索引写入...\n");
fwrite(allindex.pindex, sizeof(int), allindex.length, pfw);
fclose(pfw);
printf("索引写入结束。\n");
//释放内存
//free(allindex.pindex);
/*printf("开始读取...\n");
FILE *pfr1 = fopen("E:\\qqindex.txt", "rb");
fread(allindex.pindex, sizeof(int), allindex.length, pfr1);
fclose(pfr1);
printf("结束读取...\n");*/
}
//快速读取,就是建立好索引文件后,直接读取索引文件
void qucik(char *path)
{
printf("索引数组开始分配...\n");
allindex.length = getLine(path);
allindex.pindex = calloc(N, sizeof(int)); //开辟内存空间
printf("索引数组完成分配。\n");
printf("开始读取...\n");
FILE *pfr1 = fopen("E:\\qqindex.txt", "rb");
fread(allindex.pindex, sizeof(int), allindex.length, pfr1);
fclose(pfr1);
printf("结束读取...\n");
}
void main1()
{
//int line = getLine(path);
//printf("%d\n", line);
initindex(path); //初始化
//qucik(path); //这是在上面的 初始化 后有了索引文件后可以这样快速执行。
FILE *pfr = fopen(path, "rb");
while (1)
{
printf("\n请输入要读取的行数:");
int num = 0;
scanf("%d", &num);
fseek(pfr, allindex.pindex[num], SEEK_SET);
char str[256] = { 0 };
fgets(str, 256, pfr);
printf("%s\n", str);
}
fclose(pfr);
system("pause");
}
// 因为索引文件保存的是int 数组,而数据排列是线性的,即每个数据所占的空间大小都一样。
//这时可以按指针移动,来跳到索引处(因为每个索行保存的每行数据的首地址),这时读出
//索引的值,然后再移动数据指针到相应的文件处,读出其中的 数据,这样可以使用较小的
//内存,可以完成对大数据的查询。不过首先要建立好索引。
void main()
{
FILE *pf1 = fopen(path, "rb");//数据文件
FILE *pf2 = fopen(index, "rb");//索引文件
if (pf1 == NULL || pf2 == NULL)
{
printf("文件打开失败!\n");
return;
}
while (1)
{
printf("\n请输入要读取的行数:");
int num = 0;
scanf("%d", &num);
int index =0;
fseek(pf2,num*sizeof(int) , SEEK_SET); //移动指针在索引文件中查询
fread(&index, sizeof(int), 1, pf2); //读出索引文件的值。
fseek(pf1, index, SEEK_SET);
char str[256] = { 0 };
fgets(str, 256, pf1);
printf("%s\n", str);
}
fclose(pf1);
fclose(pf2);
}