2012-04-09 2 views
3

Unix에서 Windows로 변환 할 때 정확한 결과를 얻습니다. 그러나 Windows에서 Unix로 갈 때 이상한 결과를 얻습니다. 내가 허용해야했던 것은 캐리지 리턴 '\ r'을 제거하는 것 뿐이라고 생각했습니다. 이것은 비록 작동하지 않습니다. 코드를 실행 한 후 텍스트 파일을 열면 몇 가지 이상한 결과가 나타나고 첫 번째 줄이 올 바르며 모든 지옥이 끊어집니다.텍스트 파일을 Windows에서 Unix로 변환하는 방법

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 
+0

그래서, 다른 방향으로 어떻게됩니까? –

+0

스크립트를 사용할 수 있으면 linux/unix 플랫폼에서 dos2unix를 사용할 수도 있습니다. – weima

+1

이 경우 문제가 될지는 모르지만 실제로 fest를 호출해야합니다.close()'를 호출하여 대상 파일의 입력 스트림을 닫은 다음 출력 스트림으로여십시오. –

답변

4

*이 (충분히 당신을 위해 줄 바꿈을 처리 이 경우)을 구성원이 아닌 getline()과 결합한 다음 마지막 줄을 제외한 각 줄 다음에 \ n 또는 \ r \ n을 삽입하면서 출력 파일에 출력합니다.

그런 다음 원본 파일을 제거하고 임시 파일의 이름을 원래 파일 이름으로 바꿀 수 있습니다. 또는 원하는 경우 줄을 벡터로 < 문자열 >으로 push_back 할 수 있습니다. 그런 다음 파일의 입력 핸들을 닫고 ofstream out ("filename", ios_base :: trunc)을 수행하고 벡터의 요소를 원하는 줄 바꿈으로 구분하면서 파일에 쓸 수 있습니다.

모두 요구 사항에 따라 다릅니다.

다음은 오류 처리가 최소화 된 예제입니다. 하지만 실제로 FOR 루프와 한 줄씩 읽는 것만 다른 방식으로 보여주고 싶습니다.

convert_file.exe "TEST.TXT" "리눅스"

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 ++와 같은 편집자)이 당신을 위해 개행 문자 변환을합니다. 따라서 다른 이유로 (사용자가 지정하지 않은 경우에만)이 작업을 수행하지 않는 한 직접 구현할 필요가 없습니다.

+0

내 논리 또는 알고리즘에 문제가 있는지 알고 싶었습니다. – Jerrod

1

데이터를 올바른 형식으로 읽고 올바른 형식으로 저장했는지 확인 했습니까?

다른 문자 인코딩으로 작업하고 '읽기'만하면 아주 나쁜 일이 발생합니다.

그리고 나서 수행해야 할 다른 대체 작업도 고려해야합니다. 이 도움이 될 수

link

+0

C++에 대한 지식이 제한적입니다. 나는 바이너리 코드로 데이터를 읽으므로, 그 레벨에서 윈도우와 유닉스 사이의 포맷에는 차이가 없다. 그래서 내가 아는 한 윈도우 개행 문자는 "/ r/n"으로 읽히고, 유닉스는 "/ n"으로 읽힌다. 그러므로 3 개의 서로 다른 줄에 세 단어가있는 Unix 텍스트 파일은 창에 열리고 그 사이에 공백없이 한 줄에 세 단어로 나타납니다. 이는 윈도우가 "/ n"을 개행 문자로 인식하지 않기 때문에 "/ r"이 앞에 붙지 않기 때문입니다. 그래서 저에게, 그것은 "/ r"을 추가하는 것입니다. 그리고 그것이 제가 시도한 것입니다. – Jerrod

+0

예, 파일이 UTF-16으로 인코딩 된 경우'\ r \ 0 \ n \ 0 \을'\ n \ 0 '으로 대체해야합니다. 그런 것들. –

2

I가 다시 편집 ..이 도움이

희망을 코드를하고 나를 위해 잘 작동!

#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; 
} 
+1

이것은 파일을 다른 것으로 복사하는 것 외에는 아무 것도하지 않는 것처럼 보입니다. 형식이 성공적으로 변환되지 않습니다. – Jerrod

2

루프의 창을 확인하는 것에 대해 걱정할 필요가 없습니다. 캐리지 리턴을 확인하기 만하면됩니다. 'carriage_return'변수를 설정하십시오. 다음 반복, 'carriage-return'및 ch! = linefeed가 있으면 단순히 줄 바꿈을 삽입하십시오. 그런 다음 carriage_return 변수를 false로 재설정하십시오. 그것은 당신을 잘못 보내지 않을 매우 간단하고 기본적인 규칙입니다. 당신은 단순한 ASCII (아마도 UTF-8) 텍스트 파일을 변환 할 필요가 * 당신이 번역 모드에서 루프 라인 별을 원본 파일을 읽을 수 있다면

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(); 
} 
+0

LF가'\ n'이고 CR이'\ r'라고 맞습니다. –

관련 문제