初探ifstream与回车换行及类型匹配等几个问题
来源:http://blog.csdn.net/shellching/archive/2009/08/12/4438099.aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | #include <iostream> #include<fstream> using namespace std; /*本例: 1、练习ifstream、ofstream读写文件基本方法; 2、验证回车换行符号在文件读写中的状态和作用; 3、验证几种判断文件末尾的方法; 4、验证几种解决ifstream对读入类型不匹配数据的处理方法 回车与换行符: 字符 名称 ASCII值 控制字符 '\n' 换行(New line) 010 LF (Line Feed) '\r' 回车(Carriage return) 013 CR (Carriage Return) 杨小进 0:31 2009-8-12 */ //创建输入文件,为练习准备 void createFile( char *fname) { ofstream ofs(fname); ofs << "aaaaa\n" ; ofs << "bbbbb\n" ; ofs << "11111\n" ; ofs << "22222\n" ; ofs.close(); } //获取文件长度字节,会得到比输入更多的字节,因为 \n 被转换为 \r\n int getFileLen( char *fname) { ifstream ifs(fname); ifs.seekg(0, ios::end); //移动文件指针到末尾 int n = ifs.tellg(); //获取文件长度字节 ifs.seekg(ios::beg); //恢复指针到开始,对于接下来继续读有用 ifs.close(); return n; } //用read函数文本模式下读取文件,读到字节数小于真实文件大小, //因为系统读 \r\n 时又转换为 \n, 只是\n被读进来了 //若是binary模式,则会读到实际文件大小的字节 void readFileRead( char *fname, ios_base::openmode om = ios_base::in) { int n = getFileLen(fname); ifstream ifs(fname, om); char *pc = new char [n+1]; memset (pc, 0, sizeof ( char )*(n+1) ); ifs.read(pc, n); if (om & ios_base::binary) { cout << " binary模式" ; } cout << " read()读取了" << ifs.gcount() << "字节:\n" ; cout << pc; delete pc; ifs.close(); } //使用流提取符号读取文件,不管是何种模式,空白字符都会被 >> 略过 void readFileExtranction( char *fname) { ifstream ifs(fname, ios_base::binary); char c; cout << "binary模式 >>读取:\n" ; while (!ifs.eof()) { ifs >> c; cout << c << "_" ; } ifs.close(); } //使用Get在文本模式下读取文件内容,对于"\r\n"多跳过一个字符只读进'\n',指针移到'\n'后 //若在binary模式则是按照真实数据读取'\r','\n'; void readFileGet( char *fname, ios_base::openmode om = ios_base::in) { ifstream ifs(fname, om); char c; if (om & ios_base::binary) { cout << " binary模式" ; } cout << " get()从第5字节开始读取3个字符:\n十进制:" ; ifs.seekg(4, ios::beg); ifs.get(c); //读取第5字节,为'a' cout << int (c) << "_" ; ifs.get(c); //读取下一个字节应为13 = '\r',实际读进10 = '\n' cout << int (c) << "_" ; //若在binary模式下则是13 ='\r' ifs.get(c); //读取下一个字节,为'b',若是binary则是10='\n' cout << int (c) << "_" ; ifs.close(); } //使用Peek读取文件内容,文本模式下对于"\r\n"读进'\n'; //在binary模式下,对于"\r\n"则会读进'\r',peek始终都不会移动文件指针 void readFilePeek( char *fname, ios_base::openmode om = ios_base::in) { ifstream ifs(fname, om); //ifstream ifs3("input.txt", ios_base::binary); char c; if (om & ios_base::binary) { cout << " binary模式" ; } cout << " peek()读取第6、7、8字节:\n" ; ifs.seekg(5, ios::beg); c = ifs.peek(); //读取第6字节应为13 = '\r',实际上读进10 ='\n' cout << int (c) << "_" ; //若在binary模式则是13 ='\r' ifs.seekg(6, ios::beg); c = ifs.peek(); //读取第7字节,为10 ='\n' cout << int (c) << "_" ; ifs.seekg(7, ios::beg); c = ifs.peek(); //读取第8字节,为'b' cout << int (c) << "_" ; ifs.close(); } //通过eof()判断文件结束,若某行只有回车也算是一行,即使在文件尾部 void getOverEof( char *fname) { ifstream ifs(fname); string str; int i = 0; cout << " eof()判断文件结束" ; while (!ifs.eof()) { getline(ifs, str); cout << "\n第" << ++i << "行长度 " << str.length() << " : " << str; } ifs.close(); } //通过good()判断文件结束,同eof,若某行只有回车也算是一行,即使在文件尾部 //因为使用了binary模式,所以getline比平时多读入一个字符'\r',忽略'\n' void getOverGood( char *fname) { ifstream ifs(fname, ios_base::binary); int i = 0; string str; cout << " binary模式 good()判断文件结束" ; while (ifs.good()) { getline(ifs, str); cout << "\n第" << ++i << "行长度 " << str.length() << " : " << str; cout << " 第6字节" << int (str[5]); } ifs.close(); } //通过getline()判断文件结束,只有回车且在文件末尾的空行不算一行 void getOverGetline( char *fname) { ifstream ifs( "input.txt" ); int i = 0; string str; cout << " getline()判断文件结束" ; while (getline(ifs, str)) { cout << "\n第" << ++i << "行长度 " << str.length() << " : " << str; } ifs.close(); } //使用ifstream的提取符号从文本文件读入某种类型数据例如float或double时, //若遇到字符串或其它非数字符号会发生错误,造成死循环,所以需要特别处理 bool readErr( char *fname) { cout << "不匹配数据类型处理:" ; ifstream ifs(fname); if ( !ifs ) { cout << "\n打开文件 " << fname << " 失败\n" ; return false ; } int count=0; int dVal, sum=0; while ( !ifs.eof() ) { ifs >> dVal; if (ifs.fail()) //错误判断,使用"!ifs"也可以,但是"ifs.bad()"不行 { ifs.clear(); //清楚错误标志 ifs.ignore(1); //忽略当前非预期字符 continue ; //继续读取下一个 } else { cout << "\n第 " << ++count << "个数: " << dVal; sum += dVal; } } ifs.close(); cout << "\n总共 " << count << " 个数," << " 和为" << sum << endl; return true ; } int main() { char fname[] = "input.txt" ; createFile(fname); cout << "文件长度:" << getFileLen(fname) << " 字节" ; cout << "\n-----------------------" ; readFileRead(fname); cout << "\n-----------------------" ; readFileRead(fname, ios_base::binary); cout << "\n-----------------------" ; readFileExtranction(fname); cout << "\n-----------------------" ; readFileGet(fname); cout << "\n-----------------------" ; readFileGet(fname, ios_base::binary); cout << "\n-----------------------" ; readFilePeek(fname); cout << "\n-----------------------" ; readFilePeek(fname, ios_base::binary); cout << "\n-----------------------" ; getOverEof(fname); cout << "\n-----------------------" ; getOverGood(fname); cout << "\n-----------------------" ; getOverGetline(fname); /* 总结:windows系统中使用ofstream写文本文件时系统会把'\n'转换为'\n''\r'两个字符写入文件; 若是单写入'\r'则不会做上述转换;通常读取时会相应把'\n''\r'两个字符转换为'\n'; 对于文本中单独的'\n'和'\r'读取时不会作特别转换,作为一个字符读出; 使用流输入符号">>"读取字符时,无论使用何种模式打开文件,都会忽略空白字符\n\r等; 使用get和peek读取时,若在文本模式下,对于文本中的"\r\n"只是作为一个字符'\n'对待; get和peek,若在二进制模式下,对于文本中的"\r\n"作为两个字符对待; getline在文本模式下忽略"\r\n",但是在binary模式下会忽略'\n',而不会忽略'\r'; */ cout << "\n-----------------------" ; readErr(fname); cout << endl; return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架