본문 바로가기
JAVA공부/0-자바기초(초급자)

[File] 파일클래스를 이용한 파일탐색기 기능구현-자바의 파일입출력과 디렉토리 파일 알고리즘과 스택을 이해해보자

by 으노으뇨 2023. 12. 3.
728x90
반응형
SMALL

안녕하세요~! ㅎㅎㅎ

이번 포스팅은 자바의 기능 중 하나인 파일관련되어서 간단하게 파일 탐색기 기능을 구현하는것을 포스팅 해보겠습니다!

기능

> 최초 프로그램을 실행하면 탐색기기능을 사용할 것이냐고 물어본다.
> 검색을 시작할 드라이브를 선택하도록 함
> 탐색기 기능시작 
> 디렉터리 이동시 해당 디렉터리 폴더/파일명을 나열
> 폴더이름 입력하면 해당 폴더 진입
> 파일이름 입력하면 파일이라고 화면에 출력
> 상위 디렉터리로 돌아가고싶으면 " .. " 를 입력하여 상위 디렉터리로 이동

사용 기술

  1.  Java I/O (입출력 ) : 자바 파일 클래스를 사용하여 파일 시스템을 탐색하고 디렉토리 미치 파일을 조작
    파일 및 디렉토리 확인하고 디렉토리 목록 조회등을 위해 File 클래스 메서드활용
  2. 사용자 입력 처리 : 사용자 입력과 사용자의 선택에 따라 프로그램 진행 여부 및 대화형 프로그램 기술

 

학습 측면

  1. 파일 시스템 조작 : 파일 및 디렉토리의 경로를 구성하고, 해당 경로의 파일 및 디렉토리를 확인하는 방법을 배웠습니다.
  2. 사용자 입력처리 : 사용자 입력을 받고, 입력에 따라 프로그램이 동작하도록 대화형프로그램 구로 학습
  3. 디렉토리 탐색 알고리즘 : 스택을 활용하여 디렉토리를 탐색하는 방법을 이애하고 구현했습니다.

엄청간단하지만 재미있을 것 같아요!

먼저 사용할 File의 매서드입니다.!!

메서드 사용하는 이유
listRoots() 현재 클라이언트PC의 루트드라이브 정보를 File객체배열로 가져옵니다.
list() 해당 디렉터리의 목록을 String 형태로 가져옵니다.
exists() 존재유무 판단
isDirectory() 폴더 판단
isFile() 파일 판단
getParent() 상위 디렉터리주소를 반환 받습니다.

이렇게 간단하게 진행하겠습니다!!!


최초 소스

우선 소스부터 보여드리자면

package Java.File;

import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;

public class FileTrtmClass
{
	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		System.out.println("파일탐색기를 열으셨습니다.");
		System.out.println("파일탐색을 시작하시겠습니까?");
		boolean startFlag = true;
		while (startFlag)
		{
			String input = sc.next();
			if (input.equalsIgnoreCase("Y"))
			{
				startFlag = false;
			}
			else if (input.equalsIgnoreCase("N"))
			{
				System.out.println("종료합니다.");
				System.exit(0);
			}
			else
			{
				System.out.println("Y 또는 N을 눌러서 의사를 명확히 하세요.");
			}
		}
		String rootPath = "";
		boolean rootFlag = true;
		File ROOTS[] = File.listRoots();
		while (rootFlag)
		{
			for (File f : ROOTS)
			{
				System.out.print(f.getPath() + "\t");
			}
			System.out.println("찾으실 드라이브를 선택해주세요.");
			String input = sc.next();
			for (int i = 0; i < ROOTS.length; i++)
			{
				if (input.equalsIgnoreCase(ROOTS[i].getPath()))
				{
					rootPath = ROOTS[i].getPath();
					rootFlag = false;
				}
			}
		}
		ArrayList<String> heap = new ArrayList<String>();
		File file = new File(rootPath);
		boolean progressFlag = true;
		while (progressFlag)
		{
			String path = file.getPath();
			System.out.println("현재는 디렉터리는 " + path + " 입니다.");
			System.out.println("현재디렉터리 리스트 : ");
			for (String str : file.list())
			{
				System.out.print(str + "\t");
			}
			System.out.println();
			System.out.println("여기서 탐색할 파일/폴더를 입력하세요");
			String input = sc.next();
			for (int i = 0; i < file.list().length; i++)
			{
				if (file.list()[i].equals(input))
				{
					path += "/" + input;
					break;
				}
				else if (input.equals(".."))
				{
					if (heap.size() == 0)
					{
						System.out.println("여기가 루트디렉터리입니다. 더 이상 진행 할 수 없습니다.");
						break;
					}
					else
					{
						heap.remove(heap.size() - 1);
						path = file.getParent();
						break;
					}
				}
				else
				{
					continue;
				}
			}
			File tmpFile = new File(path);
			if (tmpFile.exists())
			{
				if (tmpFile.isDirectory())
				{
					heap.add("/" + input);
					file = tmpFile;
				}
				else if (tmpFile.isFile())
				{
					System.out.println("파일입니다.");
				}
				else
				{
					System.out.println("알 수 없는 경로입니다.");
				}
			}
		}
	}
}

이렇습니다. 나중에 제가 간단하게 설명하고 절차 설명후 리팩토링 또는 조금 다듬어서 마지막에 다시 올려드리겠습니다

급하거나 소스만 필요하시다면 위소스가져가서 사용하시고, 좀더 다듬어진 깔끔한것을 참고하시고 싶으시다면 조금 길지만 같이 이 포스팅을 보고 끝까지 내리시면 찾으실수 있을 것같습니다...

저도 작성하면서 진행하는지라 ㅠ


설명

우선 프로그램 실행시 파일탐색을 시작하겠냐고 물어봅니다.

 y를 입력하면 다음단계로, n을 입력하면 종료됩니다. 그리고 다른값을 입력하면 다시 물어봅니다. 

Y가 아닌 다른값을 입력한 모습

이제 Y를 눌러서 진행을 하면 다음 물음을 받습니다.

해당부분은 

이렇게 관리하고 있습니다. 

우선

static File ROOTS[] = File.listRoots();

File의 listRoots()는 File을 배열형태로 리턴해줍니다.

해당 ROOTS 객체의 값입니다. 그래서 원하는 드라이브 디렉터리를 선택하면 다음단계로 진행되고, 해당 값이 없다면 계속 물어봅니다.

만약 옳게된 C:\ 를 입력한다면 해당드라이브로 이동하게됩니다. 그리고 해당 디렉터리의 파일 및 폴더 리스트를 모두 보여줍니다.

저의 경우 콘솔창에 해당 파일/폴더 리스트들이 모두 나오고 짤릴정도로 많아서 짤려서 나오고있습니다. 

해당 리스트들이 출력되는 소스는 

이렇습니다.

이제 출력된 리스트중에서 실제 있는 폴더이름을 입력해보겠습니다.

이렇게 헤당 폴더로 진입했습니다.

해당소스는 아래와 같습니다.

여기서 잠깐 설명드리자면

입력된 문자열이 존재하는 폴더고 리스트에 있으면 우선 현재의 경로에 추가하고 heap메모리를 구현한 List객체에 해당 입력값을 추가하고 다음단계로 넘깁니다.

그런데 만약 입력된 값이 상위 디렉터리로 이동하는 " .. "가 입력된다면 

heap을 하나 지우고 경로를 상위 디렉터리로 설정합니다. 

또는 해당 리스트에 없는 파일을 문자열로 입력한다면 다시 해당 부분을 반혹하게됩니다.

아래는 실행화면입니다.

현재처럼 .. 을 눌렀을때 드라이브 디렉터리에서 상위로 진입하려한다면 더 이상 진행할수 없다고 안내합니다.

상위폴더로 이동할수 없는 드라이브 디렉터레에서 3DP > Net > 2101 이렇게 하위폴더 까지 들어오면

heap메모리( 제가 List형태로 만든...) 에 쌓이게되며

..을 통해 나가게 된다면

.. 을 하면서 나가다보면 힙메모리도 하나씩 제거되는것을 볼 수 있습니다.

그래서 계속진행하면 다시 C드라이브로 돌아왔습니다.

이제 마지막입니다.

해당 입력된 값이 우선 실제 존재하는 파일인지  폴더인지 확인하고, 존재한다면 해당 입력값된 경로의 값이 폴더인지 파일인지 구분하는 로직입니다.

만약 존재하지않으면 다시 돌아가서 디렉터리를 출력합니다.

없는값을 입력했을 때
파일을 입력했을때

만약 폴더라면 아까 설명드린것과 같이 heap메모리에 추가합니다. 

파일의 경우 heap에 추가하지 않습니다, 만약 파일일때도 추가한다면

파일을 입력하고 .. 으로 상위 디렉터리로 이동시도하면 원활한 폴더이동이 되지않을 것입니다.

한번더 .. 을 입력해야한다거나 등등

여기까지 설명이었습니다.

긴 글 읽어주셔서 감사합니다. ㅠㅠ


안전하진 않지만 그냥 용한 소스

package Java.File;

import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;

public class FileTrtmClass
{
	static ArrayList<String> heap = new ArrayList<String>();
	static String path = "";
	static Scanner sc = new Scanner(System.in);
	static File file;
	public static void main(String[] args)
	{
		/* 실행할지 말지 결정을 얻어낸다. */
		checkUserPlayDecision();
		/* 드라이브를 선택한다.. */
		selectDrivePath();
		/* 탐색기를 연다. */
		openExplore();
		sc.close();
	}
	static void openExplore()
	{
		boolean progressFlag = true;
		while (progressFlag)
		{
			file = new File(path);
			/* 해당 디렉터리 리스트 출력 */
			showListDirectory();
			/* 해당 디렉터리 리스트 출력 */
			chageDirectory();
		}
	}

	static void showListDirectory()
	{
		System.out.println("현재는 디렉터리는 " + file.getAbsolutePath() + " 입니다.");
		System.out.println("현재디렉터리 리스트 : ");
		for (String str : file.list())
		{
			System.out.print(str + "\t");
		}
	}
	static void checkUserPlayDecision()
	{
		boolean startFlag = true;
		System.out.println("파일탐색기를 열으셨습니다.");
		System.out.println("파일탐색을 시작하시겠습니까?");
		while (startFlag)
		{
			String input = sc.next();
			if (input.equalsIgnoreCase("Y"))
			{
				startFlag = false;
			}
			else if (input.equalsIgnoreCase("N"))
			{
				System.out.println("종료합니다.");
				System.exit(0);
			}
			else
			{
				System.out.println("Y 또는 N을 눌러서 의사를 명확히 하세요.");
			}
		}
	}
	static void selectDrivePath()
	{
		boolean rootFlag = true;
		File ROOTS[] = File.listRoots();
		while (rootFlag)
		{
			for (File f : ROOTS)
			{
				System.out.print(f.getPath() + "  ");
			}
			System.out.println("찾으실 드라이브를 선택해주세요.");
			String input = sc.next();
			for (int i = 0; i < ROOTS.length; i++)
			{
				String rootPath = ROOTS[i].getPath();
				if (input.equalsIgnoreCase(rootPath) || input.equalsIgnoreCase(rootPath.replace("\\", ""))
						|| input.equalsIgnoreCase(rootPath.replace("\\", "").replace(":", "")))
				{
					path = ROOTS[i].getPath();
					rootFlag = false;
				}
			}
		}
	}
	static void chageDirectory()
	{
		System.out.println();
		System.out.println("여기서 탐색할 파일/폴더를 입력하세요");
		String input = sc.next();
		for (int i = 0; i < file.list().length; i++)
		{
			if (file.list()[i].equals(input))
			{
				checkUserInputFileDirectory("/" + input);
				break;
			}
			else if (input.equals(".."))
			{
				if (heap.size() == 0)
				{
					System.out.println("여기가 루트디렉터리입니다. 더 이상 진행 할 수 없습니다.");
					break;
				}
				else
				{
					heap.remove(heap.size() - 1);
					path = file.getParent();
					break;
				}
			}
			else
			{
				continue;
			}
		}
	}
	static void checkUserInputFileDirectory(String input)
	{
		File tmpFile = new File(path + input);
		if (tmpFile.exists())
		{
			if (tmpFile.isDirectory())
			{
				heap.add("/" + input);
				path = tmpFile.getAbsolutePath();
			}
			else if (tmpFile.isFile())
			{
				System.out.println("파일입니다.");
			}
			else
			{
				System.out.println("알 수 없는 경로입니다.");
			}
		}
	}
}

 

728x90
반응형
LIST

댓글