자바에서 파일 쓰기 할 때
BufferedWriter file = new BufferedWriter(new FileWriter("filename")); 


대개의 경우 이런식으로 코딩을 했었는데, 이 코드는 파일을 덮어쓴다. 
파일을 덮어쓰지 않고 이어쓰기하는 방법이 없을까 하고 고민하고 찾아봤다.
RandomAccessFile 클래스를 사용하는 방법도 있었고
그리고 파일을 쭉 읽어서 변수에 저장을 한 뒤 새로 추가할 내용을 덧붙여서 파일에 쓰는 방법도 있었다. 
하지만 뭔가 더 간편한게 있을 것 같아서 찾아봤더니
이 한문장이면 파일 이어쓰기가 가능하다.

BufferedWriter file = new BufferedWriter(new FileWriter("filename", true));

이 코드는 파일이 없으면 새로 만들고 있다면 덮어쓰지 않고 이어서 쓰게한다.

그리고 파일에서 개행문자를 쓰려고할 때
C나 C++에서처럼 당연히 ""이 먹힐거라 생각을 하고 
str = str + "";
file.write(str, 0, str.length());

이렇게 썼는데 파일에는 줄바꿈이 되어있지 않았다. 
알아본 결과 저 위에서 사용한 FileWriter가 가독성때문에 ""을 지원하지 않기 때문이었다. 
BufferedWriter를 통해서 개행문자를 쓸 수 있다. 
바로 이렇게..

file.write(str, 0, str.length());
file.newLine();

간단하다. 하하하;;;
이 사실을 난... 어제 알았다. 쿨럭 -_-;;;
까먹을까봐...



===================================================================================


자바로, 텍스트 파일을 만들어서, 그 안에 문자열을 쓰고, 저장하는 예제입니다.

텍스트 파일 생성/만들기 예제 소스


소스 파일명: Foo.java
import java.io.*;

public class Foo {
  public static void main(String args[]) {

    try {
      ////////////////////////////////////////////////////////////////
      BufferedWriter out = new BufferedWriter(new FileWriter("out.txt"));
      String s = "출력 파일에 저장될 이런 저런 문자열입니다.";

      out.write(s); out.newLine();
      out.write(s); out.newLine();

      out.close();
      ////////////////////////////////////////////////////////////////
    } catch (IOException e) {
        System.err.println(e); // 에러가 있다면 메시지 출력
        System.exit(1);
    }

  }
}


위의 자바 소스를 컴파일한 후 실행하면, 하드의 현재 디렉토리에 out.txt 라는 텍스트 파일이 생깁니다.

생성된 out.txt 파일의 내용:
출력 파일에 저장될 이런 저런 문자열입니다.
출력 파일에 저장될 이런 저런 문자열입니다.



참고로, newLine() 이라는 메소드는, 현재 운영체제의 종류를 자동으로 판단한 후, 적절한 개행문자를 출력하여 줄바꿈하는 것입니다.


출처 - http://mwultong.blogspot.com/2006/10/java-text-file-write.html



===================================================================================


하드에 있는 텍스트 파일을, 명령행 옵션으로 지정해 주면, 그 파일을 한 줄씩 읽어서 화면에 출력하는 자바 프로그램입니다.

if (args.length == 0) 라는 부분은 읽을 파일명을 지정해 주지 않았을 때 에러 메시지를 출력하는 코드입니다.


자바로 텍스트 파일 읽기 예제 소스


소스 파일명: Foo.java
import java.io.*;

public class Foo {
  public static void main(String args[]) {

    if (args.length == 0) {                   // args.length 는 옵션 개수
      System.err.println("Input Filename...");
      System.exit(1);                         // 읽을 파일명을 주지 않았을 때는 종료
    }

    try {
      ////////////////////////////////////////////////////////////////
      BufferedReader in = new BufferedReader(new FileReader(args[0]));
      String s;

      while ((s = in.readLine()) != null) {
        System.out.println(s);
      }
      in.close();
      ////////////////////////////////////////////////////////////////
    } catch (IOException e) {
        System.err.println(e); // 에러가 있다면 메시지 출력
        System.exit(1);
    }

  }
}


위의 소스에서 빗금 쳐진 구역이, 파일을 읽는 핵심부입니다.

FileReader 는 현재 시스템의 기본 인코딩으로 파일을 읽는데, BufferedReader 로 감싸 주어야 합니다.

readLine() 은 파일을 한 줄씩 읽지만 줄바꿈 문자는 읽지 않습니다. 그래서 println()이 아닌 print(s)로 출력하면 모든 줄이 하나로 붙어서 나옵니다.



0.txt 라는 테스트용 텍스트 파일에, 이육사 시인의 '청포도'라는 시가 적혀 있다고 가정합니다.

javac Foo.java
이렇게 컴파일 한 후

java Foo 0.txt
이렇게 실행시킵니다.


실행 결과:
D:\Z>javac Foo.java

D:\Z>java Foo 0.txt

          청포도


                          이육사


내 고장 칠월은
청포도가 익어 가는 시절

이 마을 전설이 주저리주저리 열리고
먼 데 하늘이 꿈꾸며 알알이 들여와 박혀

하늘 밑 푸른 바다가 가슴을 열고
흰 돛단배가 곱게 밀려서 오면,

내가 바라는 손님은 고달픈 몸으로
靑袍를 입고 찾아온다고 했으니

내 그를 맞아, 이 포도를 따먹으면
두 손은 함뿍 적셔도 좋으련

아이야, 우리 식탁엔 은쟁반에
하이얀 모시 수건을 마련해 두렴


D:\Z>


출처 - http://mwultong.blogspot.com/2006/10/java.html


===================================================================================


<텍스트 파일을 읽기>

1.파일을 연다.
텍스트 파일을 읽기 위해서는 FileReader 스트림 클래스를 사용한다.

FileReader in = new FileReader("test.txt");
또는
FileReader in = new FileReader("c:/test.txt");

2.데이터를 읽는다.
데이터를 읽기 위해서는 read() 메소드를 사용한다.
read() 메서드는 읽어 온 문자를 int 형 정수로 변환한다.
읽어 올 데이터가 없으면 -1 을 반환한다.

int c;
c = in.read();

3.파일을 닫는다.
파일을 닫기 위해서는close() 메서드를 사용한다.

in.close();

텍스트 파일의 전체 내용을 읽기 위해서는 read() 메서드가 -1 을 반환할때까지 읽기를 반복하면 된다.

inc c;
String s = new String();
while((c=in.read()) != -1){
  s = s + (char) c;
}

즉, in.read() 를 이용해 읽어들인 값 c 는 int 형 정수이기 때문에, 이를 캐스트 연산자를 이용해 char 형으로 변환한다.
(한개의 문자를 읽기 때문에)
그리고, 이렇게 변환한 문자를 String 형 변수인 s 에 계속 덧붙여서 문장을 완성한다.

test.txt 라는 파일이 존재하고, 그 안에 '가나다라마바사' 라는 내용이 들어있다고 가정하자.
아래와 같은 로직을 통해 파일을 읽어들인다.

<a.java 내용>

import java.io.*;   //스트림을 이용하기 위해서 java.io 패키지를 이용한다.
public class a
{
  public static void main(String [] args)
  {
    try{
      //FileReader in = new FileReader(args[0]);  //읽어들일 파일을 최초 클래스 호출시 인자값으로 받아 처리한다.
      //FileReader in = new FileReader("c:/test.txt");  //인자가 아니라, 지정된 파일명으로 호출한다.
      //만약, 파일의 절대경로를 표시하려면, C:\ 로 표시하지 말고, C:/ 로 표시해야 한다.
      //만약, 현재 클래스 파일과 같은 위치의 파일이라면, 경로를 생략하고 파일명만 기재하면 된다.
      FileReader in = new FileReader("test.txt");
      int c;
      String s = new String();
      while((c=in.read()) != -1){
       s = s + (char)c;
       //System.out.println(s);  //엔터키값이 있는 경우에도 읽어들이는데, 엔터키값은 2개의 코드로 이루어져 있어 두번더 반복된다.(화면에는 출력되지 않음)
      }
      System.out.println(s);
      in.close();
    }catch(IOException ie){
      System.out.println("파일이 존재하지 않습니다.");
      //IOException 의 경우에는, 별도로 java.io 패키지를 사용하는 경우 덧붙여 사용할 수 있다.(생략가능)
      //만약, 생략하면, 그냥 catch(Exception e) 에 걸린다.
    }catch(Exception e){
      System.out.println(e);
    }
  }
}

위의 로직에서 몇가지를 테스트 해보았다.
절대경로를 탐색하는 경우에는 \ 기호가 아니라 / 기호를 이용해야 한다.
즉, c 루트에 있는 test.txt 파일이라면,
c:\test.txt 로 하게되면 파일을 찾지 못한다.
그래서,
c:/test.txt 로 경로를 작성하면 파일이 검색된다.
또한, FileReader 객체를 소거하는 in.close() 경우에도,
while 구문 안에 넣어서는 안된다. while 구문이 끝난 마지막에 처리할것.
catch(IOException ie) 는, java.io 패키지를 사용하는 경우, 추가하여 기술할 수 있다.
이는, 파일스트림관련 오류가 발생할 경우, 그 에러를 감지한다.

엔터키값이 들어있는 경우에도, 이 코드들을 한개의 문자로 인식하기 때문에,
while 반복구문에서 두번의 반복 횟수가 늘어난다.
즉, \n 또는 키값이 있기 때문인데,
화면에는 별도로 표시되지 않지만, 반복횟수는 두번이 늘어난다는 것을 명심할것.

최초, 파일을 찾는 부분에서, 호출 인자인 arg[] 를 이용해 파일을 찾는다면,
FileReader in = new FileReader(args[0]);
라고 기술할 수 있으며, 이는, 실행명령 다음에, 클래스명 다음에 온 문자열을 파일의 이름으로 인식하는 것이다.
즉,

c:\java>java a test.txt

라고 기술한다면,
test.txt 라는 인자를 인지하여, 그것으로 파일을 찾는 것이다.


<텍스트 파일에 쓰기>
1.파일을 연다.
텍스트 파일에 문자를 써 넣기 위해서는 FileWriter 스트림 클래스의 오브젝트를 사용한다.

FileWriter out = new FileWriter("test.txt");
또는,
FileWriter out = new FileWriter("c:/test.txt");

2.데이터를 써 넣는다.
데이터를 써 넣을때는 write() 메서드를 이용한다.
write() 메서드는 인수로 주어진 데이터를 파일에 써 넣는다.
(또는, 임의로 지정한 스트링을 입력)

out.write("Hello\n");

3.파일을 닫는다.

out.close();

이를 이용해 아래와 같은 로직을 작성한다.

import java.io.*;

public class a
{
  public static void main(String [] args)
  {
    try{
      //FileWriter out = new FileWriter("c:/test.txt");  //절대경로를 사용할 경우,
      //FileWriter out = new FileWriter(args[0]);  //인자를 이용해서 사용할 경우.
      
      String fn = "test.txt";
      
      FileWriter out = new FileWriter(fn);
      int a = 10, b = 5;
      out.write ("덧셈:");
      out.write (a + " + " + b + " = " + (a+b));
      //out.write ("\n");  //유닉스 계열에서는 \r 을 사용하지 않는다.
      out.write ("\r\n");  //윈도우에서는 줄바꿈을 위해 \r\n 을 해줘야 한다.
      out.write ("뺄셈:");
      out.write (a + " - " + b + " = " + (a-b));
      out.write ("\r\n");
      out.close();
      
      System.out.println("파일 " + fn + " 에 내용을 입력하였습니다.");
    }catch(IOException ie){
      System.out.println("IO 에러가 발생했습니다.");
    }catch(Exception e){
      System.out.println(e);
    }
  }
}


주의할점은, write() 메소드는, 기존에 파일이 없으면 새로 생성하고,
있다면, 그 내용이 모두 지워지고 새로 쓰여 진다는 점이다.

또한, 줄바꿈에 있어서, 윈도우 계열에서는 줄바꿈을 \r\n 을 이용해야만 줄바꿈이 되며,
\n 만을 사용하면, ■ 과 같은 기호만 출력된다.
그러나, 유닉스 계열에서는 줄바꿈에 \r 을 사용하지 않는다.
따라서, 유닉스 계열에서는 \n 만을 사용해야 한다.

책에서는 별도로, 파일에 쓰기 관련해서는 IOException 을 언급하고 있지 않지만,
이 부분을 기술해도 에러가 나지 않는것으로 보아, 사용할 수 있을것으로 보이며,
실상, 쓰기에서 IOException 에러가 나는 상황을 접해보지 않아서, 그런 경우에 어떻게 처리하면 좋을 것인지는
좀더 테스트가 필요하다.


\n 을 이용한경우,

\r\n 을 이용한경우,





Java 7 Files

NIO. 2 에 파일 관련 각종 API가 추가되었다. 이전보다 더 쉽게 파일 관련 작업을 수행할 수 있다.

File I/O (Featuring NIO.2) (The Java™ Tutorials > Essential Classes > Basic I/O) 에서 자세히 볼 수 있으며 아래는 간단한 정리이다..

Path

파일의 경로는 java.nio.file.Path 인터페이스로 나타낸다. 기존의 java.io.File을 Path로 대체한다.

Path 는 인터페이스이며 Paths 혹은 FileSystem 객체로부터 Path 객체를 생성할 수 있다.

import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
 
Path path = Paths.get("C:\\Temp\\test.txt");
//혹은 FileSystem 객체로 부터...
Path pathFromFS = FileSystems.getDefault().getPath("C:\\Temp\\test.txt");
 
System.out.println("Path exists == " + Files.exists(path));

Files

Files 클래스는 파일의 복사/이동/삭제/스트림생성/각종 파일 속성 설정 등에 관련된 매우 쉬운 static 메소드를 수십여개 제공해주고 있다.

Manipulating Files in Java 7와 File I/O (Featuring NIO.2) (The Java™ Tutorials > Essential Classes > Basic I/O)를 참조한다.

Java 7: Copy and Move Files and Directories - Java Code Geeks


출처 - http://wiki.kwonnam.pe.kr/java/7/files













'Development > Java' 카테고리의 다른 글

java - 가비지 컬렉션(Garbage Collection)  (0) 2012.10.05
jdom - xmlns, xsi 설정  (0) 2012.10.04
java - 파일 읽기 및 쓰기  (0) 2012.10.04
java - 디렉토리 생성, 삭제  (0) 2012.10.04
java - JDOM  (0) 2012.10.02
java - Date 시간 및 날짜 차이 계산  (0) 2012.09.08
Posted by linuxism

댓글을 달아 주세요