3

从 Unix 转换到 Windows 时,我得到了正确的输出;但是,当从 Windows 转到 Unix 时,我得到了一些奇怪的输出。我认为我所要做的就是删除回车符'\ r'。这虽然行不​​通。当我运行代码后打开文本文件时,我得到了一些奇怪的结果,第一行是正确的,然后所有的地狱都输了。

   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
4

4 回答 4

4

*如果*您只需要转换简单的 ascii(也许是 utf-8)文本文件,您可以在循环中以翻译模式逐行读取源文件(在这种情况下为您处理足够的换行符)与非成员 getline() 然后将行输出到输出文件,同时在除最后一行之外的每一行之后插入 \n 或 \r\n。

然后,您可以删除原始文件并将临时文件重命名为原始文件的名称。或者,如果您愿意,您可以改为将行 push_back 放入 vector<string>。然后,您可以关闭文件的输入句柄,执行 ofstream out("filename", ios_base::trunc) 并将向量的元素写入文件,同时用所需的换行符分隔它们。

这一切都取决于您的要求。

以下是一个错误处理最少的示例。但是,我想在这里展示的只是 FOR 循环和逐行读取,这是一种不同的做事方式。

convert_file.exe "test.txt" "linux"

convert_file.exe “test.txt” “赢”

#include <iostream>
#include <string>
#include <fstream>
#include <ostream>
#include <cstdlib>
#include <cstdio>
using namespace std;

int main(int argc, char* argv[]) {
    if (argc != 3) {
        cerr << "Usage: this.exe file_to_convert newline_format(\"linux\" or \"win\")" << endl;
        return EXIT_FAILURE;
    }
    string fmt(argv[2]);
    if (fmt != "linux" && fmt != "win") {
        cerr << "Invalid newline format specified" << endl;
        return EXIT_FAILURE;
    }
    ifstream in(argv[1]);
    if (!in) {
        cerr << "Error reading test.txt" << endl;
        return EXIT_FAILURE;
    }
    string tmp(argv[1]);
    tmp += "converted";
    ofstream out(tmp.c_str(), ios_base::binary);
    if (!out) {
        cerr << "Error writing " << tmp << endl;
        return EXIT_FAILURE;
    }
    bool first = true;
    for (string line; getline(in, line); ) {
        if (!first) {
            if (fmt == "linux") {
                out << "\n";
            } else {
                out << "\r\n";
            }
        }
        out << line;
        first = false;
    }
    in.close();
    out.close();
    if (remove(argv[1]) != 0) {
        cerr << "Error deleting " << argv[1] << endl;
        return EXIT_FAILURE;
    }
    if (rename(tmp.c_str(), argv[1]) != 0) {
        cerr << "Error renaming " << tmp << " to " << argv[1] << endl;
        return EXIT_FAILURE;
    }
}

正如其他人所说,已经有一些实用程序(包括像 Notepadd++ 这样的文本编辑器)可以为您进行换行符转换。因此,您不需要自己实现任何东西,除非您出于其他原因(您没有指定)这样做。

于 2012-04-10T05:50:10.557 回答
2

我已经重新编辑了你的代码,它对我来说很好用..

希望这可以帮助 !

#include <iostream>
#include <fstream>
#include <iostream>
#include<stdio.h>
using namespace std;

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!";
        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;
        cin >> answer;
        if ( answer == 'n' || answer == 'N' )
        {
            return 1;
        }
    }
    //clrscr();

    ofstream fout( destination);
    if ( !fout.good() )
    {
        cout << destination << "could not be opened!" << endl;
        return 1;
    }
    char ch = fin.get();
    while (!fin.eof())
    {
        if ( ch == '\r' ) 
        {                   
            windows = true;
        }
        if ( ch == '\n' && windows == false )    // If the file is in the Unix format..
        {
            // Don't do anything here
        }
        fout.put( ch );
        cout << ch; // For Debugging purpose
        ch = fin.get();
    }
    fout.close();
    fin.close();

    if ( windows == true )       // A little output for user-friendly-ness.
    {
        cout<<endl;
        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;
    return 0;
}
于 2012-04-09T06:03:03.140 回答
2

不用担心在循环中检查窗口。只需检查回车。设置一个变量“carriage_return”。下一次迭代,如果 'carriage-return' 和 ch != linefeed,只需插入一个换行符。然后将carriage_return 变量重置为false。这是一个非常简单和基本的规则,不会让你出错。

bool carriage_return = false;
const char linefeed = '\n'; // Is it? I forget.
const char cr = '\r'; // I forget again. Too late to check.
char ch = fin.get();
if (ch == cr) carriage_return = true;
while (!fin.eof()){
  if (carriage_return) {  // Check if we already have a newline
    if (ch != linefeed) { // If we have a newline previously, we need a linefeed. If it's already there just leave it, if it isn't there put it in
      fout.put(linefeed);
    }
    if (ch != cr) carriage_return = false; // Reset the carriage-return flag *if* we don't have another carriage return. This handles multiple empty lines in an easy way for us.
  }

  fout.put(ch);
  ch = fin.get();
}
于 2012-04-09T06:13:46.657 回答
1

您是否确保以正确的格式读取数据并以正确的格式保存?

尝试使用不同的字符编码并只是“读取”它会导致非常糟糕的事情:|

然后,您还必须考虑需要完成的不同替换。

这可能有助于链接

于 2012-04-09T04:59:36.770 回答