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)テキストファイルのみを変換する必要がある場合は、翻訳モードのループでソースファイルを1行ずつ読み取ることができます(この場合は十分に改行を処理します)。メンバーgetline()を実行し、最後を除く各行の後に\nまたは\r \ nを挿入しながら、出力ファイルに行を出力します。

次に、元のファイルを削除し、一時ファイルの名前を元のファイルの名前に変更できます。または、必要に応じて、代わりに行をvector<string>にpush_backすることができます。次に、ファイルへの入力ハンドルを閉じ、ofstream out( "filename"、ios_base :: trunc)を実行し、必要な改行で区切ってベクターの要素をファイルに書き込みます。

それはすべてあなたの要件に依存します。

以下は、エラー処理を最小限に抑えた例です。しかし、ここで別の方法として示したいのは、実際にはFORループと行ごとの読み取りだけです。

convert_file.exe "test.txt" "linux"

convert_file.exe "test.txt" "win"

#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 に答える