// g++ -g -O2 efbbbf-strip.cpp -o efbbbf-strip.exe #include using std::cout; using std::cerr; using std::endl; using std::ios_base; #include using std::ifstream; using std::ofstream; #include using std::string; #include using std::strlen; static const string EFBBBF = string("\xef\xbb\xbf"); static const unsigned int EFBBBF_LEN = 3; bool Strip(const char* filename); int main(int argc, char* argv[]) { if(argc == 1) { cerr << "Strips text files of UTF-8 byte order marks (BOM) in place." << endl; cerr << " Usage: efbbbf-strip.exe [ …]" << endl; return 1; } for(unsigned int i = 1; i < (unsigned int)argc; i++) { Strip(argv[i]); } } bool Strip(const char* filename) { if ( !filename || 0 == strlen(filename) ) return false; ////////////////////////////////////////////////////////// // Read the file ////////////////////////////////////////////////////////// ifstream ifile(filename); if( !ifile.good() ) { cerr << "Unable to open " << filename << " for reading" << endl; return false; } // Reserve size to save on allocations ifile.seekg(0, ios_base::end); if( !ifile.good() ) { cerr << "Failed to seek to end of " << filename << endl; return false; } size_t fsize = ifile.tellg(); if( !ifile.good() ) { cerr << "Failed to determine size of " << filename << endl; return false; } ifile.seekg(0, ios_base::beg); if( !ifile.good() ) { cerr << "Failed to seek to beginning of " << filename << endl; return false; } string str, line; str.reserve(fsize); // Read the file line by line. Not sure why reading in one fell swoop failed.... while(std::getline(ifile, line)) { str += line; str += "\n"; if( !ifile.good() ) break; } ifile.close(); ////////////////////////////////////////////////////////// // Fix the file ////////////////////////////////////////////////////////// size_t count = 0; string::size_type pos = 1; while( (pos = str.find(EFBBBF, pos)) != string::npos ) { str.replace(pos, EFBBBF_LEN, ""); count++; } if(0 == count) { cout << filename << ": no replacements" << endl; return true; } ////////////////////////////////////////////////////////// // Write the file ////////////////////////////////////////////////////////// ofstream ofile(filename, ios_base::out | ios_base::trunc); if( !ofile.good() ) { cerr << "Unable to open " << filename << " for writing" << endl; return false; } ofile.write(str.data(), str.size()); if( !ofile.good() ) { cerr << "Failed to write " << filename << endl; return false; } ofile.close(); ////////////////////////////////////////////////////////// // Book keeping ////////////////////////////////////////////////////////// cout << filename << ": " << count << " replacements" << endl; return true; }