文本文件内容定位问题?

sun420 2008-04-07 02:56:29
文本文件中保存多行数据,数据的格式如下:
2008_51,25,文件记录文件记录,文件记录文件记录.aaa
2008_52,266,文件记录文件记录,文件记录文件记录.aaa
2008_53,255,文件记录文件记录,文件记录文件记录.aaa
2008_54,25,文件记录文件记录,文件记录文件记录.aaa
......
***************************************************
每一行的记录长度不确定,那么如何取得任意一条记录的内容呢?

用C语言实现的,谢谢各位了!
...全文
231 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
rushman 2008-04-08
  • 打赏
  • 举报
回复
> 我的文件很大,又几十万行数据吧。我打算的是分块读入内存,然后进行排序和查找等操作......
建个索引吧。不一定要分块,记录跨块边界时比较麻烦。一行行读,一条记录一条记录的处理并不会降低效率。

索引的组织和排序的算法很多,需要斟酌。
最简单的索引是一维数组,配合快速排序的话,可以这样处理:

//
// 随手写的,没有检查、测试,程序中也没有检查参数及返回值,仅供参考
//

// 索引项
struct IndexItem{
long offset; // 记录位置
unsigned long hashkey; // 为便于排序/查找,避免频繁访问文件,可以对记录的键值进行散列
};

// 由于文件较大,可以一次读取、排序若干条记录,形成索引块,然后进行合并
// 若干索引块可以用链表组织起来
struct IndexBlock{
IndexItem * index;
int itemcount;
IndexBlock * nextblock;
};

// 为一条记录生成散列值
unsigned long hashKeyValue(const char * item){
// 根据需要设计一个散列算法
return(((unsigned long *)(const void*)item)[0] ^ ((unsigned long *)(const void*)item)[1]);
}

// 比较两条记录
int compRecord(const void * item1,const void * item2){
// 先比较 hashkey,如果相同再读取文件进行准确的比较
//..........
}

// 一次读取idxCount条记录
int readDataBlock(FILE* inputfile, IndexItem * idx,int idxcount){
int i;
char buffer[BUFFERSIZE];
for(i = 0; i < idxcount && !feof(inputfile);i++){
fgets(buffer,BUFFERSIZE,inputfile);
idx[i].offset = ftell(inputfile);
idx[i].hashkey = hashKeyValue(buffer);
}
return (i);
}

// 读取文件记录
int readData(FILE * inputfile, IndexBlock * head){
int count = 0;
IndexBlock * newblock = head;
do{
newblock->nextblock = new IndexBlock;
newblock = newblock->nextblock;
newblock->index = new IndexItem[BLOCKSIZE];
newblock->itemcount = readDataBlock(inputfile,newblock->index,BLOCKSIZE);
count += newblock->itemcount;
}while(!feof(inputfile));
newblock->nextblock = NULL;
return (count);
}

// 合并两个索引块
int unionIndexBlock(const IndexBlock * index1,const IndexBlock * index2,IndexBlock * resuindex){
int i1,i2,ir,total;
total = index1->itemcount + index2->itemcount;
for(ir = i1 = i2 = 0; ir < total; ir++){
if(compRecord(index1->index[i1],index2->index[i2]) > 0){
copyIndex(index2->index[i2],resuindex->index[ir]);
i2++;
}else{
copyIndex(index1->index[i1],resuindex->index[ir]);
i1++;
}
}
resuindex-itemcount = ir;
return (resuindex->itemcount);
}

// 读取文件并创建索引
IndexBlock * createIndex(FILE * inputfile){
IndexBlock head;
IndexBlock * currblock;
IndexBlock * newblock;

readData(inputfile, &head);

// 排序
for(currblock = head.nextblock; currblock != NULL; currblock = currblock->nextblock){
qsort((void*)currblock->head,currblock->itemcount,sizeof(IndexItem),compRecord);
}

// 合并索引块
while(head.nextblock->nextblock != NULL){
currblock = &head;
while(true){
if(currblock->nextblock == NULL || currblock->nextblock->nextblock == NULL)break;
newblock = new IndexBlock;
newblock->index = new IndexItem[currblock->nextblock->itemcount + currblock->nextblock->nextblock->itemcount];
newblock->nextblock = currblock->nextblock->nextblock->nextblock;
unionIndexBlock(currblock->nextblock,currblock->nextblock->nextblock,newblock);
delete []currblock->nextblock->nextblock->index;
delete []currblock->nextblock->index;
delete currblock->nextblock->nextblock;
delete currblock->nextblock;
currblock->nextblock = newblock;
currblock = newblock;
}
}
return (head.nextblock);
}
sun420 2008-04-08
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 rushman 的回复:]
如果文件不大,可以考虑一次性全部读入内存。
如果文件比较大,那就建个索引。


C/C++ code#define MAXSIZE 1000
#define BUFFSIZE 1000

fpos_t index[MAXSIZE];
char buffer[BUFFSIZE];

for(int i = 0;i < MAXSIZE;i++){
fgetpos(index + i,inputFile);
fgets(buffer,BUFFSIZE,inputFile);
if(feof(inputFile))break;
}
[/Quote]
我的文件很大,又几十万行数据吧。我打算的是分块读入内存,然后进行排序和查找等操作。
不知道又什么好的建议吗?谢谢了
rushman 2008-04-07
  • 打赏
  • 举报
回复
如果文件不大,可以考虑一次性全部读入内存。
如果文件比较大,那就建个索引。

#define MAXSIZE 1000
#define BUFFSIZE 1000

fpos_t index[MAXSIZE];
char buffer[BUFFSIZE];

for(int i = 0;i < MAXSIZE;i++){
fgetpos(index + i,inputFile);
fgets(buffer,BUFFSIZE,inputFile);
if(feof(inputFile))break;
}
冰矿 2008-04-07
  • 打赏
  • 举报
回复

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define M 256
int main()
{
FILE *F = fopen("file.txt","rt");
char buff[M];
char searchstr[M];
char *find = NULL;
if (F == NULL) exit(1);
printf("输入你要找的纪录号:");
scanf("%s",searchstr);
while (!feof(F))
{
fgets(buff,M-1,F);
if (buff[0] == '\n') continue; /*如果是空行直接再读取下一行*/
find = strstr(buff,searchstr);
if (find != NULL)
{
puts(buff); find = NULL;
}
}
fclose(F);
system("PAUSE");
return 0;
}

测试
输入你要找的纪录号:2008_54
2008_54,25,文件记录文件记录,文件记录文件记录.aaa
请按任意键继续. . .
Inhibitory 2008-04-07
  • 打赏
  • 举报
回复
自己再写一个程序, 对这个文件的每一行开始的位置建立索引, 然后先读入索引文件, 读取行的位置, 打开这个文本文件, 把文件指针跳到目标位置
lala_benben 2008-04-07
  • 打赏
  • 举报
回复
一次读一行。。。
sun420 2008-04-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 Kenmark 的回复:]
读入内存建立表格然后索引
因为记录长度不一样
[/Quote]
能不能具体讲一下呢?
你的意思是再建立一个文件,用来记录每条记录的长度吗?
那如果现在就想按顺序遍历这个文件,同时返回此时位置指针指向记录的内容呢?
这样应该比随机取的实现方法简单一些吧?
我啃 2008-04-07
  • 打赏
  • 举报
回复
读入内存建立表格然后索引
因为记录长度不一样
sun420 2008-04-07
  • 打赏
  • 举报
回复
别沉~上去!!
用于windows下面的vim编辑器。 给喜欢vim的人使用。详细如下: 好吧,详细点,这里写出一些基本的命令: 【什么是vi】 vi就是linux命令行下的最著名的编辑器之一,(编辑器就是类似windows记事本的功能,不过vi功能比记事本强大无限倍!^_^),现在实际使用的都是vim,它是vi的改进版本,所以现在的vi基本上就是vim了。 【vi能做什么】 第一个功能不用多说,vi可以编辑文本文件。至于其他的功能,多得无法列举,我只说我所知的一些典型的功能应用: (1)编辑文本文件 (2)方便地阅读程序源代码 (3)当文件目录浏览器来用 (4)提供编程、调试环境 (5)利用vi执行一些脚本文件(vi有自己的脚本文件语法) (x)等等等等...... 【vi的操作模式】   vi具有两种基本模式,为输入模式(或插入模式、编辑模式)和指令模式(或命令模式)。输入模式下输入字符,文本就会显示在屏幕上;而指令模式下输入字符就解释为一个输入命令并执行,而不会显示相应的字符。理解指令模式最简单方式就是想象平时剪切、复制以及粘贴数据时所发生的情况。 使用[Esc]键可以停止当前操作(插入或者命令)重新回到指令模式,准备接受新的指令。如果本来就在指令模式下面,将会响铃一下。 【最基本的使用】 这里提供了使用vi得最基本的操作,能够实现大多数的编辑目的。如果你肯花几分钟把“最基本的使用”的内容都实践一下,那么你至少可以独立地在vim中朝你想要得方向“前进”了。如果你不想学习,那么就把它当作一个“字典”吧。 *用vi打开一个文件: 输入“vi filename”. 这里,filename就是你要打开的文件的名字,默认打开文件后vi处于指令模式。 *进入编辑模式编辑打开的文件: 输入“i”. 或输入“a”. 进入编辑模式后,你可以直接敲入想要输入的字符到文件,两者的区别是i在当前字符前面开始插入,a在当前字符后面开始插入。 *退出编辑模式: 输入“[Esc]”. 这样,将返回指令模式,准备接收你要传达给vi的指令并执行,如果之前已经在指令模式下,那么系统将响铃提醒一下。 **以下命令都是在命令模式下进行: *撤销修改: 输入“u”. 这里,相比以前的vi来说,vim支持多步撤销。 *恢复修改: 输入“[Ctrl]r”. 这里,和撤销命令相反,是撤销的撤销,也可多步。 *复制行到剪切板: 输入“yy”. *复制选定内容到剪切板: (1)输入“v”。 (2)按方向键将高亮选择的内容。 (3)输入“y”。 这里,开始输入v使vi临时进入了一个"选择模式",输入方向键可以选择,输入y将选择的内容复制剪切板。 *删除行: 输入“dd”. 注意,vi的删除等价于剪切,删除的内容会保存到剪切板中。 *删除选定内容: (1)输入“v”。 (2)按方向键将高亮选择的内容。 (3)输入“d”。 这里,开始输入v使vi临时进入了一个“选择模式”,输入方向键可以选择,输入d将选择的内容删除。 *粘贴: 输入“p”. 这样会将剪切板的内容粘贴到光标位置或者光标下一行。 *查找字符并定位到第一个匹配处: 输入“/character”. 这里character是待查找的字符,只要先输入/,再输入待查字符,最后回车即可定位到第一个匹配的字符处。 *定位到匹配查找的下一个字符处: 输入“n”. *定位到匹配查找的上一个字符处: 输入“N”. *保存文件: 输入“:w”. 注意w前面的':',输入':'之后,vim会将':'之后的输入解释为待执行的指令。 *退出: 输入“:q”. 这里,如果文件没有保存,将提示无法退出,除非你强制退出,不保存文件,或者保存退出。 *强制退出: 输入“:q!”. *保存退出: 输入“:wq”. 或输入“ZZ”. *察看帮助 输入":help". ** 另外还有一个简易的教程: 输入命令:vimtutor.

70,023

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧