DEV ℧ Developer Diary

[Java] Linux와 Window의 엔터값(개행문자)으로 인한 트러블 슈팅

해당 포스터를 쓸 당시에, JAVA로 파일을 생성해야하는 업무가 있었는데, 400b를 맞춰야 하는 파일이 이상하게 401b과 같이 1~2 byte가 맞지 않았던 일이 있었다.

이에 대해 해결했던 이론을 정리해 보았다.

개행문자

줄바꿈을 갖는 개행문자는 같은 Enter 값이라고 해도 OS별로 차이가 있다. 먼저 줄바꿈을 나타내는 제어문자에는 아래와 같이 사용한다.

  • CR (Carrige Return) : \r로 표현하며 커서를 맨 왼쪽으로 이동시킨다.
  • LF (Line Feed) : \n로 표현하며 커서를 한칸 아래로 이동하여 새로운 라인을 추가한다.

운영체제별로 CR과 LF를 각기 조합해서 개행문자로 표현하고 있다.

  • Unix (linux, Mac)은 LF(\n)을 이용해 개행문자를 표현한다.
  • Window는 CR/LF(/r/n)을 이용해 개행문자를 표현한다.
  • Mac OS의 경우 9버전 이하는 CR(/r)을 이용해 개행문자를 표현한다.

운영체제별 개행문자의 차이는 서로 다른 OS에서 동작하는 프로그램의 경우 문제가 발생할 수 있다.

대표적인 예를 보자. Java의 경우 운영체제의 종류에 맞춰서 줄바꿈 문자를 변경해주는데,

String fileName = "text.txt";
try{
    BufferedWriter bw = new BufferedWriter(new FileWriter(fileName, true));
    bw.write("abcde");
    bw.newLine();
    bw.flush();
    bw.close();
} catch (Exception e){
    e.printStackTrace();
}

해당 소스를 각기 다른 운영체제에서 실행하면 다른 결과물이 나온다.

메모장이나 vi를 이용해 생성된 파일을 열었을때 둘다

abcde

의 결과가 출력 되어있을 것이다. 하지만 파일의 정보를 열어 파일의 크기를 볼경우 차이를 확인 할 수 있다.

윈도우에서는 abcde(5byte) + \r\n(2byte)의 총 7byte의 텍스트 파일이 생성되고, Unix계열의 운영체제에서는 abcde(5byte) + \n(1byte)의 6byte의 텍스트 파일이 생성된다.

정보를 파일처리하여 각기 다른 OS로 송수신 하는 경우 개행문자로 인한 용량차이로 에러를 불러 올 수 있으며, window에서 작성한 shell스크립트를 리눅스에서 실행할 경우에도

$'\r': command not found

와 같은 오류를 발생 할 수 있다.

해당 오류의 경우

sed -i 's/\r$//' filename

의 명령어를 이용해 해결할 수 있다. filename이라는 이름의 파일안에 있는 /r의 문자를 sed -i의 명령어를 이용해 공백으로 치환 해준다는 명령어이다.