副标题#e#
和很多的C++措施一样,有些人更喜欢用原先的C语言方法处理惩罚问题,假如你刚好也是这些人中的一员,就应该进修一下这篇文章。
根基的文件操纵有
◆fopen——打开文件,指定文件以奈何的方法打开(读/写)以及范例(二进制/文本)
◆fclose——封锁已经打开的文件
◆fread——读取文件
◆fwrite——写文件
◆fseek/fsetpos——将文件指示器转移到文件中的某一处所
◆ftell/fgetpos——可以汇报你文件指示器地址的位置
文件有两种根基范例:文本和二进制。在这两者之中,凡是二进制范例是较容易办理的。由于在文本中处理惩罚随机存取并不常用,我们会在本文中重点存眷二进制文件的处理惩罚。上面列出的操纵中的前四项可用于文本文件和随机存取文件。后头的两项则仅用于随机存取。
随机存取意味着我们可以在文件的任意部门之间举办切换,且可以从中读写数据而不需要通读整篇文件。
二进制文件
二进制文件是任意长度的文件,它生存有从0到0xff(0到255)不等的字节值。这些字节在二进制文件中没有任何意义,与此差异的是,在文本文件中,值为13就意味着回车,10意味着换行,26意味着文件竣事,而读取文本文件的软件要可以或许办理这些问题。
在此刻的术语中,我们将二进制文件称为包括了字节的字符流,大大都语言倾向于将其领略为字符流而不是文件。重要的部门是数据流自己而不是其来历。在C语言中,你能从文件或数据流方面来思量数据。可能,你可以将其领略为一组长的数组。通过随机存取,你可以读写数组的任意部门。
例一:
// ex1.c : Defines the entry point for the console application.
//
#include < stdio.h>
#include < string.h>
#include < windows.h>
int FileSuccess(FILE * handle,const char * reason, const char * path) {
OutputDebugString( reason );
OutputDebugString( path );
OutputDebugString(" Result : ");
if (handle==0)
{
OutputDebugString("Failed");
return 0;
}
else
{
OutputDebugString("Suceeded");
return 1;
}
}
int main(int argc, char * argv[])
{
const char * filename="test.txt";
const char * mytext="Once upon a time there were three bears.";
int byteswritten=0;
FILE * ft= fopen(filename, "wb");
if (FileSuccess(ft,"Opening File: ", filename)) {
fwrite(mytext,sizeof(char),strlen(mytext), ft);
fclose( ft );
}
printf("len of mytext = %i ",strlen(mytext));
return 0;
}
这段代码显示了一个简朴的打开待写的二进制文件,文本字符(char*)会写入该文件。凡是你会利用文本文件可是笔者想证明你可以向二进制文件写入文本。
// ex1.c
#include < stdio.h>
#include < string.h>
int main(int argc, char * argv[])
{
const char * filename="test.txt";
const char * mytext="Once upon a time there were three bears.";
int byteswritten=0;
FILE * ft= fopen(filename, "wb") ;
if (ft) {
fwrite(mytext,sizeof(char),strlen(mytext), ft) ;
fclose( ft ) ;
}
printf("len of mytext = %i ",strlen(mytext)) ;
return 0;
}
#p#副标题#e#
例一的浸染
这个例子打开了一个待写的二进制文件。FILE*变量从fopen()挪用中返回。假如这一操纵失败那么它会返回为0。
Fopen()呼吁试图打开指定的文件,在这个案例中则是位于沟通文件夹的test.txt。记着,假如文件包括一个路径那么所有的退格必需重叠。“c:\folder\test.txt”是错误的,你必需利用“c:\\folder\\test.txt”。
由于文件样式是wb,我们正筹备写入二进制文件。假如文件不存在则系统会建设一个文件,假如存在,则内里的内容城市被删除。假如挪用fopen失败了,或者由于文件被打开了,可能其名称包罗无效字符又可能一个无效路径那么fopen会返回0值。
固然你可以只查抄ft是否为0(值为0则乐成),可是笔者照旧添加了一个FileSuccess()函数来确保这一操纵。在窗口中,它会显示挪用是否乐成以及文件名称。假如你失败了则大概需要修复。留意在Windows中一般没有几多输出文本可供系统调试器利用,
#p#分页标题#e#
fwrite(mytext,sizeof(char),strlen(mytext), ft) ; fwrite()挪用输出了指定文本。第二,三个参数别离是字符的巨细和字符串的长度。它们两个都是被size_t界说了。留意有了二进制文件后,即便你正在向文件中写入(char*)字符串,它也没有任何附加换行字符。假如你想要这些字符,你必需明晰将这些字符包括到字符串中。
读写文件
打开一个文件的时候,必需指定打开的方法。这意味着假如你规划要为文件附加对象,那么是否要建设新文件并对其举办包围?它是文本文件照旧二进制文件呢?是要读取文件照旧要写文件呢?这样要通过利用一个或更多的文件模式分类符来完成,文件模式分类符是一些单独的字母“r”,“b”,“w”,“a”和+。“r”意思是打开文件以便读取。假如文件不存在或找不到文件这一操纵会失败。“w”意思是待写方法或空文件方法打开文件。假如文件存在,则文件内容会被损坏。“a”暗示打开文件,并筹备从文件结尾写入而不需要在写入新数据前删除EOF标志;假如不存在该文件则首先会建设一个文件。向文件模子添加+会建设下列三种新模子:
“r+”打开文件期待读取或写入。“w+”以空文件方法打开文件期待读取或写入。假如文件存在,则文件内容会被损毁。
“a+”打开文件期待读取或添加,添加的操纵包罗新数据写入前EOF标志的移除,以及写入完成后EOF标志的生存,假如文件不存在则先要建设文件。
下面的列表显示了字码组合包罗文本的和二进制文件的。凡是你可以选择从文本文件中读取或写入文件,可是不要两者同时利用。
就二进制文件而言,你可以选择对沟通文件举办读取和写入的操纵。列表汇报了我们可以用字码举办哪些操纵。
Mode Type of file Read Write Create Truncate
r text Read
rb+ binary Read
r+ text Read Write
r+b binary Read Write
rb+ binary Read Write
w text Write Create Truncate
wb binary Write Create Truncate
w+ text Read Write Create Truncate
w+b binary Read Write Create Truncate
wb+ binary Read Write Create Truncate
a text Write Create
ab binary Write Create
a+ text Read Write Create
a+b binary Write Create
ab+ binary Write Create
就笔者的履向来看,除非你方才建设完文件或读取完文件,不然你通过利用“w+b”只能荣幸乐成。
尚有一些环境答允其他字母存在。譬喻微软运行“t”代表文本模式,“c”用于承认,“n”用于非承认,“S”为顺序存取优化缓冲,“R”代表随机存取,“T”代表姑且性而“D”用于 删除/姑且性生存。
利用二进制文件的主要原因是可以得到机动性;你可以读取或写入文件的任意部门。文本文件只能让你凭据顺序读取或写入。此刻跟着SQLite或MySQL数据库的普及,在二进制文件中利用随机存取的需要淘汰了。从某种意义上说,随机存取文件记录有点老土了,可是仍然照旧有用的。
笔者在数据库普及之前就利用过基于随机存取文件的多种数据处理惩罚方案。譬喻,在小文件中,笔者利用的是 索引/数据 文件模式。该模式包罗两个文件。一个是数据文件,它生存了一些是非纷歧的记录。另一种文件是索引文件,这样的文件拥有同样的记录作为数据文件。可是在索引文件中每个记录的长度沟通并且都由两个适合布局的部门构成。
struct {??fpos_t pos;??int size; } indexrec;
范例fpos_t是由fsetpos()和fgetpos()界说和利用的执行。这些是fseek和ftell更新的版本且更有助于建设书签。假如你正在计较文件闻之且需要设定文件那么你应该利用fseek(),别的ftell()也可以给你int的当前位置。
在实际操纵中,fpos_t大概只是一个int可是你应该利用fpos_t范例。它生存了当前文件指示器的副本。这是随机存取文件的属性,它表白了下一次读取或写入的位置。它的粒度为一,因此你可以将其放在文件的任意位置。