linux文件内内容按数值进行排序,对文件内容按字符单位进行排序(linux c)

RT:

前提:任意大小不超过4G的文件。

要求:对文件内容进行二进制排序,以升序为例

实现方法:

1.以字符为单位遍历源文件(source file)

2.用unsigned long arr[256]  中的每一位保存每个字符出现的个数(如读取到source中的一个字符的十六进制为0x01,则arr[0x01]++),最坏的情况4G文件保存的全部是一个十六进制值.unsigned long 刚好可以满足,这就是为什么定义成unsigned long 数组.

3.从arr[0x00]开始遍历arr,分别打印字符到目标文件(target file)中(如arr[0x05] 的值为5则向target file 写入5个0x05);

4.降序则从arr[255]开始反向遍历输出即可.

以下为具体实现:

filesort.h

#ifndef _FILE_SORT_H

#define _FILE_SORT_H

#define MAX_ARR_SIZE 256

#define BUFFER_SIZE 1024

int file_sort(const char *, const char *);

#endif /*_FILE_SORT_H*/

filesort.c

#include #include #include #include #include "filesort.h"

/**

*函数说明:通过接受用户输入的源文件名以及目标文件名,

* 按文件内容的二进制升序排序

*参数说明:argc 输入的参数个数

* argv 输入的参数

*/

int main(int argc, char *argv[])

{

int ret = 0;

if (argc < 3)

{

printf("input args error!\n");

return 1;

}

if (0 == strcmp(argv[1], argv[2]))

{

printf("source file name must not be equals target file name!\n");

return 1;

}

ret = file_sort(argv[1], argv[2]);

/*ret != 0,sort fail*/

if (ret)

{

printf("sort fail!\n");

return 1;

}

return 0;

}

/**

*函数功能:将文件内容按二进制升序排序

*参数说明:sf 源文件名

* tf 目标文件名

*/

int file_sort(const char *sf, const char *tf)

{

FILE *prf = NULL;

FILE *pwf = NULL;

int read_bytes = 0;

int write_bytes = 0;

int idx = 0;

int flag = 0;

unsigned long cnt = 0;

unsigned char buffer[BUFFER_SIZE];

unsigned long arr[MAX_ARR_SIZE]={0};

assert(NULL != sf);

assert(NULL != tf);

do

{

prf = fopen(sf, "rb");

if (NULL == prf)

{

printf("cannot open the file:%s\n", sf);

flag = 1; /*flag sort fail*/

break;

}

pwf = fopen(tf, "wb");

if (NULL == pwf)

{

printf("cannot create the file:%s\n", tf);

flag = 1; /*flag sort fail*/

break;

}

/*read file and sort chars*/

while ((read_bytes = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, prf)))

{

if ((-1 == read_bytes) && (errno != EINTR))

{

break;

}

for (idx = 0; idx < read_bytes; idx++)

{

arr[buffer[idx]]++;

}/* end for */

}/* end while */

/* write target file with sorted chars*/

for (idx = 0; idx < MAX_ARR_SIZE; idx++)

{

for (cnt = 0; cnt < arr[idx]; cnt++)

{

buffer[write_bytes++] = idx;

if ((write_bytes % BUFFER_SIZE) == 0)

{

fwrite(buffer, sizeof(unsigned char), BUFFER_SIZE, pwf);

write_bytes = 0;

}

}

}

if (write_bytes > 0)

{

fwrite(buffer, sizeof(unsigned char), write_bytes, pwf);

}

flag = 0; /*flag sort ok*/

} while(0);

/*close source file and target file stream*/

fclose(prf);

fclose(pwf);

return flag;

}

Makefile文件:

CC = cc

CFLAGS = -g

SRC = filesort.c

INC = -I../inc

LIBS =

OBJ = $(SRC:.c=.o)

TARGET = ./fs

all:$(TARGET)

.c.o:

$(CC) $(CFLAGS) $(INC) -c $(@D)/$(

编译生成可执行文件:

ricesea@ricesea-laptop:~/cs/src$ make

执行(注:source 是在当前文件夹下存在的一个文件,也可以指定其他的文件, date命令打印出开始执行和执行之后的时间,相减可以得出排序所用的时间):

ricesea@ricesea-laptop:~/cs/src$ date&&filesort source target&&date

演示一下吧:

在当前文件夹下有source文件:

1297880190034190336.htm

在文件中有如下内容:

1297880190034190336.htm

十六进制查看:

1297880190034190336.htm

执行一下:date&&./fs source target&&date

1297880190034190336.htm

多生成了一个指定的target文件,查看一下target内容是否符合:

1297880190034190336.htm

十六进制:

1297880190034190336.htm

ok 已经排好序了,但是两次date输出的时间都一样,因为date只能显示到秒级别,而刚刚我们排序的文件比较小

花的时间很少,所以没有变化,现在打算对一个稍大一点的文件排序,看看要花多少时间!

source_temp:大概310多MB

1297880190034190336.htm

跑一下:date&&./fs source_temp target_temp&&date

1297880190034190336.htm

排序总用时大概:3(s).

再看看cp 命令对其copy需要多少时间(为了区别,cp的目标文件为target_cp):

1297880190034190336.htm

使用cp 命令总用时大概:2(s).

再看看文件列表:

1297880190034190336.htm

P.S.:本人使用linux版本:Linux version 2.6.32-38-generic (buildd@zirconium) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) )

CPU信息:Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz

内存:2G

代码包下载: 对文件内容排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值