When converting from Unix to Windows, I get the correct output; however, when going from Windows to Unix I get some strange output. I thought all I had to allow for was the removal of the carriage return, ‘\r’. This isn’t working though. When I open the text file after running the code, I get some strange results, the first line is correct, and then all hell breaks lose.
int main( )
{
bool windows = false;
char source[256];
char destination[256]; // Allocate the max amount of space for the filenames.
cout << "Please enter the name of the source file: ";
cin >> source;
ifstream fin( source, ios::binary );
if ( !fin ) // Check to make sure the source file exists.
{
cerr << "File " << source << " not found!";
getch();
return 1;
}//endif
cout << "Please enter the name of the destination file: ";
cin >> destination;
ifstream fest( destination );
if ( fest ) // Check to see if the destination file already exists.
{
cout << "The file " << destination << " already exists!" << endl;
cout << "If you would like to truncate the data, please enter 'Y', "
<< "otherwise enter 'N' to quit: ";
char answer = char( getch() );
if ( answer == 'n' || answer == 'N' )
{
return 1;
}//endif
}//endif
clrscr(); // Clear screen for neatness.
ofstream fout( destination, ios::binary );
if ( !fout.good() ) // Check to see if the destination file can be edited.
{
cout << destination << "could not be opened!" << endl;
getch();
return 1;
}//endif
// Open the destination file in binary mode.
fout.open( destination, ios::binary );
char ch = fin.get(); // Set ch to the first char in the source file.
while ( !fin.eof() )
{
if ( ch == '\x0D' ) // If ch is a carriage return, then the source file
{ // must be in a windows format.
windows = true;
}//endif
if ( windows == true )
{
ch = fin.get(); // Advance ch, so that at the bottom of the loop, the
}//endif // carriage return is not coppied into the new file.
if ( windows == false )
{
if ( ch == '\x0A' ) // If the file is in the Unix format..
{
fout.put( '\x0D' ); // When a new line is found, output a carriage
}//endif // return.
}//endif
fout.put( ch );
ch = fin.get();
}//endwh
if ( windows == true )
{
fout.put( '\x0A' );
}//endif
fout.close();
fin.close(); // Close yer files.
if ( windows == true ) // A little output for user-friendly-ness.
{
cout << "The contents of " << source << " have been coppied to "
<< destination << " and converted to Unix format." << endl;
}else{
cout << "The contents of " << source << " have been coppied to "
<< destination << " and converted to Windows format." << endl;
}//endif
cout << "Enter any key to quit.." << endl;
getch();
return 0;
}//endmn
*If* you only need to convert simple ascii (and perhaps utf-8) text files, you could read the source file line-by-line in a loop in translated mode (handles newlines for you enough for this case) with non-member getline() and then output the lines to the output file while inserting \n or \r\n after each line except the last.
Then, you can remove the original file and rename the temp file to have the original file’s name. Or, if you want, you can instead push_back the lines into a vector<string>. Then, you could close the input handle to the file, do ofstream out(“filename”, ios_base::trunc) and write the elements of the vector to the file while separating them by the newlines you want.
It all depends on your requirements.
The following is an example with minimal error handling. But, it’s really only the FOR loop and reading line-by-line that I want to show here as a different way of doing things.
convert_file.exe “test.txt” “linux”
convert_file.exe “test.txt” “win”
As others have said though, there are already utilities (including text editors like Notepadd++) that do newline conversion for you. So, you don’t need to implement anything yourself unless you’re doing this for other reasons (you didn’t specify).