当前位置: 技术问答>linux和unix
求教:Unix下用c实现文本文件的随机读写的问题!!!
来源: 互联网 发布时间:2015-05-01
本文导语: 问题:有一个文件file1,内容格式为:字段1|字段2|,有n条记录,且记录是无序排列的,现在要求在不改变记录的排序的情况下,将所有字段1相同的记录中的字段2的值也改为相同的。如:原文件内容为: 1101|1| 1002|2| 110...
问题:有一个文件file1,内容格式为:字段1|字段2|,有n条记录,且记录是无序排列的,现在要求在不改变记录的排序的情况下,将所有字段1相同的记录中的字段2的值也改为相同的。如:原文件内容为:
1101|1|
1002|2|
1101|2|
1002|3|
要求修改后为:
1101|1|
1002|2|
1101|1|
1002|2|
请教该如何实现?
我想用双重循环来读取文件,然后依次找到字段1相同的记录,然后修改记录的字段2
的值,写入原位置,可是我不清楚怎么将字段2的值修改后再写入原来的位置?
我用fgets来逐行读取记录的,可是怎么得到字段2的起始位置?
1101|1|
1002|2|
1101|2|
1002|3|
要求修改后为:
1101|1|
1002|2|
1101|1|
1002|2|
请教该如何实现?
我想用双重循环来读取文件,然后依次找到字段1相同的记录,然后修改记录的字段2
的值,写入原位置,可是我不清楚怎么将字段2的值修改后再写入原来的位置?
我用fgets来逐行读取记录的,可是怎么得到字段2的起始位置?
|
/* recordio */
#include
#include
#include
#include
#include "recordio.h"
int initrecord(const char* pathname, unsigned int reclen)
{
int fd;
int rs;
RECORDINFO info;
if ( (fd = open(pathname, O_RDWR|O_CREAT, 0660)) == -1 ) {
perror("Fail to open file for initializing record");
return -1;
}
if ( (rs = read(fd, &info, sizeof(RECORDINFO))) == -1 ) {
perror("Fail to read record info for initializing record");
return -1;
}
if ( rs == 0 ) {
info.reclen = reclen;
info.recnum = 0;
if ( write(fd, &info, sizeof(RECORDINFO)) == -1 ) {
perror("Fail to write record info for initializing record");
return -1;
}
}
close(fd);
return 0;
}
int addrecord(const char* pathname, void* buf, unsigned int reclen, unsigned int recnum)
{
int fd;
int rs;
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
if ( (fd = open(pathname, O_WRONLY|O_APPEND)) == -1 ) {
perror("Fail to open file for adding record");
return -1;
}
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to lock file for adding record");
return -1;
}
lock.l_type = F_UNLCK;
rs = write(fd, buf, reclen * recnum);
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to unlock file for adding record");
return -1;
}
close(fd);
return rs;
}
int getrecord(const char* pathname, void* buf, unsigned int reclen, unsigned int recnum)
{
int fd;
int len;
RECORDINFO info;
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
if ( (fd = open(pathname, O_RDWR)) == -1 ) {
perror("Fail to open file for geting record");
return -1;
}
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to lock file for geting record");
return -1;
}
lock.l_type = F_UNLCK;
if ( read(fd, &info, sizeof(RECORDINFO)) != sizeof(RECORDINFO) ) {
perror("Fail to read record info");
return -1;
}
if ( info.reclen != reclen ) {
fprintf(stderr, "Invalid reclen parameter n");
return -1;
}
if ( lseek(fd, sizeof(RECORDINFO) + info.reclen * info.recnum, SEEK_SET) == -1 ) {
perror("Fail to seek read position");
return -1;
}
if ( (len = read(fd, buf, reclen * recnum)) == -1 ) {
perror("Fail to get record");
return -1;
}
if ( len == 0 ) {
if ( ftruncate(fd, sizeof(RECORDINFO)) == -1 ) {
perror("Fail to truncate file");
return -1;
}
info.recnum = 0;
if ( lseek(fd, 0, SEEK_SET) == -1 ) {
perror("Fail to return beginning");
return -1;
}
if ( write(fd, &info, sizeof(RECORDINFO)) == -1 ) {
perror("Fail to update record info");
return -1;
}
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to unlock file for geting record");
return -1;
}
close(fd);
return 0;
} else {
info.recnum += len / info.reclen;
if ( lseek(fd, 0, SEEK_SET) == -1 ) {
perror("Fail to return beginning");
return -1;
}
if ( write(fd, &info, sizeof(RECORDINFO)) == -1 ) {
perror("Fail to update record info");
return -1;
}
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to unlock file for geting record");
return -1;
}
close(fd);
return len;
}
}
|
"或者是怎样在用fgets读取了一行记录后再回到该行记录的起始处?这样我就可以用fputs写入修改后的记录了"
ftell:获得当前文件位置
fseek:跳转当前文件位置
ftell:获得当前文件位置
fseek:跳转当前文件位置
|
每条记录是不是都是同样长度的?那就简单多了。
用fseek就行了,比如你上面的例子
首先,估计一个数组arc[7][100];
然后,fgets,每取到一个全新的记录,就添加到arc里,然后fseek(fp, -3, SEEK_SET)(应该是往前回3个吧,你自己再测试一下 :)),然后fputs就可以了。
用fseek就行了,比如你上面的例子
首先,估计一个数组arc[7][100];
然后,fgets,每取到一个全新的记录,就添加到arc里,然后fseek(fp, -3, SEEK_SET)(应该是往前回3个吧,你自己再测试一下 :)),然后fputs就可以了。
|
如果要提高效率就
1、导入HASH表
2、多线程对数据进行修改
3、写文件
1、导入HASH表
2、多线程对数据进行修改
3、写文件