﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-*尘埃之地-文章分类-转载  </title><link>http://www.cppblog.com/lazz/category/9544.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 11 Mar 2009 07:35:05 GMT</lastBuildDate><pubDate>Wed, 11 Mar 2009 07:35:05 GMT</pubDate><ttl>60</ttl><item><title>用标准c++进行string与各种内置数据类型的转换</title><link>http://www.cppblog.com/lazz/articles/73683.html</link><dc:creator>蓝尘</dc:creator><author>蓝尘</author><pubDate>Thu, 12 Feb 2009 19:16:00 GMT</pubDate><guid>http://www.cppblog.com/lazz/articles/73683.html</guid><description><![CDATA[<h2>用标准c++进行string与各种内置数据类型的转换</h2>
要实现这个目标，非<font size="2"><strong> stringstream</strong> 类莫属。这个类在&lt;sstream&gt;头文件中定义， &lt;sstream&gt;库定义了三种类：istringstream、ostringstream和stringstream，分别用来进行流的输入、输出和输入输出操作。另外，每个类都有一个对应的宽字符集版本。简单起见，我主要以stringstream为中心，因为每个转换都要涉及到输入和输出操作。示例1示范怎样使用一个stringstream对象进行从<br>
<strong> string到int类型的转换</strong> <br>
注意，&lt;sstream&gt;使用string对象来代替字符数组。这样可以避免缓冲区溢出的危险。而且，传入参数和目标对象的类型被自动推导出来，即使使用了不正确的格式化符也没有危险。<br>
示例1：<br>
std::stringstream stream;<br>
string result="10000";<br>
int n = 0;<br>
stream &lt;&lt; result;<br>
stream &gt;&gt; n;//n等于10000<br>
<strong> int到string类型的转换</strong> <br>
string result;<br>
int n = 12345;<br>
stream &lt;&lt; n;<br>
result =stream.str();// result等于"12345"<br>
<strong> 重复利用stringstream对象</strong> <br>
如果你打算在多次转换中使用同一个stringstream对象，记住再每次转换前要使用clear()方法，在多次转换中重复使用同一个stringstream（而不是每次都创建一个新的对象）对象最大的好处在于效率。stringstream对象的构造和析构函数通常是非常耗费CPU时间的。经试验，单单使用clear()并不能清除stringstream对象的内容，仅仅是了该对象的状态，要重复使用同一个stringstream对象,需要使用str()重新初始化该对象。<br>
示例2：<br>
std::stringstream strsql;<br>
for (int i= 1; i &lt; 10; ++i)<br>
{ <br>
&nbsp;&nbsp;strsql &lt;&lt; "insert into test_tab&nbsp;&nbsp;values(";<br>
&nbsp;&nbsp;strsql&nbsp;&nbsp;&lt;&lt; i &lt;&lt; ","&lt;&lt; (i+10) &lt;&lt; ");";<br>
&nbsp;&nbsp;std::string str = strsql.str(); // 得到string<br>
&nbsp;&nbsp;res = sqlite3_exec(pDB,str.c_str(),0,0, &amp;errMsg);<br>
&nbsp;&nbsp;std::cout &lt;&lt; strsql.str() &lt;&lt; std::endl;<br>
&nbsp;&nbsp;strsql.clear();<br>
&nbsp;&nbsp;strsql.str("");<br>
}<br>
<strong> 转换中使用模板</strong> <br>
也可以轻松地定义函数模板来将一个任意的类型转换到特定的目标类型。例如，需要将各种数字值，如int、long、double等等转换成字符串，要使用以一个string类型和一个任意值<em> t</em> 为参数的to_string()函数。to_string()函数将<em> t</em> 转换为字符串并写入result中。使用str()成员函数来获取流内部缓冲的一份拷贝：<br>
示例3：<br>
template&lt;class T&gt;<br>
void to_string(string &amp; result,const T&amp; t)<br>
{<br>
ostringstream oss;//创建一个流<br>
oss&lt;&lt;t;//把值传递如流中<br>
result=oss.str();//获取转换后的字符转并将其写入result<br>
}<br>
这样，你就和衣轻松地将多种数值转换成字符串了：<br>
to_string(s1,10.5);//double到string<br>
to_string(s2,123);//int到string<br>
to_string(s3,true);//bool到string<br>
可以更进一步定义一个通用的转换模板，用于任意类型之间的转换。函数模板convert()含有两个模板参数out_type和in_value，功能是将in_value值转换成out_type类型：<br>
template&lt;class out_type,class in_value&gt;<br>
out_type convert(const in_value &amp; t)<br>
{<br>
stringstream stream;<br>
stream&lt;&lt;t;//向流中传值<br>
out_type result;//这里存储转换结果<br>
stream&gt;&gt;result;//向result中写入值<br>
return result;<br>
}<br>
这样使用convert()：<br>
double d;<br>
string salary;<br>
string s=&#8221;12.56&#8221;;<br>
d=convert&lt;double&gt;(s);//d等于12.56<br>
salary=convert&lt;string&gt;(9000.0);//salary等于&#8221;9000&#8221;<br>
<strong> 结论</strong>  <br>
<br>
在过去留下来的程序代码和纯粹的C程序中，传统的&lt;stdio.h&gt;形式的转换伴随了我们很长的一段时间。但是，如文中所述，基于stringstream的转换拥有类型安全和不会溢出这样抢眼的特性，使我们有充足得理由抛弃&lt;stdio.h&gt;而使用&lt;sstream&gt;。<br>
当然现在还有一个更好的选择，那就是使用boost库中的lexical_cast,它是类型安全的转换。如下例：<br>
#include &lt;iostream&gt;<br>
<br>
#include &lt;sstream&gt;<br>
#include &lt;string&gt;<br>
#include &lt;cstdlib&gt;<br>
#include &lt;boost/lexical_cast.hpp&gt;<br>
using namespace std;<br>
using namespace boost;<br>
int main(void)<br>
try{<br>
<br>
//<font face="宋体 ">以下是内置类型向</font>string<font face="宋体 ">转换的解决方案</font> <br>
<br>
//lexical_cast<font face="宋体 ">优势明显</font> <br>
<br>
int ival;<br>
<br>
char cval;<br>
<br>
ostringstream out_string;<br>
<br>
string str0;<br>
<br>
string str1;<br>
<br>
<br>
<br>
ival = 100;<br>
<br>
cval = 'w';<br>
<br>
out_string &lt;&lt; ival &lt;&lt; " " &lt;&lt; cval; <br>
<br>
str0 = out_string.str();<br>
<br>
str1 = lexical_cast&lt;string&gt;(ival) <br>
<br>
<br>
+ lexical_cast&lt;string&gt;(cval);<br>
<br>
cout &lt;&lt; str0 &lt;&lt; endl;<br>
<br>
cout &lt;&lt; str1 &lt;&lt; endl;<br>
<br>
<br>
//<font face="宋体 ">以下是</font>string<font face="宋体 ">向内置类型转换的解决方案</font> <br>
<br>
//<font face="宋体 ">几乎和</font>stringstrem<font face="宋体 ">相比，lexical_cast就是类型安全的，</font><br>
<br>
int itmpe;<br>
<br>
char ctmpe;<br>
<br>
str0 = "100k"; <br>
<br>
str1 = "100h";<br>
<br>
istringstream in_string( str0 );<br>
<br>
in_string &gt;&gt; itmpe &gt;&gt; ctmpe;<br>
<br>
cout &lt;&lt; itmpe &lt;&lt; " " &lt;&lt; ctmpe &lt;&lt; endl;<br>
<br>
<br>
itmpe = lexical_cast&lt;int&gt;(str1);<br>
<br>
<br>
ctmpe = lexical_cast&lt;char&gt;(str1);<br>
<br>
system( "PAUSE" );<br>
<br>
return 0;<br>
}<br>
catch(bad_lexical_cast e)<br>
{<br>
<br>
cout &lt;&lt; e.what() &lt;&lt; endl;<br>
<br>
cin.get();<br>
}</font>
<br> <img src ="http://www.cppblog.com/lazz/aggbug/73683.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lazz/" target="_blank">蓝尘</a> 2009-02-13 03:16 <a href="http://www.cppblog.com/lazz/articles/73683.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++文件操作</title><link>http://www.cppblog.com/lazz/articles/73682.html</link><dc:creator>蓝尘</dc:creator><author>蓝尘</author><pubDate>Thu, 12 Feb 2009 19:11:00 GMT</pubDate><guid>http://www.cppblog.com/lazz/articles/73682.html</guid><description><![CDATA[<p>&nbsp;原文地址：http://www.layz.net/blog/user1/xuanxuan/archives/2006/67.html<br>
&nbsp;在C++中，有一个stream这个类，所有的I/O都以这个&#8220;流&#8221;类为基础的，包括我们要认识的文件I/O，stream这个类有两个重要的运算符： <br>
<br>
1、插入器(&lt;&lt;) <br>
向流输出数据。比如说系统有一个默认的标准输出流(cout)，一般情况下就是指的显示器，所以，cout&lt;&lt;"Write
Stdout"&lt;&lt;'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。 <br>
<br>
2、析取器(&gt;&gt;) <br>
从流中输入数据。比如说系统有一个默认的标准输入流(cin)，一般情况下就是指的键盘，所以，cin&gt;&gt;x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。 <br>
<br>
在C++中，对文件的操作是通过stream的子类fstream(file stream)来实现的，所以，要用这种方式操作文件，就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。 <br>
<br>
一、打开文件 <br>
在fstream类中，有一个成员函数open()，就是用来打开文件的，其原型是： <br>
<br>
void open(const char* filename,int mode,int access); <br>
<br>
参数： <br>
<br>
filename：　　要打开的文件名 <br>
mode：　　　　要打开文件的方式 <br>
access：　　　打开文件的属性 <br>
打开文件的方式在类ios(是所有流式I/O类的基类)中定义，常用的值如下： <br>
<br>
ios::app：　　　以追加的方式打开文件 <br>
ios::ate：　　　文件打开后定位到文件尾，ios:app就包含有此属性 <br>
ios::binary： 　以二进制方式打开文件，缺省的方式是文本方式。两种方式的区别见前文 <br>
ios::in：　　　 文件以输入方式打开 <br>
ios::out：　　　文件以输出方式打开 <br>
ios::nocreate： 不建立文件，所以文件不存在时打开失败　 <br>
ios::noreplace：不覆盖文件，所以打开文件时如果文件存在失败 <br>
ios::trunc：　　如果文件存在，把文件长度设为0 <br>
可以用&#8220;或&#8221;把以上属性连接起来，如ios::out|ios::binary <br>
<br>
打开文件的属性取值是： <br>
<br>
0：普通文件，打开访问 <br>
1：只读文件 <br>
2：隐含文件 <br>
4：系统文件 <br>
可以用&#8220;或&#8221;或者&#8220;+&#8221;把以上属性连接起来 ，如3或1|2就是以只读和隐含属性打开文件。 <br>
<br>
例如：以二进制输入方式打开文件c:\config.sys <br>
<br>
fstream file1; <br>
file1.open("c:\\config.sys",ios::binary|ios::in,0); <br>
<br>
如果open函数只有文件名一个参数，则是以读/写普通文件打开，即： <br>
<br>
file1.open("c:\\config.sys");&lt;=&gt;file1.open("c:\\config.sys",ios::in|ios::out,0); <br>
<br>
另外，fstream还有和open()一样的构造函数，对于上例，在定义的时侯就可以打开文件了： <br>
<br>
fstream file1("c:\\config.sys"); <br>
<br>
特别提出的是，fstream有两个子类：ifstream(input file stream)和ofstream(outpu file stream)，ifstream默认以输入方式打开文件，而ofstream默认以输出方式打开文件。 <br>
<br>
ifstream file2("c:\\pdos.def");//以输入方式打开文件 <br>
ofstream file3("c:\\x.123");//以输出方式打开文件 <br>
<br>
所以，在实际应用中，根据需要的不同，选择不同的类来定义：如果想以输入方式打开，就用ifstream来定义；如果想以输出方式打开，就用ofstream来定义；如果想以输入/输出方式来打开，就用fstream来定义。 <br>
<br>
二、关闭文件 <br>
打开的文件使用完成后一定要关闭，fstream提供了成员函数close()来完成此操作，如：file1.close();就把file1相连的文件关闭。 <br>
<br>
三、读写文件 <br>
读写文件分为文本文件和二进制文件的读取，对于文本文件的读取比较简单，用插入器和析取器就可以了；而对于二进制的读取就要复杂些，下要就详细的介绍这两种方式 <br>
<br>
1、文本文件的读写 <br>
文本文件的读写很简单：用插入器(&lt;&lt;)向文件输出；用析取器(&gt;&gt;)从文件输入。假设file1是以输入方式打开，file2以输出打开。示例如下： <br>
<br>
file2&lt;&lt;"I Love You";//向文件写入字符串"I Love You" <br>
int i; <br>
file1&gt;&gt;i;//从文件输入一个整数值。 <br>
<br>
这种方式还有一种简单的格式化能力，比如可以指定输出为16进制等等，具体的格式有以下一些 <br>
<br>
操纵符 功能 输入/输出 <br>
dec 格式化为十进制数值数据 输入和输出 <br>
endl 输出一个换行符并刷新此流 输出 <br>
ends 输出一个空字符 输出 <br>
hex 格式化为十六进制数值数据 输入和输出 <br>
oct 格式化为八进制数值数据 输入和输出 <br>
setpxecision(int p) 设置浮点数的精度位数 输出 <br>
<br>
比如要把123当作十六进制输出：file1&lt;&lt;&lt;123;要把3.1415926以5位精度输出：FILE1&lt;<setpxecision(5)>&lt;&lt;3.1415926。 <br>
<br>
2、二进制文件的读写 <br>
①put() <br>
put()函数向流写入一个字符，其原型是ofstream &amp;put(char ch)，使用也比较简单，如file1.put('c');就是向流写一个字符'c'。 <br>
<br>
②get() <br>
get()函数比较灵活，有3种常用的重载形式： <br>
<br>
一种就是和put()对应的形式：ifstream &amp;get(char &amp;ch);功能是从流中读取一个字符，结果保存在引用ch中，如果到文件尾，返回空字符。如file2.get(x);表示从文件中读取一个字符，并把读取的字符保存在x中。 <br>
<br>
另一种重载形式的原型是： int get();这种形式是从流中返回一个字符，如果到达文件尾，返回EOF，如x=file2.get();和上例功能是一样的。 <br>
<br>
还有一种形式的原型是：ifstream &amp;get(char *buf,int num,char
delim='\n')；这种形式把字符读入由 buf 指向的数组，直到读入了 num 个字符或遇到了由 delim 指定的字符，如果没使用
delim 这个参数，将使用缺省值换行符'\n'。例如： <br>
<br>
file2.get(str1,127,'A');//从文件中读取字符到字符串str1，当遇到字符'A'或读取了127个字符时终止。 <br>
<br>
③读写数据块 <br>
要读写二进制数据块，使用成员函数read()和write()成员函数，它们原型如下： <br>
<br>
read(unsigned char *buf,int num); <br>
write(const unsigned char *buf,int num); <br>
<br>
read()从文件中读取 num 个字符到 buf 指向的缓存中，如果在还未读入 num 个字符时就到了文件尾，可以用成员函数 int
gcount();来取得实际读取的字符数；而 write() 从buf 指向的缓存写 num 个字符到文件中，值得注意的是缓存的类型是
unsigned char *，有时可能需要类型转换。 <br>
<br>
例： <br>
<br>
unsigned char str1[]="I Love You"; <br>
int n[5]; <br>
ifstream in("xxx.xxx"); <br>
ofstream out("yyy.yyy"); <br>
out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中 <br>
in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数，注意类型转换 <br>
in.close();out.close(); <br>
<br>
四、检测EOF <br>
成员函数eof()用来检测是否到达文件尾，如果到达文件尾返回非0值，否则返回0。原型是int eof(); <br>
<br>
例：　　if(in.eof())ShowMessage("已经到达文件尾！"); <br>
<br>
五、文件定位 <br>
和C的文件操作方式不同的是，C++
I/O系统管理两个与一个文件相联系的指针。一个是读指针，它说明输入操作在文件中的位置；另一个是写指针，它下次写操作的位置。每次执行输入或输出时，
相应的指针自动变化。所以，C++的文件定位分为读位置和写位置的定位，对应的成员函数是 seekg()和
seekp()，seekg()是设置读位置，seekp是设置写位置。它们最通用的形式如下： <br>
<br>
istream &amp;seekg(streamoff offset,seek_dir origin); <br>
ostream &amp;seekp(streamoff offset,seek_dir origin); <br>
<br>
streamoff定义于 iostream.h 中，定义有偏移量 offset 所能取得的最大值，seek_dir 表示移动的基准位置，是一个有以下值的枚举： <br>
<br>
ios::beg：　　文件开头 <br>
ios::cur：　　文件当前位置 <br>
ios::end：　　文件结尾 <br>
这两个函数一般用于二进制文件，因为文本文件会因为系统对字符的解释而可能与预想的值不同。 <br>
<br>
例： <br>
<br>
file1.seekg(1234,ios::cur);//把文件的读指针从当前位置向后移1234个字节 <br>
file2.seekp(1234,ios::beg);//把文件的写指针从文件开头向后移1234个字节</setpxecision(5)></p>
<p>&nbsp;</p>
<p><font face="Verdana"><span style="background-color: yellow;"><font style="background-color: #ffffff; color: #ff0000;" face="Verdana"><span style="background-color: yellow;"><font face="Verdana"><font style="background-color: #ffffff; font-family: tahoma; font-size: 18pt;" face="Verdana"><strong>基于C的文件操作</strong> </font></font></span><br>
</font></span>　　在ANSI C中，对文件的操作分为两种方式，即流式文件操作和I/O文件操作，下面就分别介绍之。</font></p>
<p><font face="Verdana">一、流式文件操作<br>
这种方式的文件操作有一个重要的结构FILE，FILE在stdio.h中定义如下：</font></p>
<p><font face="Verdana">typedef struct {<br>
int level; /* fill/empty level of buffer */<br>
unsigned flags; /* File status flags */<br>
char fd; /* File descriptor */<br>
unsigned char hold; /* Ungetc char if no buffer */<br>
int bsize; /* Buffer size */<br>
unsigned char _FAR *buffer; /* Data transfer buffer */<br>
unsigned char _FAR *curp; /* Current active pointer */<br>
unsigned istemp; /* Temporary file indicator */<br>
short token; /* Used for validity checking */<br>
} FILE; /* This is the FILE object */</font></p>
<p><font face="Verdana">　　FILE这个结构包含了文件操作的基本属性，对文件的操作都要通过这个结构的指针来进行，此种文件操作常用的函数见下表 函数 功能 <br>
fopen() 打开流 <br>
fclose() 关闭流 <br>
fputc() 写一个字符到流中 <br>
fgetc() 从流中读一个字符 <br>
fseek() 在流中定位到指定的字符 <br>
fputs() 写字符串到流 <br>
fgets() 从流中读一行或指定个字符 <br>
fprintf() 按格式输出到流 <br>
fscanf() 从流中按格式读取 <br>
feof() 到达文件尾时返回真值 <br>
ferror() 发生错误时返回其值 <br>
rewind() 复位文件定位器到文件开始处 <br>
remove() 删除文件 <br>
fread() 从流中读指定个数的字符 <br>
fwrite() 向流中写指定个数的字符 <br>
tmpfile() 生成一个临时文件流 <br>
tmpnam() 生成一个唯一的文件名 </font></p>
<font face="Verdana">
</font>
<p><font face="Verdana"><br>
下面就介绍一下这些函数</font></p>
<p><font face="Verdana">1.fopen()<br>
fopen的原型是：FILE *fopen(const char *filename,const char *mode)，fopen实现三个功能</font></p>
<p><font face="Verdana">为使用而打开一个流 <br>
把一个文件和此流相连接 <br>
给此流返回一个FILR指针<br>
参数filename指向要打开的文件名，mode表示打开状态的字符串，其取值如下表</font></p>
<p><font face="Verdana">字符串 含义 <br>
"r" 以只读方式打开文件 <br>
"w" 以只写方式打开文件 <br>
"a" 以追加方式打开文件 <br>
"r+" 以读/写方式打开文件，如无文件出错 <br>
"w+" 以读/写方式打开文件，如无文件生成新文件 </font></p>
<p><font face="Verdana">　　一个文件可以以文本模式或二进制模式打开，这两种的区别是：在文本模式中回车被当成一个字符
''\n''，而二进制模式认为它是两个字符0x0D,0x0A；如果在文件中读到0x1B，文本模式会认为这是文件结束符，也就是二进制模型不会对文件
进行处理，而文本方式会按一定的方式对数据作相应的转换。</font></p>
<p><font face="Verdana">　　系统默认的是以文本模式打开，可以修改全部变量_fmode的值来修改这个设置，例如_fmode=O_TEXT；就设置默认打开方式为文本模式；而_fmode=O_BINARY；则设置默认打开方式是二进制模式。</font></p>
<p><font face="Verdana">　　我们也可以在模式字符串中指定打开的模式，如"rb"表示以二进制模式打开只读文件，"w+t"或"wt+"表示以文本模式打开读/写文件。</font></p>
<p><font face="Verdana">　　此函数返回一个FILE指针，所以申明一个FILE指针后不用初始化，而是用fopen()来返回一个指针并与一个特定的文件相连，如果成败，返回NULL。</font></p>
<p><font face="Verdana">例:</font></p>
<p><font face="Verdana">　　FILE *fp; <br>
if(fp=fopen("123.456","wb"))<br>
puts("打开文件成功");<br>
else <br>
puts("打开文件成败"); </font></p>
<p><font face="Verdana">2.fclose() <br>
fclose()的功能就是关闭用fopen()打开的文件，其原型是：int fclose(FILE *fp);如果成功，返回0,失败返回EOF。</font></p>
<p><font face="Verdana">　　在程序结束时一定要记得关闭打开的文件，不然可能会造成数据丢失的情况，我以前就经常犯这样的毛病。</font></p>
<p><font face="Verdana">例：fclose(fp);</font></p>
<p><font face="Verdana">3.fputc()<br>
向流写一个字符，原型是int fputc(int c, FILE *stream); 成功返回这个字符,失败返回EOF。</font></p>
<p><font face="Verdana">例：fputc(''X'',fp);</font></p>
<p><font face="Verdana">4.fgetc()<br>
从流中读一个字符，原型是int fputc(FILE *stream); 成功返回这个字符,失败返回EOF。</font></p>
<p><font face="Verdana">例：char ch1=fgetc(fp);</font></p>
<p><font face="Verdana">5. fseek()<br>
此函数一般用于二进制模式打开的文件中，功能是定位到流中指定的位置，原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0，参数offset是移动的字符数，whence是移动的基准，取值是</font></p>
<p><font face="Verdana">符号常量 值 基准位置 <br>
SEEK_SET 0 文件开头 <br>
SEEK_CUR 1 当前读写的位置 <br>
SEEK_END 2 文件尾部 </font></p>
<p><font face="Verdana">例：fseek(fp,1234L,SEEK_CUR);//把读写位置从当前位置向后移动1234字节(L后缀表示长整数)</font></p>
<p><font face="Verdana">　　fseek(fp,0L,2);//把读写位置移动到文件尾</font></p>
<p><font face="Verdana">6.fputs()<br>
写一个字符串到流中，原型int fputs(const char *s, FILE *stream); </font></p>
<p><font face="Verdana">例：fputs("I Love You",fp);</font></p>
<p><font face="Verdana">7.fgets()<br>
从流中读一行或指定个字符，原型是char *fgets(char *s, int n, FILE *stream); 从流中读取n-1个字符，除非读完一行，参数s是来接收字符串，如果成功则返回s的指针，否则返回NULL。</font></p>
<p><font face="Verdana">例：如果一个文件的当前位置的文本如下</font></p>
<p><font face="Verdana">Love ,I Have</font></p>
<p><font face="Verdana">But &#8230;&#8230;..</font></p>
<p><font face="Verdana">如果用</font></p>
<p><font face="Verdana">　　fgets(str1,4,file1);</font></p>
<p><font face="Verdana">则执行后str1="Lov"，读取了4-1=3个字符，而如果用</font></p>
<p><font face="Verdana">　　fgets(str1,23,file1);</font></p>
<p><font face="Verdana">则执行str="Love ,I Have"，读取了一行(不包括行尾的''\n'')。</font></p>
<p><font face="Verdana">8.fprintf()<br>
按格式输入到流，其原型是int fprintf(FILE *stream, const char *format[, argument, &#8230;]);其用法和printf()相同，不过不是写到控制台，而是写到流罢了</font></p>
<p><font face="Verdana">例：fprintf(fp,"%2d%s",4,"Hahaha");</font></p>
<p><font face="Verdana">9.fscanf()<br>
从流中按格式读取，其原型是int fscanf(FILE *stream, const char *format[, address, &#8230;]);其用法和scanf()相同，不过不是从控制台读取，而是从流读取罢了。</font></p>
<p><font face="Verdana">例：fscanf(fp,"%d%d" ,&amp;x,&amp;y);</font></p>
<p><font face="Verdana">10.feof()<br>
检测是否已到文件尾，是返回真，否则返回0，其原型是int feof(FILE *stream);</font></p>
<p><font face="Verdana">例：if(feof(fp))printf("已到文件尾");</font></p>
<p><font face="Verdana">11.ferror()<br>
原型是int ferror(FILE *stream);返回流最近的错误代码，可用clearerr()来清除它，clearerr()的原型是void clearerr(FILE *stream);</font></p>
<p><font face="Verdana">例：printf("%d",ferror(fp));</font></p>
<p><font face="Verdana">12.rewind()<br>
把当前的读写位置回到文件开始，原型是void rewind(FILE *stream);其实本函数相当于fseek(fp,0L,SEEK_SET);</font></p>
<p><font face="Verdana">例：rewind(fp);</font></p>
<p><font face="Verdana">12.remove()<br>
删除文件，原型是int remove(const char *filename); 参数就是要删除的文件名，成功返回0。</font></p>
<p><font face="Verdana">例：remove("c:\\io.sys");</font></p>
<p><font face="Verdana">13.fread()<br>
从流中读指定个数的字符，原型是size_t fread(void *ptr, size_t size, size_t n, FILE
*stream);参数ptr是保存读取的数据，void*的指针可用任何类型的指针来替换，如char*、int
*等等来替换；size是每块的字节数；n是读取的块数，如果成功，返回实际读取的块数(不是字节数)，本函数一般用于二进制模式打开的文件中。</font></p>
<p><font face="Verdana">例：</font></p>
<p><font face="Verdana">　　char x[4230];<br>
FILE *file1=fopen("c:\\msdos.sys","r");<br>
fread(x,200,12 ,file1);//共读取200*12=2400个字节</font></p>
<p><font face="Verdana">14.fwrite()<br>
与fread对应，向流中写指定的数据，原型是size_t fwrite(const void *ptr, size_t size,
size_t n, FILE *stream);参数ptr是要写入的数据指针，void*的指针可用任何类型的指针来替换，如char*、int
*等等来替换；size是每块的字节数；n是要写的块数，如果成功，返回实际写入的块数(不是字节数)，本函数一般用于二进制模式打开的文件中。</font></p>
<p><font face="Verdana">例：</font></p>
<p><font face="Verdana">　　char x[]="I Love You";<br>
fwire(x, 6,12,fp);//写入6*12=72字节</font></p>
<p><font face="Verdana">　　将把"I Love"写到流fp中12次，共72字节</font></p>
<p><font face="Verdana">15.tmpfile()<br>
其原型是FILE *tmpfile(void); 生成一个临时文件，以"w+b"的模式打开，并返回这个临时流的指针，如果失败返回NULL。在程序结束时，这个文件会被自动删除。</font></p>
<p><font face="Verdana">例：FILE *fp=tmpfile();</font></p>
<p><font face="Verdana">16.tmpnam();<br>
其原型为char *tmpnam(char *s); 生成一个唯一的文件名，其实tmpfile()就调用了此函数，参数s用来保存得到的文件名，并返回这个指针，如果失败，返回NULL。</font></p>
<p><font face="Verdana">例：tmpnam(str1);</font></p>
<font face="Verdana">
</font>
<p><font face="Verdana"><br>
二、直接I/O文件操作<br>
这是C提供的另一种文件操作，它是通过直接存/取文件来完成对文件的处理，而上篇所说流式文件操作是通过缓冲区来进行；流式文件操作是围绕一个
FILE指针来进行，而此类文件操作是围绕一个文件的&#8220;句柄&#8221;来进行，什么是句柄呢？它是一个整数，是系统用来标识一个文件(在WINDOWS中，句柄的
概念扩展到所有设备资源的标识)的唯一的记号。此类文件操作常用的函数如下表，这些函数及其所用的一些符号在io.h和fcntl.h中定义，在使用时要
加入相应的头文件。</font></p>
<p><font face="Verdana">函数 说明 <br>
open() 打开一个文件并返回它的句柄 <br>
close() 关闭一个句柄 <br>
lseek() 定位到文件的指定位置 <br>
read() 块读文件 <br>
write() 块写文件 <br>
eof() 测试文件是否结束 <br>
filelength() 取得文件长度 <br>
rename() 重命名文件 <br>
chsize() 改变文件长度 </font></p>
<p><font face="Verdana">　　下面就对这些函数一一说明：</font></p>
<p><font face="Verdana">1.open()<br>
打开一个文件并返回它的句柄，如果失败，将返回一个小于0的值，原型是int open(const char *path, int
access [, unsigned mode]);
参数path是要打开的文件名，access是打开的模式，mode是可选项。表示文件的属性，主要用于UNIX系统中，在DOS/WINDOWS这个参
数没有意义。其中文件的打开模式如下表。</font></p>
<p><font face="Verdana">符号 含义 符号 含义 符号 含义 <br>
O_RDONLY 只读方式 O_WRONLY 只写方式 O_RDWR 读/写方式 <br>
O_NDELAY 用于UNIX系统 O_APPEND 追加方式 O_CREAT 如果文件不存在就创建 <br>
O_TRUNC 把文件长度截为0 O_EXCL 和O_CREAT连用，如果文件存在返回错误 O_BINARY 二进制方式 <br>
O_TEXT 文本方式 </font></p>
<p><font face="Verdana">　　对于多个要求，可以用"|"运算符来连接，如O_APPEND|O_TEXT表示以文本模式和追加方式打开文件。</font></p>
<p><font face="Verdana">例：int handle=open("c:\\msdos.sys",O_BINARY|O_CREAT|O_WRITE)</font></p>
<p><font face="Verdana">2.close()<br>
关闭一个句柄，原型是int close(int handle);如果成功返回0</font></p>
<p><font face="Verdana">例：close(handle)</font></p>
<p><font face="Verdana">3.lseek()<br>
定位到指定的位置，原型是：long lseek(int handle, long offset, int
fromwhere);参数offset是移动的量，fromwhere是移动的基准位置，取值和前面讲的fseek()一样，SEEK_SET：文件首
部；SEEK_CUR：文件当前位置；SEEK_END：文件尾。此函数返回执行后文件新的存取位置。</font></p>
<p><font face="Verdana">例：</font></p>
<p><font face="Verdana">　　lseek(handle,-1234L,SEEK_CUR);//把存取位置从当前位置向前移动1234个字节。<br>
x=lseek(hnd1,0L,SEEK_END);//把存取位置移动到文件尾，x=文件尾的位置即文件长度</font></p>
<p><font face="Verdana">4.read()<br>
从文件读取一块，原型是int read(int handle, void *buf, unsigned len);参数buf保存读出的数据，len是读取的字节。函数返回实际读出的字节。</font></p>
<p><font face="Verdana">例：char x[200];read(hnd1,x,200);</font></p>
<p><font face="Verdana">5.write()<br>
写一块数据到文件中，原型是int write(int handle, void *buf, unsigned len);参数的含义同read()，返回实际写入的字节。</font></p>
<p><font face="Verdana">例：char x[]="I Love You";write(handle,x,strlen(x));</font></p>
<p><font face="Verdana">7.eof()<br>
类似feof()，测试文件是否结束，是返回1，否则返回0;原型是：int eof(int handle);</font></p>
<p><font face="Verdana">例：while(!eof(handle1)){&#8230;&#8230;};</font></p>
<p><font face="Verdana">8.filelength()<br>
返回文件长度，原型是long filelength(int handle);相当于lseek(handle,0L,SEEK_END)</font></p>
<p><font face="Verdana">例：long x=filelength(handle);</font></p>
<p><font face="Verdana">9.rename()<br>
重命名文件，原型是int rename(const char *oldname, const char *newname); 参数oldname是旧文件名，newname是新文件名。成功返回0</font></p>
<p><font face="Verdana">例：rename("c:\\config.sys","c:\\config.w40");</font></p>
<p><font face="Verdana">10.chsize();<br>
改变文件长度，原型是int chsize(int handle, long size);参数size表示文件新的长度，成功返回0，否则返回-1，如果指定的长度小于文件长度，则文件被截短；如果指定的长度大于文件长度，则在文件后面补''\0''。</font></p>
<p><font face="Verdana">例：chsize(handle,0x12345);</font></p>
<p><font face="Verdana"><br>
--------------------------------------------------------------------------------</font></p>
<p><font face="Verdana">　　如果熟悉汇编可能会发现这种方式和汇编语言的DOS功能调用句柄式文件操作很像，比如open()
就像DOS服务的3CH号功能调用，其实这种操作还有两种类型的函数就是直接用DOS功能来完成的，如_open()，_dos_open()等等。有兴
趣可自已查询BCB的帮助。</font></p>
<p><font face="Verdana">　　同流式文件操作相同，这种也提供了Unicode字符操作的函数，如_wopen()等等，用于9X/NT下的宽字符编程，有兴趣可自已查询BCB的帮助。</font></p>
<font face="Verdana">　　另外，此种操作还有lock(),unlock(),locking()等用于多用户操作的函数，但在BCB中用得并不多，我就不介绍了，但如果要用C来写CGI，这些就必要的常识了，如果你有这方面的要求，那就得自已好好看帮助了。</font> <img src ="http://www.cppblog.com/lazz/aggbug/73682.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lazz/" target="_blank">蓝尘</a> 2009-02-13 03:11 <a href="http://www.cppblog.com/lazz/articles/73682.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>