您的位置:首页 > 理论基础 > 计算机网络

在 iOS 中对接收到的网络数据(NSData)进行文件读写

2015-08-26 14:59 483 查看
在 c 语言中,文件操作都是由库函数来实现的,主要是分为读和写两种操作:

文件指针

平常所说的文件不同于其他常见的数据类型,比如一个test.txt文档,它有自己的一些属性,比如文件的当前位置、与该文件对应的内存缓冲区地址、文件操作方式等等。对于这些信息都会专门开辟一定内存空间来存储。而且是保存在一个结构体类型的变量中,比如:

struct
{
int fd;           //文件号
int cleft;        //缓冲区中剩下的字符
int mode;         //文件操作模式
char *nextc;      //下一个字符位置
char *buff;       //文件缓冲区位置
}FILE;
/*FILE是一个存储文件信息的结构体类型的变量*/
在上述代码中可以看到,文件号、文件操作模式等信息都存储在一个结构体中。

这个结构体是系统自己定义的,定义在stdio.h头文件中,取名为FILE。也就是说FILE是系统名称,不可改变的,不是自定义。

所以只要程序用到一个文件,系统就为此文件开辟一个如上的结构体变量。需要几个文件,系统就开辟几个这样的结构体。

这些结构体变量不用变量名来标识,而是通过指向结构体类型的指针变量去访问,这就是文件指针。

比如:FILE *fp1,*fp2,*fp3; 当引用文件时,就可以把这个文件的结构体首地址赋给某个文件指针(*fp1),通过*fp1就可以调用结构体以找到相关的信息。

一般来说,有多少个文件就有多少个结构体,有多少结构体就有多少个文件指针。
对磁盘文件的操作必须是先打开,然后读写操作,最后关闭。

打开文件

函数原型

FILE * fopen(const char * path,const char * mode);
path:需要打开的文件路径

mode:文件打开方式
返回值:文件顺利打开后,返回指向该流的文件指针。如果文件打开失败则返回NULL,并把错误代码存在errno中。(errno
是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定义)

其中文件打开方式主要有一下几种:

文件使用方式

含义

“r”(只读)

为输入打开一个文本文件

“w”(只写)

为输出打开一个文本文件

“a”(追加)

为文本文件尾增加数据

“rb”(只读)

为输入打开一个二进制文件

“wb”(只写)

为输出打开一个二进制文件

“ab”(追加)

向二进制文件尾增加数据

“r+”(读写)

为读写打开一个文本文件

“w+”(读写)

为读写打开一个新的文本文件

“a+”(读写)

为读写打开一个文本文件

“rb+”(读写)

为读写打开一个二进制文件

“wb+”(读写)

为读写建立一个新的二进制文件

“ab+”(读写)

为读写打开一个二进制文件

“t”(文本文件)可以省略不写

总结为:r为读 w为写 b为二进制文件 a为追加 +为读写。可以组合使用

关闭文件

函数原型:
int fclose( FILE *fp );
返回值:如果流成功关闭,fclose
返回 0,否则返回EOF(-1)。(如果流为NULL,而且程序可以继续执行,fclose设定error number给EINVAL,并返回EOF。)

读写文件

常用的文件读写函数主要有:

字符读写函数:fgetc() 和 fputc (getc 和 putc)

字符串读写函数:fgets() 和 fputs()

数据块读写函数:fread() 和 fwrite()

格式化读写函数:fscanf() 和 fprintf()

fread()


函数原型

size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
功能:从一个文件流中读数据,最多读取count个元素,每个元素size字节,如果调用成功返回实际读取到的元素个数,如果不成功或读到文件末尾返回
0。
buffer:用于接收数据的内存地址。
size:要读的每个数据项的字节数,单位是字节(byte)。
count:要读count个数据项,每个数据项size个字节。
stream:文件输入流
返回值:实际读取的元素个数。如果返回值与count不相同,则可能文件结尾或发生错误。从ferror和feof获取错误信息或检测是否到达文件结尾。

fwrite()



函数原型

size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
功能:向文件写入一个数据块(注意:这个函数以二进制形式对文件进行操作,不局限于文本文件)。
buffer:是一个指针,对fwrite来说,是要获取数据的地址(即数据来源地址)。
size:要写入内容的单字节数。
count:要进行写入size字节的数据项的个数。
stream:目标文件指针。
返回值:返回实际写入的数据块数目。

fseek()

函数原型

int fseek(FILE *stream, long offset, int fromwhere);
功能:重定位流(数据流/文件)上的文件内部位置指针(即:可以移动文件的读写指针到指定的位置,即移动当前文件的位置指针)。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
stream:文件指针。
offset:偏移量。
fromwhere:指针的起始位置,为下列其中一种
* SEEK_SET:从距离文件开头 offset 位移量为新的读写位置;
* SEEK_CUR :以目前的读写位置往后增加 offset 个位移量;
* SEEK_END :将读写位置指向文件末尾后再增加 offset 个位移量。

ftell()

函数原型

long ftell(FILE *stream);
功能:用于获取文件位置指针当前位置相对于文件首的偏移字节数。(使用fseek()后再调用函数ftell()就能非常容易地确定文件的当前位置。)
strem:文件指针。(注意:文件指针必须是有效的,且必须指向一个通过 fopen()popen() 成功打开的文件。在附加模式(加参数
"a" 打开文件)中 ftell() 会返回未定义错误。)
返回值:
handle
指定的文件指针的位置,也就是文件流中的偏移量。如果出错,返回 FALSE
约束:因为ftell返回long型,根据long型的取值范围-231~231-1(-2147483648~2147483647),故对大于2.1G的文件进行操作时出错。

改变文件大小

ftruncate()

函数原型
int ftruncate(int fd,off_t length);
功能:将参数fd指定的文件大小改为参数length指定的大小。
fd:为已打开的文件描述词,而且必须是以写入模式打开的文件。
length:要改成的大小,如果原来的文件大小比参数length大,则超过的部分会被删去。
返回值:执行成功则返回0,失败返回-1,错误原因存于errno
错误代码

EBADF 参数fd文件描述词为无效的或该文件已关闭。

EINVAL 参数fd 为一socket 并非文件,或是该文件并非以写入模式打开。
说明:fd一般可以fileno(FILE *fp)获取,标示文件当前的大小,lenggth则可由用户定义。此函数一般用在文件初始化或者重新为文件分配空间时。

fileno()

函数原型
int _fileno( FILE *stream );
功能:用来取得参数stream指定的文件流所使用的文件描述符。
stream:文件输入流。
返回值:某个数据流的文件描述符。

下面简单讲一下在iOS 下,对NSData 的文件读写:

读文件

/*
* ===  FUNCTION  ==================================================
*         Name:  readDataToBuffer:fromPath:
*  Description:  从指定 path 的文件读取内容到 buffer
* =================================================================
*/
-(void)readDataToBuffer:(char *)buffer fromPath:(NSString *)path
{

FILE *p_r= fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "r");  //打开文件
if (NULL == p_r)
{
NSLog(@"Open file error to read data !");
return ;
}

fseek(p_r, 0, SEEK_END);                //定位到文件末尾
NSInteger dataLength = ftell(p_r);      //获取文件长度
fseek(p_r, 0, SEEK_SET);                //定位到文件起始位置
fread(buffer, dataLength, 1, p_r);      //读取文件到指定的缓冲区
fclose(p_r);                            //关闭文件

}


写文件

/*
* ===  FUNCTION  ==================================================
*         Name:  writeData:toPath:
*  Description:  把数据写到指定的文件中
* =================================================================
*/
-(void)writeData:(NSData *)data toPath:(NSString *)path
{
FILE *p_w= fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "ab");  //已追加二进制方式打开文件
if (NULL == p_w)
{
NSLog(@"Open file error to write data!");
return ;
}
fseek(p_w, 0, SEEK_END);                                 // 移到文件末尾
fwrite((void *)[data bytes], data.length, 1, p_w);       // 写入数据
data = nil;
fclose(p_w);                                             //关闭文件
}


此博文源自 /article/11517861.html

如需转载,请说明博文出处。谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: