/*---------------------------------------------------------------------------------// FileFormatIO: Data file input and output formatting example(数据文件输入输出格式化示例)// Author(s): JoyPoint@qq.com// Copyright (c) 2021年01月01日// All rights reserved.// Release : FileFormatIO-v1.0.0//// to Compile:// g++ -Wall -std=c++17 simple.Cpp -o simple//// to Run: e.g.// ./simple.exe//// Reference: http://www.cplusplus.com/doc/tutorial/files/// C++ provides the following classes to perform output and input of characters to/from files:// ofstream: Stream class to write on files// ifstream: Stream class to read from files// fstream: Stream class to both read and write from/to files.// These classes are derived directly or indirectly from the classes istream and ostream.// these classes: cin is an object of class istream and cout is an object of class ostream.//---------------------------------------------------------------------------------*/#include <iostream> //include istream and ostream#include <fstream> //include ifstream and ofstream#include <iomanip> //include setiosflags setprecision setw#include <cstdlib> //include system("pause") system("chcp 65001")#include <stdexcept> //include std::runtime_error std::filesystem::filesystem_error#include <codecvt> //include codecvt_utf8_utf16#include <filesystem> //include path exists create_directory#include <cstring> //include strlen#include <string>#include <ctime>#include <cmath>#include <vector>/* Chinese system locale */#ifdef _MSC_VER#include <io.h>#include <fcntl.h>#else#include <locale>#include <clocale>#endif// using namespace std;// namespace fs = std::filesystem;int main(){// system("chcp 65001"); //控制台显示中文问题,可以在控制台输入chcp命令,查看和修改当前code page,GBK code=936,UTF-8 code=65001// msg:测试用字符串std::vector<std::string> msg {"Hello", "C++", "World", "from", "VS Code", "数据文件格式化输入输出测试!"};// testFilePath:测试用文件路径std::filesystem::path currentRootPath = std::filesystem::current_path();//获取当前路径pathstd::filesystem::path testFileDirectory; //测试文件目录路径名std::filesystem::path currentTestFileDir; //当前测试文件目录std::filesystem::path currentTestFilePath; //测试文件全路径std::string testFileDirString_UTF8 = "testFile中文路径"; //输入输出文件目录,格式:or ".\\testFile"std::u16string testFileDirString_UTF16; // 临时变量,用于将string转换为wstring path// testFile: 测试用输入输出文件,Txt:文本文件,Bin:二进制文件std::string testTxtFileString = "testTxtFile.txt";std::string testBinFileString = "testBinFile.bin";std::string testTxtFile = testFileDirString_UTF8 + "/" + testTxtFileString;std::string testBinFile = testFileDirString_UTF8 + "/" + testBinFileString;/*****路径检查Dir*****/// Reference: https://en.cppreference.com/w/cpp/filesystem/path/string#ifdef _MSC_VERDir_setmode(_fileno(stderr), _O_WTEXT);#else// replace the C++ global locale as well as the C locale with the user-preferred localestd::setlocale(LC_ALL, "");std::locale::global(std::locale(""));// use the new global locale for future wide character output// std::cout.imbue(std::locale());// std::wcerr.imbue(std::locale());#endif// std::filesystem::path testFilePath = std::filesystem::u8path(u8"./testFile中文路径"); //ok1// std::filesystem::path testFilePath = L"./testFile中文路径"; //ok2/* convert UTF-8 string or UTF-16 wstring Reference: https://en.cppreference.com/w/cpp/locale/codecvt_utf8_utf16#include <locale>#include <codecvt>#include <string>std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;std::string narrow = converter.to_bytes(wide_utf16_source_string);std::wstring wide = converter.from_bytes(narrow_utf8_source_string);*/// convert UTF-8 to UTF-16/char16_ttestFileDirString_UTF16 = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(testFileDirString_UTF8); //ok3testFileDirectory = testFileDirString_UTF16;try{currentTestFileDir = currentRootPath / testFileDirectory.relative_path();//获取当前测试文件路径: path append operator /=if (!std::filesystem::exists(testFileDirectory)){if(std::filesystem::create_directory(testFileDirectory)){std::cout << "Create file path: " << currentTestFileDir.string() << std::endl;}}else{std::cout << "Exist file path: " << currentTestFileDir.string() << std::endl;}}catch(const std::filesystem::filesystem_error& e){std::cout << "Test File Path is not exists and Create Failed!" << std::endl;std::cerr << std::string("Filesystem_Error: ").c_str() << e.what() << '\n';}/*****输入输出文件路径定义******/// 设定输入输出用测试文件全路径testTxtFile = (currentTestFileDir / testTxtFileString).string();testBinFile = (currentTestFileDir / testBinFileString).string();/*****输入输出流定义******///通过locale("")获取当前本地系统语言环境,中文系统locale 对象的name应为"Chinese_People's Republic of China.936",//用于读取中文路径及含中文文件名,//原始的locale对象的name为"C",也就是缺省的ANSI_C公约。//注意:如果使用locale::global(locale(""))设置全局locale后,没有用 locale::global(locale("C"))恢复的话,//如未对cout进行locale绑定,cout语句输出中文乱码。/*try {std::setlocale(LC_ALL, "");// replace the C++ global locale as well as the C locale with the user-preferred localestd::locale::global(std::locale(""));std::cout << "LC_ALL: " << std::setlocale(LC_ALL, NULL) << std::endl;std::cout << "LC_CTYPE: " << std::setlocale(LC_CTYPE, NULL) << std::endl;std::wcout << "User-preferred locale setting is " << std::locale().name().c_str() << '\n';}catch (std::runtime_error& e) {std::cerr << "What:" << e.what() << std::endl;std::cerr << "Type:" << typeid(e).name() << std::endl;std::wcout << "The selected locale is: " << std::locale().name().c_str() << '\n';}*/std::ifstream ifp; //std::ifstream ifp( inFile.c_str(), std::ios::in | std::ios::binary );std::ofstream ofp; //std::ofstream ofp( outFile.c_str(), std::ios::out );// // replace the C++ global locale as well as the C locale from the user-preferred locale// std::locale::global(std::locale("C"));/***** 加载输入输出文件 ******//***** TXT文件 ******///加载输出文件try{std::cout << std::endl;std::cout << "***** Begin test output TXT file: *****" << std::endl;std::cout << "Open testTxtFilePath: " << testTxtFile << std::endl;currentTestFilePath = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(testTxtFile);ofp.open(currentTestFilePath, std::ios::out);if (ofp.is_open()){// 获取系统的当前日期/时间time_t now = std::time(0);// 把 now 转换为字符串形式char* localeTime = ctime(&now); // Thu Dec 31 10:23:52 2020// 格式化输出设置/*//C++ 输入/输出库 std::ios_base Reference: https://en.cppreference.com/w/cpp/io/ios_base/fmtflagstypedef fmtflags;static constexpr fmtflags = //implementation defined指定可用的格式化标志。它是位掩码类型 (BitmaskType) 。定义下列常量:dec 为整数 I/O 使用十进制底oct 为整数 I/O 使用八进制底hex 为整数 I/O 使用十六进制底basefield dec|oct|hex 。适用于掩码运算left 左校正(添加填充字符到右)right 右校正(添加填充字符到左)internal 内部校正(添加填充字符到内部选定点)adjustfield left|right|internal 。适用于掩码运算scientific 用科学记数法生成浮点类型,或若与 fixed 组合则用十六进制记法fixed 用定点记法生成浮点类型,或若与 scientific 组合则用十六进制记法floatfield scientific|fixed 。适用于掩码运算boolalpha 以字母数字格式插入并释出 bool 类型showbase 生成为整数输出指示数字基底的前缀,货币 I/O 中要求现金指示器showpoint 无条件为浮点数输出生成小数点字符showpos 为非负数值输出生成 + 字符skipws 在具体输入操作前跳过前导空白符unitbuf 在每次输出操作后冲入输出uppercase 在具体输出的输出操作中以大写等价替换小写字符//C++ 标准库头文件 <iomanip> Reference: https://en.cppreference.com/w/cpp/header/iomanip此头文件是输入/输出操纵符库的一部分。定义resetiosflags 清除指定的 ios_base 标志 (函数)setiosflags 设置指定的 ios_base 标志 (函数)setbase 更改用于整数 I/O 的基数 (函数)setfill 更改填充字符 (函数模板)setprecision 更改浮点精度 (函数)setw 更改下个输入/输出域的宽度 (函数)get_money (C++11)剖析货币值 (函数模板)put_money (C++11)格式化并输出货币值 (函数模板)get_time (C++11)剖析指定格式的日期/时间值 (函数模板)put_time (C++11)按照指定格式格式化并输出日期/时间值 (函数模板)quoted (C++14)插入和读取带有内嵌空格的被引号括起来的字符串 (函数模板)概要namespace std {// 类型 T1 、 T2 ......为未指定的实现类型/T1/ resetiosflags(ios_base::fmtflags mask);/T2/ setiosflags (ios_base::fmtflags mask);/T3/ setbase(int base);template<charT> /T4/ setfill(charT c);/T5/ setprecision(int n);/T6/ setw(int n);template <class moneyT> /T7/ get_money(moneyT& mon, bool intl = false);template <class moneyT> /T8/ put_money(const moneyT& mon, bool intl = false);template <class charT> /T9/ get_time(struct tm* tmb, const charT* fmt);template <class charT> /T10/ put_time(const struct tm* tmb, const charT* fmt);template <class CharT>/T11/ quoted(const CharT* s, CharT delim = CharT('"'), CharT escape = CharT('\\'));template <class CharT, class Traits, class Allocator>/*T12/ quoted(const std::basic_string<CharT, Traits, Allocator>& s, CharT delim = CharT('"'), CharT escape = CharT('\\'));template< class CharT, class Traits>/*T13/ quoted(std::basic_string_view<CharT, Traits> s, CharT delim = CharT('"'), CharT escape = CharT('\\'));template< class CharT, class Traits, class Allocator >/*T14/ quoted(std::basic_string<CharT, Traits, Allocator>& s, CharT delim = CharT('"'), CharT escape = CharT('\\'));}*/// getline() with clear state// Reference: https://stackoverflow.com/questions/12133379/c-using-ifstream-with-getline// Reference: https://en.cppreference.com/w/cpp/io/basic_ios/fail// Reference: https://en.cppreference.com/w/cpp/io/basic_ios/clear/* have to call filein.clear(); in between the getline() calls.if (fp.bad())std::cout << m+1 << ":I/O error while reading\n";else if (fp.eof())std::cout << m+1 << ":End of file reached successfully\n";else if (fp.fail())std::cout << m+1 << ":Non-integer data encountered\n";fp.clear();//清理fp状态标志,防止while误判而使循环读取出错*/ofp << std::setiosflags(std::ios_base::fixed)<< std::setiosflags(std::ios_base::showpoint);// 格式化输出数据ofp << "/** 输出示例:以随机半径长度计算圆周长10次!" << "\tCode version: " << "1.0.0" << "\n";ofp << "/** FileName: " << testTxtFile << "\n";ofp << "/** Locale CTYPE: " << std::setlocale(LC_CTYPE, NULL) << "\tLocale time: " << localeTime;ofp << std::setw(4) << "/ No." << "\t";ofp << std::setw(6) << "Radius" << "\t";ofp << std::setw(10) << "PI" << "\t";ofp << std::setw(16) << "Circumference" << "\n";// 输出示例,以随机半径长度计算圆周长10次const double PI = std::atan(1.0) * 4; //获取pistd::srand(std::time(nullptr)); //以当前时间为随机生成器的种子for (int i = 0; i < 10; i++){int r = std::rand() % 10; //获取10以内随机数ofp << std::setw(4) << i+1 << "\t";ofp << std::setw(4) << r << "\t";ofp << std::setw(10) << std::setprecision(8) << PI << "\t";ofp << std::setw(16) << std::setprecision(12) << 2*PI*r << "\n";}ofp.clear(); //清除所有错误状态标志ofp.close();currentTestFilePath.clear(); //清空路径内容std::cout << "***** Output Success!*TXT文件输出成功!*****" << std::endl;}else std::cout << "/*** Unable to open output file ! ***/" << std::endl;}catch(const std::runtime_error& e){std::cerr << "What:" << e.what() << std::endl;std::cerr << "Type:" << typeid(e).name() << std::endl;}//加载输入文件try{std::cout << std::endl;std::cout << "***** Begin test read TXT file: *****" << std::endl;std::cout << "Open testTxtFilePath: " << testTxtFile << std::endl;currentTestFilePath = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(testTxtFile);ifp.open(currentTestFilePath, std::ios::in);if (ifp.is_open()){ifp.seekg(0, std::ios_base::beg);std::string lineInfo;while (std::getline(ifp, lineInfo)){std::cout << lineInfo << std::endl;ifp.clear();//!important!You would have to call filein.clear(); in between the getline() calls.}ifp.clear(); //清除所有错误状态标志ifp.close();currentTestFilePath.clear(); //清空路径内容std::cout << "***** Input Success!*TXT文件读取成功!*****" << std::endl;}else std::cout << "/*** Unable to open input file ! ***/" << std::endl;}catch(const std::runtime_error& e){std::cerr << "What:" << e.what() << std::endl;std::cerr << "Type:" << typeid(e).name() << std::endl;}/***** BIN文件 ******/// 示例二进制BIN文件输入输出所需公用变量;// 根据二进制数据写入文件的方式,在读取二进制文件数据时,应知道其存入时的数据类型、字节长度等;std::string exampleStr;std::size_t exampleStrSize;std::string codeVersionStr;std::size_t codeVersionStrSize;std::string fileNameStr;std::size_t fileNameStrSize;std::string localeCtypeStr;std::size_t localeCtypeStrSize;char* localeTime;std::size_t localeTimeStrSize;//加载输出文件try{std::cout << std::endl;std::cout << "***** Begin test output BIN file: *****" << std::endl;std::cout << "Open testBinFilePath: " << testBinFile << std::endl;currentTestFilePath = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(testBinFile);ofp.open(currentTestFilePath, std::ios::out | std::ios::binary);if (ofp.is_open()){// 获取系统的当前日期/时间time_t now = std::time(0);// 把 now 转换为字符串形式localeTime = ctime(&now); // Thu Dec 31 10:23:52 2020// 格式化输出设置// 写二进制文件 输出数据exampleStr = "输出示例:以随机半径长度计算圆周长10次!";exampleStrSize = exampleStr.size();codeVersionStr = "1.0.0";codeVersionStrSize = codeVersionStr.size();fileNameStr = testBinFile;fileNameStrSize = fileNameStr.size();localeCtypeStr = std::setlocale(LC_CTYPE, NULL);localeCtypeStrSize = localeCtypeStr.size();localeTimeStrSize = std::strlen(localeTime);//or sizeof(localeTime),but with null character,strlen(localeTime) without null character;std::cout << "localeTimeStr character: " << localeTime << '\n';std::cout << "localeTimeStrSize without null character: " << localeTimeStrSize << '\n';// 输出示例头部信息ofp.write((char*)&exampleStrSize,sizeof(int));ofp.write((char*)exampleStr.c_str(),sizeof(char)*exampleStrSize);ofp.write((char*)&codeVersionStrSize,sizeof(int));ofp.write((char*)codeVersionStr.c_str(),sizeof(char)*codeVersionStrSize);ofp.write((char*)&fileNameStrSize,sizeof(int));ofp.write((char*)fileNameStr.c_str(),sizeof(char)*fileNameStrSize);ofp.write((char*)&localeCtypeStrSize,sizeof(int));ofp.write((char*)localeCtypeStr.c_str(),sizeof(char)*localeCtypeStrSize);ofp.write((char*)&localeTimeStrSize,sizeof(int));ofp.write((char*)&localeTime,sizeof(char)*localeTimeStrSize);// 输出示例,以随机半径长度计算圆周长10次const int N = 10; //计算次数const double PI = std::atan(1.0) * 4; //获取piofp.write((char*)&N,sizeof(int));ofp.setf(std::ios_base::scientific); //设置double PI以科学计数法方式写入ofp.write((char*)&PI,sizeof(double));std::srand(std::time(nullptr)); //以当前时间为随机生成器的种子for (int i = 0; i < N; i++){int r = std::rand() % 10; //获取10以内随机数int j = i + 1;double cir = 2*PI*r;ofp.write((char*)&j,sizeof(int));ofp.write((char*)&r,sizeof(int));ofp.setf(std::ios_base::scientific);ofp.write((char*)&cir,sizeof(double));}ofp.clear();ofp.close();currentTestFilePath.clear();std::cout << "***** Output Success!*BIN文件输出成功!*****" << std::endl;}else std::cout << "/*** Unable to open output file ! ***/" << std::endl;}catch(const std::runtime_error& e){std::cerr << "What:" << e.what() << std::endl;std::cerr << "Type:" << typeid(e).name() << std::endl;}//加载输入文件try{std::cout << std::endl;std::cout << "***** Begin test read BIN file: *****" << std::endl;std::cout << "Open testBinFilePath: " << testBinFile << std::endl;currentTestFilePath = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(testBinFile);ifp.open(currentTestFilePath, std::ios::in | std::ios::binary);if (ifp.is_open()){ifp.seekg(0, std::ios_base::beg);ifp.seekg(0, std::ios_base::end);int fileDataCount = ifp.tellg(); //获取文件数据字节数std::cout << "Open file Data Count: " << fileDataCount << std::endl;ifp.seekg(0, std::ios_base::beg);// 读取示例头部信息ifp.read((char*)&exampleStrSize,sizeof(int));ifp.read(&exampleStr[0],exampleStrSize);ifp.read((char*)&codeVersionStrSize,sizeof(int));ifp.read(&codeVersionStr[0],codeVersionStrSize);ifp.read((char*)&fileNameStrSize,sizeof(int));ifp.read(&fileNameStr[0],fileNameStrSize);ifp.read((char*)&localeCtypeStrSize,sizeof(int));ifp.read(&localeCtypeStr[0],localeCtypeStrSize);ifp.read((char*)&localeTimeStrSize,sizeof(int));localeTime = new char[localeTimeStrSize+1];ifp.read(localeTime,localeTimeStrSize);localeTime[localeTimeStrSize] = '0円';std::cout << "/** " << exampleStr.c_str() << "\tCode version: " << codeVersionStr.c_str() << "\n";std::cout << "/** FileName: " << fileNameStr.c_str() << "\n";std::cout << "/** Locale CTYPE: " << localeCtypeStr.c_str() << "\tLocale time: " << localeTime << "\n";std::cout << std::setw(4) << "/ No." << "\t";std::cout << std::setw(6) << "Radius" << "\t";std::cout << std::setw(10) << "PI" << "\t";std::cout << std::setw(16) << "Circumference" << "\n";// 读取示例数据int N; //计算次数double PI; //获取piifp.read((char*)&N,sizeof(int));ifp.read((char*)&PI,sizeof(double));std::cout << std::setiosflags(std::ios_base::fixed)<< std::setiosflags(std::ios_base::showpoint);for (int i = 0; i < N; i++){int r; //获取半径int j; //获取计算次数double cir; //获取圆周长ifp.read((char*)&j,sizeof(int));ifp.read((char*)&r,sizeof(int));ifp.read((char*)&cir,sizeof(double));std::cout << std::setw(4) << j << "\t";std::cout << std::setw(4) << r << "\t";std::cout << std::setw(10) << std::setprecision(8) << PI << "\t";std::cout << std::setw(16) << std::setprecision(12) << cir << "\n";}ifp.clear();ifp.close();currentTestFilePath.clear();std::cout << "***** Input Success!*BIN文件读取成功!*****" << std::endl;}else std::cout << "/*** Unable to open input file ! ***/" << std::endl;}catch(const std::runtime_error& e){std::cerr << "What:" << e.what() << std::endl;std::cerr << "Type:" << typeid(e).name() << std::endl;}/***** 测试控制台输出 *****/std::cout << std::endl;std::cout << "***** Begin test Console output: *****" << std::endl;for (const std::string& word : msg){std::cout << word << " ";}std::cout << std::endl;std::cout << "***** Output Complete!*输出完成!*****" << std::endl;return 0;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。