请教怎样实现一次I/O写多行文本到文本文件?谢谢

summber_flower 2013-10-10 10:20:47
原帖如下
http://bbs.csdn.net/topics/390583874
读取foxpro的DBF文件,我希望攒够2000行(也就是2000条记录)
先在内存里保存,当积累到2000条记录的时候,才写一次文件,也就是每次写2000行
然后清掉buffer里的2000行,再次积累到2000行的时候,写一次文件
最后一次写文件,可能不是2000行,比如一个DBF文件有5000行,会写3次,2000,2000,1000
类似于java的bufferwriter,不知道C++怎么实现?
谢谢
...全文
431 45 打赏 收藏 转发到动态 举报
写回复
用AI写文章
45 条回复
切换为时间正序
请发表友善的回复…
发表回复
summber_flower 2013-10-17
  • 打赏
  • 举报
回复
多谢zhao4zhong1大神,还有其他的大牛,先结贴
summber_flower 2013-10-15
  • 打赏
  • 举报
回复
引用 42 楼 shiguojie19892 的回复:
[quote=引用 1 楼 turingo 的回复:] 1、用malloc/free管理你的buffer; 2、用fopen/fclose/fread/fwrite操作文件; 3、其中fwrite可以一次性把buffer中的数据写入文件。 [quote=引用 楼主 u011718046 的回复:] 原帖如下 http://bbs.csdn.net/topics/390583874 读取foxpro的DBF文件,我希望攒够2000行(也就是2000条记录) 先在内存里保存,当积累到2000条记录的时候,才写一次文件,也就是每次写2000行 然后清掉buffer里的2000行,再次积累到2000行的时候,写一次文件 最后一次写文件,可能不是2000行,比如一个DBF文件有5000行,会写3次,2000,2000,1000 类似于java的bufferwriter,不知道C++怎么实现? 谢谢
[/quote] 正解!写了2000后用一个函数fwrite()即可全部导出[/quote] 写了2000,写哪里?写文件?我只想2000行写一次文件啊
summber_flower 2013-10-15
  • 打赏
  • 举报
回复
引用 2 楼 max_min_ 的回复:
就和一般的保存的buffer写文件差不多吧! 只不过这里最好malloc来创建buffer空间,用栈空间不太好,太大! 读DBF文件的时候判断下结尾,没到就读2000行到buffer写如新文件, 然后清空buffer继续读DBF文件,循环,结尾读完关闭文件就好了!
谢谢 那个程序哪里用了栈空间了? 另外,我查了一下,似乎C++应该用new替代malloc?
赵4老师 2013-10-14
  • 打赏
  • 举报
回复
如下代码能正确打印每条记录得数据, for (rec=0;rec<Head.recnum;rec++) { printf("\n"); fread(buf,50,1,fdbf);buf[50]=0; printf("%s",buf); fread(buf,40,1,fdbf);buf[40]=0; printf("%s",buf); 如下代码也能正确打印每行记录 for (rec=0;rec<Head.recnum;rec++) { printf("\n"); fread(buf,90,1,fdbf);buf[90]=0; printf("%s",buf);
summber_flower 2013-10-14
  • 打赏
  • 举报
回复
引用 24 楼 zhao4zhong1 的回复:
[quote=引用 22 楼 u011718046 的回复:] 请教怎样将 char buf[256]; 在 FREAD之后 fread(buf,50,1,文件名); 然后将buf清空呢?然后接着下一次fread xieixxie
不需要清空,直接读取覆盖旧内容即可。[/quote] 上次你帮忙写得读DBF文件得代码,我大致看懂了 假设记录长度是90 我测试了如下两段代码 如下代码不能正确打印每条记录得数据, for (rec=0;rec<Head.recnum;rec++) { printf("\n"); fread(buf,50,1,fdbf); printf("%s",buf); fread(buf,40,1,fdbf); printf("%s",buf); 如下代码能正确打印每行记录 for (rec=0;rec<Head.recnum;rec++) { printf("\n"); fread(buf,90,1,fdbf); printf("%s",buf);
worldy 2013-10-14
  • 打赏
  • 举报
回复
C读写文件是有缓冲的,文件管理系统内部有缓存区,你只管往里面写就是,直到你close,或者缓存存盘函数,或者缓存区需要切换
赵4老师 2013-10-14
  • 打赏
  • 举报
回复
仅供参考
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <share.h>
#include <conio.h>
int fh;
int c,r;
__int64 offset,offset1,i64,n64,l64,r64;
char ln[16000+1];
int main(int argc,char **argv) {
    if (argc<2) {
        fprintf(stderr,"Usage:%s filename.txt [10]\nto reverse lines of file [default the last 10 lines,-1 for all lines].\n",argv[0]);
        return 1;
    }
    if (argc==2) n64=10i64;
    if (argc>2) sscanf(argv[2],"%I64d",&n64);
    fh=_sopen(argv[1],_O_BINARY|_O_RDONLY|_O_RANDOM,_SH_DENYNO);
    if (-1==fh) {
        fprintf(stderr,"Can not _sopen file %s!\n",argv[1]);
        return 2;
    }
    l64=_filelengthi64(fh);if (l64==0i64) {_close(fh);return 0;}
    offset=l64;
    offset1=_lseeki64(fh,-1i64,SEEK_END);
    if (offset1==-1i64) {_close(fh);return 3;}
    i64=0i64;
    while (1) {
        if (_read(fh,&c,1)<1) break;//
        if (('\n'==c && offset1<l64-1i64) || offset1==0i64) {
            if (offset1!=0i64) offset1++;
            if (_lseeki64(fh,offset1,SEEK_SET)==-1i64) break;//
            r64=offset-offset1;
            if (r64<=16000i64) {
                r=_read(fh,ln,(unsigned int)r64);
                if (r<=0) break;//
            } else {
                r=16000;
                while (1) {
                    if (r64>(__int64)r) {
                        r64-=(__int64)r;
                        if (1i64==r64 || 2i64==r64) {
                            r=8000;
                            r64+=(__int64)r;
                        }
                    } else {
                        r=(int)r64;
                        r64=0i64;
                    }
                    r=_read(fh,ln,r);
                    if (r<=0) break;//
                    if (0i64==r64) break;//
                    ln[r]=0;
                    printf("%s",ln);
                    r=16000;
                }
                if (r<=0) break;//
            }
            ln[r]=0;
            if (r>=2 && ln[r-1]=='\n' && ln[r-2]=='\r') {ln[r-2]='\n';ln[r-1]=0;r--;}//避免输出重定向到文件时行尾多出'\r'
            if (i64==0I64) {
                if ('\n'!=ln[r-1]) printf("%s\n",ln);
                else               printf("%s",ln);
            } else {
                printf("%s",ln);
            }
            i64++;
            if ((i64%10000)==0) cprintf("\r%I64d/%I64d",offset1,l64);
            if (n64>0i64 && i64>=n64) break;//
            offset=offset1;
            _lseeki64(fh,offset1-2i64,SEEK_SET);
            offset1-=2i64;
        } else {
            _lseeki64(fh,-2i64,SEEK_CUR);
            offset1--;
        }
    }
    _close(fh);
    return 0;
}
赵4老师 2013-10-14
  • 打赏
  • 举报
回复
引用 22 楼 u011718046 的回复:
请教怎样将 char buf[256]; 在 FREAD之后 fread(buf,50,1,文件名); 然后将buf清空呢?然后接着下一次fread xieixxie
不需要清空,直接读取覆盖旧内容即可。
shiguojie19892 2013-10-14
  • 打赏
  • 举报
回复
引用 1 楼 turingo 的回复:
1、用malloc/free管理你的buffer; 2、用fopen/fclose/fread/fwrite操作文件; 3、其中fwrite可以一次性把buffer中的数据写入文件。 [quote=引用 楼主 u011718046 的回复:] 原帖如下 http://bbs.csdn.net/topics/390583874 读取foxpro的DBF文件,我希望攒够2000行(也就是2000条记录) 先在内存里保存,当积累到2000条记录的时候,才写一次文件,也就是每次写2000行 然后清掉buffer里的2000行,再次积累到2000行的时候,写一次文件 最后一次写文件,可能不是2000行,比如一个DBF文件有5000行,会写3次,2000,2000,1000 类似于java的bufferwriter,不知道C++怎么实现? 谢谢
[/quote] 正解!写了2000后用一个函数fwrite()即可全部导出
赵4老师 2013-10-14
  • 打赏
  • 举报
回复
引用 40 楼 u011718046 的回复:
[quote=引用 38 楼 zhao4zhong1 的回复:] 1、buf不是字符数组吗?怎么把一个整数0赋值给字符数组buf呢? char即可以看成是表示ascii码的,也可以看成是-128~127的整数。 buf[50]=0;和buf[50]='\0';是一回事。 2、啥是“该结束未结束” 啊 如果没有buf[50]=0;这句,谁知道buf[50...]后面到啥时候才会遇到0x00呢? 3、为啥是0x00结束的字符串啊? 这是C语言的约定。ASCIIZ字符串。
好心的zhao4zhong1 大神,对我这样的菜菜鸟不厌其烦地指导 谢谢 也就是说 C/C++的字符数组是 '\0'结尾,那如果的DBF文件里本身也含有 \0 怎么办?[/quote] 读写DBF的程序是C编写的,如果DBF的某条数据内容含'\0'的话,它就会将其长度信息也一并保存到数据库中的。
void HexDump(char *buf,int len) {
    int i,j,k;
    char binstr[80];

    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%04x -",i);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            printf("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        printf("%s\n",binstr);
    }
}
summber_flower 2013-10-14
  • 打赏
  • 举报
回复
引用 38 楼 zhao4zhong1 的回复:
1、buf不是字符数组吗?怎么把一个整数0赋值给字符数组buf呢? char即可以看成是表示ascii码的,也可以看成是-128~127的整数。 buf[50]=0;和buf[50]='\0';是一回事。 2、啥是“该结束未结束” 啊 如果没有buf[50]=0;这句,谁知道buf[50...]后面到啥时候才会遇到0x00呢? 3、为啥是0x00结束的字符串啊? 这是C语言的约定。ASCIIZ字符串。
好心的zhao4zhong1 大神,对我这样的菜菜鸟不厌其烦地指导 谢谢 也就是说 C/C++的字符数组是 '\0'结尾,那如果的DBF文件里本身也含有 \0 怎么办?
赵4老师 2013-10-14
  • 打赏
  • 举报
回复
电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址; 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……
赵4老师 2013-10-14
  • 打赏
  • 举报
回复
1、buf不是字符数组吗?怎么把一个整数0赋值给字符数组buf呢? char即可以看成是表示ascii码的,也可以看成是-128~127的整数。 buf[50]=0;和buf[50]='\0';是一回事。 2、啥是“该结束未结束” 啊 如果没有buf[50]=0;这句,谁知道buf[50...]后面到啥时候才会遇到0x00呢? 3、为啥是0x00结束的字符串啊? 这是C语言的约定。ASCIIZ字符串。
summber_flower 2013-10-14
  • 打赏
  • 举报
回复
引用 36 楼 zhao4zhong1 的回复:
 fread(buf,50,1,fdbf);//从文件中读50个字节,放在buf[0]..buf[49]中(这50个字节值中确保没有0x00)
            buf[50]=0;//将buf[50]的值设置为0,以免下面输出时该结束未结束。
 printf("%s",buf);//输出从buf+0开始,直到0x00结束的字符串。
诶,基础太差,还是疑惑 1、buf不是字符数组吗?怎么把一个整数0赋值给字符数组buf呢? 2、啥是“该结束未结束” 啊 3、为啥是0x00结束的字符串啊?
赵4老师 2013-10-14
  • 打赏
  • 举报
回复
 fread(buf,50,1,fdbf);//从文件中读50个字节,放在buf[0]..buf[49]中(这50个字节值中确保没有0x00)
            buf[50]=0;//将buf[50]的值设置为0,以免下面输出时该结束未结束。
 printf("%s",buf);//输出从buf+0开始,直到0x00结束的字符串。
summber_flower 2013-10-14
  • 打赏
  • 举报
回复
晕死,如下写法就对了,这里 buf[50]=0 是啥意思啊?赋值?buf不是字符数组吗?怎么可以赋值整数0呢? 请大神指导一二,多谢了啊 for (rec=0;rec<Head.recnum;rec++) { printf("\n"); fread(buf,50,1,fdbf); buf[50]=0; printf("%s",buf); fread(buf,40,1,fdbf); buf[40]=0; printf("%s",buf); }
summber_flower 2013-10-14
  • 打赏
  • 举报
回复
引用 32 楼 zhao4zhong1 的回复:
在确保fdbf=fopen(...,"rb");且char buf[≥91]且没有遇到文件结束的前提下,
除非
    for (rec=0;rec<Head.recnum;rec++) {
        printf("\n");
        fread(buf,50,1,fdbf);buf[50]=0;
        printf("%s",buf);//此时buf[49]是一个汉字的前半个字节
        fread(buf,40,1,fdbf);buf[40]=0;
        printf("%s",buf);//此时buf[0]是一个汉字的后半个字节
    }
    fflush(stdout);
否则,和
    for (rec=0;rec<Head.recnum;rec++) {
        printf("\n");
        fread(buf,90,1,fdbf);buf[90]=0;
        printf("%s",buf);
    }
    fflush(stdout);
的输出绝对应该是一样的。
我再次测试了,如下写法,第一条记录是对的,从第二条记录开始貌似每行含有两条记录,但是记录的内容却不完整,没有汉字问题,假定没有汉字 if ((fdbf=fopen(buf,"rb"))==NULL) { fprintf(stderr,"Can not fopen file [%s]!",buf); return 2; } 。。。。。。 for (rec=0;rec<Head.recnum;rec++) { printf("\n"); fread(buf,50,1,fdbf); printf("%s",buf); buf[50]=0; fread(buf,40,1,fdbf); printf("%s",buf); buf[40]=0; }
summber_flower 2013-10-14
  • 打赏
  • 举报
回复
引用 32 楼 zhao4zhong1 的回复:
在确保fdbf=fopen(...,"rb");且char buf[≥91]且没有遇到文件结束的前提下,
除非
    for (rec=0;rec<Head.recnum;rec++) {
        printf("\n");
        fread(buf,50,1,fdbf);buf[50]=0;
        printf("%s",buf);//此时buf[49]是一个汉字的前半个字节
        fread(buf,40,1,fdbf);buf[40]=0;
        printf("%s",buf);//此时buf[0]是一个汉字的后半个字节
    }
    fflush(stdout);
否则,和
    for (rec=0;rec<Head.recnum;rec++) {
        printf("\n");
        fread(buf,90,1,fdbf);buf[90]=0;
        printf("%s",buf);
    }
    fflush(stdout);
的输出绝对应该是一样的。
我再测试一下,不会出现半个汉字,因为我是按照字段的字节数算的,比如总共2格字段,第一个字段50长度, 第二个字段40字节 想请大神指导一下 buf[50]=0; 是啥意思啊?清空buf ?没明白,网上也找不到答案 谢谢啊
赵4老师 2013-10-14
  • 打赏
  • 举报
回复
在确保fdbf=fopen(...,"rb");且char buf[≥91]且没有遇到文件结束的前提下,
除非
    for (rec=0;rec<Head.recnum;rec++) {
        printf("\n");
        fread(buf,50,1,fdbf);buf[50]=0;
        printf("%s",buf);//此时buf[49]是一个汉字的前半个字节
        fread(buf,40,1,fdbf);buf[40]=0;
        printf("%s",buf);//此时buf[0]是一个汉字的后半个字节
    }
    fflush(stdout);
否则,和
    for (rec=0;rec<Head.recnum;rec++) {
        printf("\n");
        fread(buf,90,1,fdbf);buf[90]=0;
        printf("%s",buf);
    }
    fflush(stdout);
的输出绝对应该是一样的。
summber_flower 2013-10-14
  • 打赏
  • 举报
回复
引用 30 楼 zhao4zhong1 的回复:
推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 不要把 fopen("...","...");fscanf,fprintf,fclose //读时把\r\n替换成\n,写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fread,fwrite,fclose //不作以上替换,遇到\x1a仍继续读;读写的内容当字节看待 弄混了
糊涂了 其实我不清楚buf[50]=0;是啥意思 而且我也测试过如下代码,不能正确打印每条记录的内容 for (rec=0;rec<Head.recnum;rec++) { printf("\n"); fread(buf,50,1,fdbf);buf[50]=0; printf("%s",buf); fread(buf,40,1,fdbf);buf[40]=0; printf("%s",buf);
加载更多回复(25)

64,685

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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