Lab #2 ( 디렉토리안에이미지파일포맷변환프로그램 ) 2017 학년도 1 학기 JAVA 프로그래밍 II 514770-1 2017 년봄학기 3/22/2017 박경신 기존요구사항분석 Lab #1은 inputimagefile, outputimagefile, format 에따라이미지파일포맷을변환시켜줌 - 최소 jpg, png, gif 영상포맷지원 ImageConverter 클래스는이미지파일포맷변환 (convert) 기능제공 ImageConverterTest 클래스는입력이미지파일명 (inputimagefile), 출력이미지파일명 (outputimagefile), 이미지포맷 (format) 을입력받아서변환하는메인프로그램 사용자가지정한 특정폴더 안에 특정영상포맷 을 다른영상포맷 으로변환 사용자가지정한폴더에는원본영상포맷이아닌파일들이있는경우변환처리안하고그대로둠 지정된폴더안에서브폴더가있다면, 그안에있는특정영상포맷도동일하게변환 commands.ini 텍스트파일로입력받는기능 기초문법, array, for-each, parameter passing, file/directory, recursive call String, File, BufferedReader Lab #1: Image File Convert Lab #2: Directory Image File Convert imagedir inputimagefile outputimagefile format C:/JAVA/IMG1.JPG C:/JAVA/PIC1.png png imagefileext format IMG1.png IMG2.png IMG3.png IMG4.png IMG5.png
Code Block 여러명령문을논리적으로결합해야할때중괄호 ({ ) 를사용하여명령문그룹을만들어표현 - 이러한명령문그룹을코드블록 (code block) 이라고함 코드블록안에는변수를선언할수있고, 다른코드블록을포함할수도있음 public class Example { public static void main(string[] args) { int outer; { int inner; outer = 1; inner = 2; outer = 5; //inner = 10; 내부코드블록 // 오류 main() 메소드코드블록 Example 클래스코드블록 Lab #2_1, For-each, Parameter Passing Lab#1_5 에서 inputimagefile, outputimagefile, format 를 String[] commands 로입력받아서처리 static String inputimagefile = "C:/Java/IMG1.jpg"; static String outputimagefile = "C:/Java/IMG1.png"; static String format = "png"; // array of strings static String[] commands = new String[3]; commands[0] = "C:/JAVA/IMG1.jpg"; commands[1] = "C:/JAVA/IMG1.png"; commands[2] = "png"; Lab#1_5 에서 boolean getcommands(string[] commands) 에서는 commands 로사용자입력을받아옴 Java2-lab2_1 폴더에저장후제출 배열 () 여러개의데이터를같은이름으로활용할수있도록해주는자료구조 인덱스 (Index, 순서번호 ) 와인덱스에대응하는데이터들로이루어진자료구조 배열을이용하면한번에많은메모리공간선언가능 배열은같은타입의데이터들이순차적으로저장되는공간 원소데이터들이순차적으로저장됨 인덱스를이용하여원소데이터접근 반복문을이용하여처리하기에적합한자료구조 ( 주로 for 또는 for-each 반복문과많이사용됨 ) 배열인덱스 0부터시작 인덱스는배열의시작위치에서부터데이터가있는상대위치 자바배열의필요성과모양
배열선언과배열생성의두단계필요 배열선언 배열생성 int char 선언과초기화 int[]; char[]; int = new int[10]; char = new char[20]; 또는 또는 int[] char[] 배열생성과값초기화 // 총10개의정수배열생성및값초기화 int int[] = {0,1,2,3,4,5,6,7,8,9; int; char; int int[] = new int[10]; char char[] = new char[20]; 배열선언과생성 잘못된배열선언 //int int[10]; // 컴파일오류. 배열의크기를지정할수없음 배열을초기화하면서생성한결과 배열참조 생성된 1개의배열을다수의레퍼런스가참조가능
배열원소접근 반드시배열생성후접근 int int []; // 배열선언 int[4] = 8; // 오류, int 배열의메모리가할당되지않았음 배열변수명과 [] 사이에원소의인덱스를적어접근 배열의인덱스는 0 부터시작 배열의마지막항목의인덱스는 ( 배열크기 1) int[] int; int = new int[10]; int[3]=6; // 배열에값을저장 int n = int[3]; // 배열로부터값을읽음 배열인덱스 인덱스는 0부터시작하며마지막인덱스는 ( 배열크기 -1) 인덱스는정수타입만가능 int int [] = new int[5]; // 인덱스는 0~4 까지가능 int n = int[-2]; // 실행오류. -2 는인덱스로적합하지않음 int m = int[5]; // 실행오류. 5 는인덱스의범위 (0~4) 를넘었음 배열의크기 배열의크기는배열레퍼런스변수를선언할때결정되지않음 배열의크기는배열생성시에결정되며, 나중에바꿀수없음 배열의크기는배열의 length 필드에저장 int size = int.length; & For-each For-each 문 배열이나나열 (enumeration) 의각원소를순차적으로접근하는데유용한 for 문 int[] num = { 1,2,3,4,5 ; int sum = 0; // 반복될때마다 k는 num[0], num[1],..., num[4] 값으로설정 for (int k : num) sum += k; 합은 15 System.out.println(" 합은 " + sum); String names[] = { " 사과 ", " 배 ", " 바나나 ", " 체리 ", " 딸기 ", " 포도 " ; // 반복할때마다 s는 names[0], names[1],..., names[5] 로설정 for (String s : names) System.out.print(s + " "); 사과배바나나체리딸기포도 메소드에서배열리턴 메소드의배열리턴 배열의레퍼런스만리턴 메소드의리턴타입 메소드가리턴하는배열의타입은리턴받는배열타입과일치 리턴타입에배열의크기를지정하지않음 Return type Method name int[] make() { int temp[] = new int[4]; return temp; return
매개변수에배열이전달되는경우 매개변수에배열이전달되는경우는배열의 reference 가복사 Parameter Passing Primitive Type 자바의인자전달방식 (Parameter Passing) 값에의한호출 (Pass-by-value) 기본타입 (Primitive Type: 예를들어 int, double, ) 의값을전달하는경우 값이복사되어전달 메소드의매개변수가변경되어도호출한실제인자값은변경되지않음 2 3 4 5 6 Parameter Passing Reference Type 자바의인자전달 (Parameter Passing) 방식 객체 (class object) 혹은배열 (array) 을전달하는경우 객체나배열의레퍼런스만전달 (Pass-by-reference) 객체혹은배열이통째로복사되어전달되는것이아님 메소드의매개변수와호출한실인자가객체나배열을공유하게됨 void assign(int[] values) { for (int i=0; i<values.length; i++) { values[i] = i; // values 배열에 0~9 까지값을넣어줌 int[] int = new int[10]; // create 10 integer array assign(int); for (int v : int) { System.out.println(v); Lab #2_2 String, class Lab#2_1에서 inputdir, imagefileext, format 입력을받아서처리 Lab#2_1에서 String[] commands는 imagedir, imagefileext, format String[] commands = { C:/JAVA, jpg, png ; //commands[0] 은 특정폴더 (imagedir) //commands[1] 은 특정영상포맷 (imagefileext) //commands[2] 는 원하는다른영상포맷 (format) Lab#2_1에서 UserInput 클래스작성 boolean getcommands(string[] commands) 에서는사용자로부터 특정폴더 (imagedir), 특정영상포맷 (imagefileext), 원하는다른영상포맷 (format) 을입력받음 Java2-lab2_2 폴더에저장후제출
String static String[] commands = {"C:/JAVA", "jpg", "png"; // commands[0] 은 imagedir // commands[1] 은 imagefileext // commands[2] 는 format UserInput.getCommands(commands); String inputimagefile = commands[0] + "/IMG1." + commands[1]; // 기본 C:/JAVA/IMG1.jpg String outputimagefile = commands[0] + "/PIC1." + commands[2]; // 기본 C:/JAVA/PIC1.png String format = commands[2]; // 기본 png // convertby 메소드는 inputimagefile, outputimagefile, format 을입력으로받아이미지변환 convertby(inputimagefile, outputimagefile, format); Lab #2_3 File/Directory, String substring/contains Lab#2_2 에서사용자가지정한특정디렉토리 (inputdir) 안에있는모든특정이미지파일 (imagefileext) 를다른이미지포맷 (format) 으로모두변환 Lab#2_2 에서 boolean convertimagesindirectory(string dirpath, String ext, String format) 메소드작성 디렉토리에서파일목록을읽고원하는확장자를골라서이미지포맷변환 Java2-lab2_3 폴더에저장후제출 File 클래스 File 클래스생성자와주요메소드 File 클래스 파일의경로명을다루는클래스 java.io.file 파일과디렉터리경로명의추상적표현 파일이름변경, 삭제, 디렉터리생성, 크기등파일관리 File 객체는파일읽고쓰기기능없음 파일입출력은파일입출력스트림이용
파일목록을읽고원하는확장자골라내기 파일목록뽑기 파일목록의배열에서어떻게원하는파일만뽑아낼까? 폴더 ( 디렉토리 ) 인지파일인지확인 파일이면확장자가원하는파일인지확인 ( 문자열함수활용 ) import java.io.*; File dir = new File(dirPath); File[] files = dir.listfiles(); // 파일목록전체를배열로넘겨줌 for (File file : files) { if (file.isdirectory()) System.out.println( directory: + file.getcanonicalpath()); else if (file.isfile()) System.out.println( file: + file.getname()); 폴더 ( 디렉토리 ) 또는파일확인 String 메소드 String substring(int beginindex) 는 beginindex부터나머지부분을 string으로반환 String substring(int beginindex, int endindex) 는 beginindex부터 endindex까지부분을 strin으로반환 String dir = "C:/JAVA"; String filename = "IMG1.jpg"; String fullpath = dir + "/" + filename; String ext = filename.substring(filename.lastindexof('.') + 1); String namewithoutext = filename.substring(0, filename.lastindexof('.')); System.out.println("fullPath=" + fullpath); // fullpath=c:/java/img1.jpg System.out.println("ext= + ext); // ext=jpg System.out.println("nameWithoutExt=" + namewithoutext); // namewithoutext=img1 폴더 ( 디렉토리 ) 또는파일확인 String 메소드 boolean contains(charsequence s) 는 s 를가지고있는지여부를 true/false 반환 int lastindexof(string str) 는 str 을가지고있는 lastindex 값을반환 String dir = "C:/JAVA"; String filename = "IMG1.jpg"; String fullpath = dir + "/" + filename; if (filename.contains("jpg")) { String format = "png"; String newfilename = fullpath.substring(0, fullpath.lastindexof('.')+1) + format; System.out.println("newFilename=" + newfilename); // newfilename= C:/JAVA/IMG1.png Lab #2_4 FileI/O Lab#2_3 에서 inputdir, imagefileext, forma 를 command.ini 파일에서읽어들임 FileInput 클래스작성 boolean getcommandsfromfile(string filename, String[] commands) 는 filename 텍스트파일을읽어서 특정폴더 (imagedir), 특정영상포맷 (imagefileext), 원하는다른영상포맷 (format) 을입력받음 Java2-lab2_4 폴더에저장후제출
바이트스트림클래스 바이트스트림 바이트단위의바이너리값을읽고쓰는스트림 바이트스트림클래스 java.io 패키지에포함 InputStream/OutputStream 추상클래스 바이트스트림을다루는모든클래스의슈퍼클래스 FileInputStream/FileOutputStream 파일로부터바이트단위로읽거나저장하는클래스 바이너리파일의입출력용도 DataInputStream/DataOutputStream 자바의기본데이터타입의값 ( 변수 ) 을바이너리값그대로입출력 문자열도바이너리형태로입출력 문자스트림클래스 문자스트림 유니코드로된문자를입출력하는스트림 문자스트림은이미지, 동영상과같은바이너리데이터는입출력할수없음 - 문자스트림은문자데이터만입출력가능 문자스트림을다루는클래스 Reader/Writer java.io 패키지에포함 추상클래스. 문자스트림을다루는모든클래스의슈퍼클래스 InputStreamReader/OutputStreamWriter 바이트스트림과문자스트림을연결시켜주는다리역할 지정된문자집합이용 InputStreamReader : 바이트를읽어문자로인코딩 OutputStreamWriter : 문자를바이트로디코딩하여출력 FileReader/FileWriter 텍스트파일에서문자데이터입출력 버퍼입출력스트림클래스 버퍼스트림 버퍼를가진스트림 입출력데이터를일시적으로저장하는버퍼를이용하여입출력효율개선 버퍼입출력의목적 입출력시운영체제의 API 호출횟수를줄여입출력성능개선 출력시여러번출력되는데이터를버퍼에모아두고한번에장치로출력 입력시입력데이터를버퍼에모아두고한번에프로그램에게전달 바이트버퍼스트림클래스 BufferedInputStream와 BufferedOutputStream 바이트단위의바이너리데이터 (Binary Data) 를처리하는버퍼스트림 문자버퍼스트림클래스 BufferedReader와 BufferedWriter 유니코드의문자데이터 (Text Data) 만처리하는버퍼스트림 텍스트파일읽기 BufferedReader 클래스를사용한텍스트파일 read import java.io.*; public class BufferedReaderExample { public static void main(string args[])throws Exception{ FileReader fr = new FileReader( C:/test.txt"); BufferedReader br = new BufferedReader(fr); int i; while((i=br.read())!=-1){ System.out.print((char)i); br.close(); fr.close();
텍스트파일읽기 BufferedReader 클래스를사용하여파일을한줄씩읽어서 lines 배열에저장 import java.io.*; public class BufferedReaderExample2 { static String[] lines = new String[10]; // 10 개의라인배열 public static void main(string args[])throws Exception{ BufferedReader br = new BufferedReader(new FileReader("C:/test.txt")); int i = 0; String line = ""; while ((line=br.readline())!= null){ lines[i++] = line; br.close(); for (String l : lines) System.out.println(l); // lines 배열출력 Lab #2_5 Recursive Call Lab#2_4에서만약사용자가지정한디렉토리안에서브디렉토리가존재한다면그안에있는이미지파일이존재한다면이미지파일포맷변환을진행 FileInput 클래스의 boolean getcommandsfromfile(string filename, String[] commands) 메소드는 TEXT 파일을읽어서 commands로넘겨줌 Java2-lab2_5 폴더에저장후제출 재귀호출 (Recursive call) 함수에서자기자신을다시부르는것을재귀호출 (recursive call) 이라고함 함수내부에서사용되는지역변수의값들은자기자신을호출하기전의값들을호출후에도그대로보존함 ( 자기자신을다시부르더라도새로운지역변수들이생성되는것을생각하면됨 ) 재귀호출을빠져나갈수있도록검사하고종료하는부분이반드시존재해야함 ( 재귀호출탈출조건 ) 재귀호출의사용예 : 팩토리얼 (factorial), 최대공약수, 피보나치수열, 등 재귀호출 팩토리얼을구현하는함수작성 n! = n x (n 1) x (n 2) x x 1 = n x (n 1)! (where n >= 1) 알고리즘 만약 n이 1보다작거나같으면값 1을반환 만약 n이 1보다크다면 n * (n 1)! 을반환 static int factorial(int n){ if (n == 0) return 1; else return(n * factorial(n-1)); factorial(1); // 1 factorial(5); // 5! = 5 * 4 * 3 * 2 * 1 = 120
재귀호출 최대공약수 (Greatest Common Divisor) 알고리즘 b = 0 이면 a 반환 // 나머지가 0 이되면연산을중지 아니면, gcd(b, a%b) 반환 static int gcd(int a, int b) { if (b == 0) return a; // 재귀호출탈출조건 else return gcd(b, a%b); gcd(12, 4); // 4 gcd(12, 18); // 6 재귀호출 피보나치수열 1 1 2 3 5 8 13 21 34 55 89 1항과 2항은 1 3항이후부터의 n항은 (n 1) 항 + (n 2) 항 f(n) = f(n 1) + f(n 2) static int fibonacci(int n) { if (n < 1) return n; // 재귀호출탈출조건 else return fibonacci(n 1) + fibonacci(n 2); fibonacci(1) // 1 fibonacci(2) // 1 fibonacci(3) // 2 fibonacci(6) // 8 과제제출 사용자가지정한폴더 (C:/JAVA) 에는서브폴더 (C:/JAVA/PHOTO) 가존재함 폴더안에는 jpg, png, gif 포맷의파일들이존재함 ( 그외의다른종류의파일은없음 ) Lab02_1 ~ Lab02_5 와보고서를전체적으로묶어서 e-learning 에과제제출