Project

데몬 프로젝트 - 파일 이동 프로그램 1

이웃비 2022. 5. 11. 23:47
기본 정보
OS: Windows
Language : Java 1.8
Tool : Eclipse

 

목적

몇개 파일이 A폴더에 들어오는 즉시 A->B 폴더로 이동

파일형식은 csv, xlsx, xls

 

조건  

- 언제 파일이 폴더에 들어오든 B폴더로 이동하도록 할 것

- 프로그램이 서버가 작동하는 한 계속해서 돌아가야 함 -> 윈도우 프로그램으로 만들어 백그라운드에서 돌아가도록 한다.

- 후에 기능이 확장될 가능성이 있음 -> Thread를 이용하여 파일 이동만을 처리한다.

 

 

1. Project 생성

Project Name : moveFiles

이클립스에서 프로젝트를 생성한다. 파일 이동 기능만 있으니까 일단 movefiles로 간단하게 만들어주었다.

 

2. 파일 이동 코드구현

moveFiles 폴더안에 A, B폴더를 생성해주었다.

1. A폴더, B폴더가 있는지 확인 후

2. A폴더에 파일이 있는지 확인 후

3. B폴더로 이동할 것이다.

파일관련 작업은 거의 java의 File클래스와 메소드를 사용한다.

구현 코드


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSource;

public class Main {

	public static void main(String[] args) {
		System.out.println("Start project!");

		// 1. A폴더, B폴더가 있는지 확인
		
		// 파일 객체 생성
		File fileA = new File("A");
		File fileB = new File("B");
		
		if(fileA.isDirectory() && fileB.isDirectory()) {
			
			// 2. A폴더에 파일이 있는지 확인 후
			File[] filesA =  fileA.listFiles();
			
			for(File oldFile : filesA){
				
				if(oldFile.isFile()){
					System.out.println("file name : "+ oldFile.getName());
					
					// 3. B폴더로 이동할 것이다.
					InputStream fin = null;
					OutputStream fout = null;
					
					byte[] b = new byte[1024];
					
					String dest = fileB.getPath() + "/" + oldFile.getName();
					System.out.println("destination : " + dest);
					
					File newFile = new File(dest);
					
					try {
						fin = new FileInputStream(oldFile);
						fout = new FileOutputStream(newFile);
						
						int read = 0;
						while((read = fin.read(b, 0, b.length)) != -1){
							fout.write(b, 0, read);
						}
						
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					} finally {
						try {
							fin.close();
							fout.close();
							
							System.out.println("old file exists? : " + oldFile.exists());
							System.out.println("delete success? : " + oldFile.delete());

						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				} // if end
			} // for end
		}
		
		System.out.println("Done!");
	}
}

파일을 이동하는 여러 방법이 있지만, 위의 방법은 단순히 파일의 바이트를 읽어서 다른 폴더에 쓴 것이기 때문에, 마지막에 A폴더에 존재하는 파일을 삭제해줘야 했다. 그래서 write()메서드로 쓰고 난 후 oldFile.delete()메서드를 사용했는데, 삭제가 안되는 것이다. 확인해보니 fin.close() 전에 사용하고 있어서 스트림이 닫히지 않은 상태였기 때문에 삭제가 안 되었던 거였다. 파일의 삭제를 가장 후 순위로 옮기고 기존파일 삭제까지 성공했다.

 

사용한 메소드, 개념 정리 

File 클래스는 입출력과 관련된 java.io 패키지에 들어있으며, 실제 파일이 가지고 있는 데이터를 다루기 위한 클래스이다. 직접적으로 파일의 내용을 수정할 수는 없다. 디스크에 있는 파일의 정보를 가져오거나 추가, 삭제를 한다.

isDirectory() : 생성된 파일 객체가 폴더인지를 확인할 수 있는 메소드로, 파일 객체를 생성해 준 경로에 폴더존재해야 true를 반환한다.

listFiles() : 폴더 내의 파일,폴더들의 절대 경로를 배열형태로 반환한다. 만약 폴더가 아니거나 I/O에러가 발생하면 null값을 반환한다. 해당 폴더에 파일,폴더가 하나도 없으면 empty상태가 된다.

FileInputStream, FileOutputStream : 입출력을 담당하는 스트림 중에서도 파일을 다루는 입출력 스트림이다.

InputStream.read(byte[] b, int off, int len) : b는 읽을 바이트배열, off는 b배열의 읽을 시작점, len은 읽을 바이트의 maximum number(어디까지 읽을지)를 의미한다. read()메소드를 사용해 읽다가 모두 읽으면 -1을 반환한다. 

OutputStream.write(byte[] b, int off, int len) : b(버퍼)에 담긴 데이터를, off부터, len 길이만큼 outstream에 쓴다. 보통 read()메소드를 이용해 읽은 수를 len에 넣는다

delete() : 파일을 삭제하며, 삭제 성공시 true, 실패시 false를 반환한다.

 

보완할 점

1. 운영체제에 맞는 파일 구분자 추가

- 현재 이동할 파일의 경로 + "/" + 파일 이름으로 경로를 세팅해주고 있다. 나는 윈도우 운영체제에서 개발하고 있어서 문제없이 작동하고 있지만, 리눅스 서버에선 파일 구분자가 다르므로 경로가 제대로 설정되지 않을 것이다. 어떤 운영체제에서도 맞는 경로일 수 있도록, 파일 구분자 메소드를 이용해서 개선해야 한다.

2. 파일 이동중에 IO문제가 생겼을 경우

- 현재 그냥 try-catch로 에러처리 해주고 있지만, 더 상세한 처리가 필요하다. 복사중에 문제가 생기면 A폴더의 파일을 삭제하지 않는 처리가 추가되야 할 것 같다.

 

향후 개선사항

1. maven으로 관리

 - 아직 배포하지는 않았지만, 현재 라이브러리 파일을 폴더에 넣고 build path로만 관리하고 있다. 혼자 개발하기는 하지만 만약 협업을 한다는 것을 가정해서 maven을 사용해서 라이브러리를 관리하고 배포까지 하는게 어떨까 생각한다.

2. 파일 용량이 클때 좀더 빨리 이동하는법

 - 지금은 간단한 csv파일만 이동했지만, 용량이 큰 엑셀 파일을 이동시킬 때를 대비해 bufferInputStream을 사용하거나 생각을 해볼필요가 있다.

3. 로그 관리

- 현재 파일이 이동되면 console로만 확인할 수 있는데, 만약 배포해서 윈도우에서 돌아갈 경우 진행사항이 어떻게 되는지 확인할 방법이 없다. 로그파일을 만들어서 핵심 사항이 기록되면 좋을 것 같다.

 


깃허브 주소 : https://github.com/hyojinsim90/fileDemonProject