首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 写入大文件求助 [已结帖,结帖人:kokiahuang]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kokiahuang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-11-04 14:40:50 楼主
    写入文件时,大小超过4G就崩溃了,

    Google无果,求高手帮忙解答一下,

    机器32-bits,已加编译选项包括:

    -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D__GLIBC_HAVE_LONG_LONG
    20  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • freshui
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-04 14:44:431楼 得分:0
    大于4G的文件一定要在NTFS格式下,不能在FAT32下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kokiahuang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-04 14:48:212楼 得分:0
    确定?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kokiahuang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-04 14:49:513楼 得分:0
    对了,是在linux下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • freshui
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-04 18:05:094楼 得分:10
    如何create大文件 (2006-08-08 12:26:00)
       

    如何create大文件
    要大就非常大,1T吧。
    有两种方法:

    一.dd
    dd if=/dev/zero of=1T.img bs=1G seek=1024 count=0
    bs=1G表示每一次读写1G数据,count=0表示读写0次,seek=1024表示略过1024个Block不写,前面block size是1G,所以共略过1T!
    这是创建大型sparse文件最简单的方法。

    二.ftruncate64/ftruncate
    如果用系统函数就稍微有些麻烦,因为涉及到宏的问题。我会结合一个实际例子详细说明,其中OPTION标志的就是测试项。
    文件sparse.c:

    //OPTION 1:是否定义与大文件相关的宏
    #define _LARGEFILE_SOURCE
    #define _LARGEFILE64_SOURCE
    #define _FILE_OFFSET_BITS 64

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <string.h>
    #define FILENAME "bigfile"
    #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
    int main(int argc, char **argv)
    {
      int fd, ret;
      off_t offset;
      int total = 0;
      if ( argc >= 2 )
      {
        total = atol(argv[1]);
        printf("total=%d\n", total);
      }

      //OPTION 2:是否有O_LARGEFILE选项
      //fd = open(FILENAME, O_RDWR|O_CREAT|O_LARGEFILE, 0644);
      fd = open(FILENAME, O_RDWR|O_CREAT, 0644);
      if (fd < 0) {
        perror(FILENAME);
        return -1;
      }
      offset = (off_t)total *1024ll*1024ll*1024ll;
      printf("offset=%ld\n", offset);

      //OPTION 3:是否调用64位系统函数
      //if (ftruncate64(fd, offset) < 0)
      if (ftruncate(fd, offset) < 0)
      {
        printf("[%d]-ftruncate64 error: %s\n",  errno, strerror(errno));
        close(fd);
        return 0;
      }
      close(fd);
      printf("OK\n");
      return 0;
    }

    测试环境:
    linux:/disk/test/big # gcc --version
    gcc (GCC) 3.3.5 20050117 (prerelease) (SUSE Linux)
    linux:/disk/test/big # uname -a
    Linux linux 2.6.11.4-20a-default #1 Wed Mar 23 21:52:37 UTC 2005 i686 i686 i386 GNU/Linux

    测试结果(伪码表示):
    1.宏定义完全的情况下:
    IF {O_LARGEFILE=TRUE && ftruncate64=TRUE}
      OK;
    ELSEIF {O_LARGEFILE=FALSE && ftruncate64=TRUE}
      OK;
    ELSEIF {O_LARGEFILE=FALSE && ftruncate64=FALSE}
      运行不报错,但是不支持>4G;
    ELSEIF {O_LARGEFILE=TRUE && ftruncate64=FALSE}
      运行不报错,但是不支持>4G;
    【结论】:在宏定义完全的情况下,是否调用ftruncate64,是决定支持4G以上文件的关键,O_LARGEFILE无作用。

    2.宏定义不完全:缺少_FILE_OFFSET_BITS
    首先声明一点,O_LARGEFILE需要定义_LARGEFILE64_SOURCE。
    IF {O_LARGEFILE=TRUE && ftruncate64=TRUE}
      产生不正常超大文件;
    ELSEIF {O_LARGEFILE=FALSE && ftruncate64=TRUE}
      产生不正常超大文件;
    ELSEIF {O_LARGEFILE=FALSE && ftruncate64=FALSE}
      运行不报错,但是不支持>2G;
    ELSEIF {O_LARGEFILE=TRUE && ftruncate64=FALSE}
      运行不报错,但是不支持>4G;
    【结论】:未定义_FILE_OFFSET_BITS的情况下,ftruncate64调用是非法的,会产生无法预料的后果,这里的测试就是产生一个超大文件(>1T),我也无法解释其原因;O_LARGEFILE的作用就是在32位系统中支持大文件系统,允许打开那些用31位(2G)都不能表示其长度的大文件;此外,off_t为unsigned int类型,也就是说最多只能达到4G,所以ftruncate最大支持4G文件。

    总结一下:如果要支持超过2G的文件,至少需要定义_LARGEFILE64_SOURCE宏,并且设置O_LARGEFILE选项;如果要支持超过4G,需要定义所有上述的宏,并且调用ftruncate64;其余的搭配都是错误的!

    【附】:
    dd 的主要选项:
    指定数字的地方若以下列字符结尾乘以相应的数字:
    b=512, c=1, k=1024, w=2, m=1024k, g=1024m
    大小写不限。
    if=file
    输入文件名,缺省为标准输入。
    of=file
    输出文件名,缺省为标准输出。
    ibs=bytes
    一次读入 bytes 个字节(即一个块大小为 bytes 个字节)。
    obs=bytes
    一次写 bytes 个字节(即一个块大小为 bytes 个字节)。
    bs=bytes
    同时设置读写块的大小为 bytes ,可代替 ibs 和 obs 。
    cbs=bytes
    一次转换 bytes 个字节,即转换缓冲区大小。
    skip=blocks
    从输入文件开头跳过 blocks 个块后再开始复制。
    seek=blocks
    从输出文件开头跳过 blocks 个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)
    count=blocks
    仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数。
    conv=conversion[,conversion...]
    用指定的参数转换文件。
    转换参数:
    ascii 转换 EBCDIC 为 ASCII。
    ebcdic 转换 ASCII 为 EBCDIC。
    ibm 转换 ASCII 为 alternate EBCDIC.
    block 把每一行转换为长度为 cbs 的记录,不足部分用空格填充。
    unblock
    使每一行的长度都为 cbs ,不足部分用空格填充。
    lcase 把大写字符转换为小写字符。
    ucase 把小写字符转换为大写字符。
    noerror
    不显示错误
    notrunc
    不截短输出文件。
    sync 把每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • qhfu
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-04 18:29:475楼 得分:10
    程序最开始定义这三个宏,
    #define _LARGEFILE_SOURCE
    #define _LARGEFILE64_SOURCE
    #define _FILE_OFFSET_BITS 64


    然后用fopen FILE

    就能写64位的,我们就是这样写大文件的
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wutaozhao
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-04 18:38:116楼 得分:0
    路上的都很好
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kokiahuang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-05 11:02:337楼 得分:0
    不是添加了编译选项吗?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • anglecloudy
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-05 11:08:108楼 得分:0
    还是看看我的BLOG里面的这篇吧:http://hi.baidu.com/anglecloudy/blog/item/639be973f9d60a198701b01b.html
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved