개발자입니다
[Java] 예제 소스 정리 - 파일 입출력 본문
com/eomcs/io/ex01~15
예제 소스 정리
파일 입출력
com/eomcs/io/ex01
폴더 정보 조회 - java.io.File 클래스
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0110 {
public static void main(String[] args) throws Exception {
// File 클래스
// => 디렉토리나 파일을 다룰 때 사용하는 클래스이다.
// => 디렉토리나 파일을 생성, 삭제, 변경할 수 있다.
// 현재 디렉토리를 조회
// => '.' 으로 표현한다.
// => JVM을 실행하는 위치가 현재 폴더이다.
// => 이클립스 : 프로젝트 디렉토리를 가리킨다.
// => 콘솔 : 현재 명령어를 실행하는 위치를 가리킨다.
//
File currentDir = new File("./src/main/java");
System.out.printf("폴더명: %s\n", currentDir.getName());
System.out.printf("경로: %s\n", currentDir.getPath());
System.out.printf("절대경로: %s\n", currentDir.getAbsolutePath());
System.out.printf("계산된 절대경로: %s\n", currentDir.getCanonicalPath());
System.out.printf("총크기: %d\n", currentDir.getTotalSpace());
System.out.printf("남은크기: %d\n", currentDir.getFreeSpace());
System.out.printf("가용크기: %d\n", currentDir.getUsableSpace());
System.out.printf("디렉토리여부: %b\n", currentDir.isDirectory());
System.out.printf("파일여부: %b\n", currentDir.isFile());
System.out.printf("감춤폴더: %b\n", currentDir.isHidden());
System.out.printf("존재여부: %b\n", currentDir.exists());
System.out.printf("실행가능여부: %b\n", currentDir.canExecute());
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0120 {
public static void main(String[] args) throws Exception {
// File 클래스
// => 파일이나 디렉토리 정보를 관리
// => 파일이나 디렉토리를 생성,삭제,변경
// 상위 폴더 정보 조회
// - ".." 으로 경로를 표시한다.
//
File currentDir = new File("./src/main/java/../../test/java");
System.out.printf("폴더명: %s\n", currentDir.getName());
System.out.printf("경로: %s\n", currentDir.getPath());
System.out.printf("절대경로: %s\n", currentDir.getAbsolutePath());
System.out.printf("계산된 절대경로: %s\n", currentDir.getCanonicalPath());
System.out.printf("총크기: %d\n", currentDir.getTotalSpace());
System.out.printf("남은크기: %d\n", currentDir.getFreeSpace());
System.out.printf("가용크기: %d\n", currentDir.getUsableSpace());
System.out.printf("디렉토리여부: %b\n", currentDir.isDirectory());
System.out.printf("파일여부: %b\n", currentDir.isFile());
System.out.printf("감춤폴더: %b\n", currentDir.isHidden());
System.out.printf("존재여부: %b\n", currentDir.exists());
System.out.printf("실행가능여부: %b\n", currentDir.canExecute());
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0130 {
public static void main(String[] args) throws Exception {
// File 클래스
// => 파일이나 디렉토리 정보를 관리
// => 파일이나 디렉토리를 생성,삭제,변경
// 존재하지 않는 폴더 조회
//
File currentDir = new File("./haha");
System.out.printf("폴더명: %s\n", currentDir.getName());
System.out.printf("경로: %s\n", currentDir.getPath());
System.out.printf("절대경로: %s\n", currentDir.getAbsolutePath());
System.out.printf("계산된 절대경로: %s\n", currentDir.getCanonicalPath());
// 존재하지 않는 폴더인 경우 크기는 0이다.
System.out.printf("총크기: %d\n", currentDir.getTotalSpace());
System.out.printf("남은크기: %d\n", currentDir.getFreeSpace());
System.out.printf("가용크기: %d\n", currentDir.getUsableSpace());
// 존재하지 않는 폴더인 경우 정보를 알아낼 수 없다. 모두 false
System.out.printf("디렉토리여부: %b\n", currentDir.isDirectory());
System.out.printf("파일여부: %b\n", currentDir.isFile());
System.out.printf("감춤폴더: %b\n", currentDir.isHidden());
System.out.printf("존재여부: %b\n", currentDir.exists());
System.out.printf("실행가능여부: %b\n", currentDir.canExecute());
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0210 {
public static void main(String[] args) throws Exception {
// File 클래스
// => 파일이나 디렉토리 정보를 관리
// => 파일이나 디렉토리를 생성,삭제,변경
// 현재 파일 정보 조회
//
File file1 = new File("./src/main/java/Hello2.java");
System.out.printf("파일명: %s\n", file1.getName());
System.out.printf("파일크기: %d\n", file1.length());
System.out.printf("경로: %s\n", file1.getPath());
System.out.printf("절대경로: %s\n", file1.getAbsolutePath());
System.out.printf("계산된 절대경로: %s\n", file1.getCanonicalPath());
// 존재하지 않는 폴더인 경우 크기를 알아낼 수 없다.
System.out.printf("총크기: %d\n", file1.getTotalSpace());
System.out.printf("남은크기: %d\n", file1.getFreeSpace());
System.out.printf("가용크기: %d\n", file1.getUsableSpace());
// 존재하지 않는 폴더인 경우 정보를 알아낼 수 없다. 모두 false
System.out.printf("디렉토리여부: %b\n", file1.isDirectory());
System.out.printf("파일여부: %b\n", file1.isFile());
System.out.printf("감춤여부: %b\n", file1.isHidden());
System.out.printf("존재여부: %b\n", file1.exists());
System.out.printf("실행가능여부: %b\n", file1.canExecute());
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0220 {
public static void main(String[] args) throws Exception {
// File 클래스
// => 파일이나 디렉토리 정보를 관리
// => 파일이나 디렉토리를 생성,삭제,변경
// 존재하지 않는 파일 정보 조회
//
File file1 = new File("./src/main/java/Hello100.java");
System.out.printf("파일명: %s\n", file1.getName());
System.out.printf("파일크기: %d\n", file1.length());
System.out.printf("경로: %s\n", file1.getPath());
System.out.printf("절대경로: %s\n", file1.getAbsolutePath());
System.out.printf("계산된 절대경로: %s\n", file1.getCanonicalPath());
// 존재하지 않는 폴더인 경우 크기를 알아낼 수 없다.
System.out.printf("총크기: %d\n", file1.getTotalSpace());
System.out.printf("남은크기: %d\n", file1.getFreeSpace());
System.out.printf("가용크기: %d\n", file1.getUsableSpace());
// 존재하지 않는 폴더인 경우 정보를 알아낼 수 없다. 모두 false
System.out.printf("디렉토리여부: %b\n", file1.isDirectory());
System.out.printf("파일여부: %b\n", file1.isFile());
System.out.printf("감춤여부: %b\n", file1.isHidden());
System.out.printf("존재여부: %b\n", file1.exists());
System.out.printf("실행가능여부: %b\n", file1.canExecute());
}
}
디렉토리 생성
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0310 {
public static void main(String[] args) throws Exception {
// 1) 생성할 디렉토리 경로 설정
// - 폴더 경로를 지정하지 않으면 현재 폴더를 의미한다.
//
File dir = new File("temp");
if (dir.mkdir()) { // 디렉토리 생성
System.out.println("temp 디렉토리를 생성하였습니다.");
} else {
System.out.println("temp 디렉토리를 생성할 수 없습니다.");
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0320 {
public static void main(String[] args) throws Exception {
File dir = new File("temp/a");
// 하위 디렉토리 생성하기
//
if (dir.mkdir()) {
System.out.println("temp/a 디렉토리를 생성하였습니다.");
} else {
System.out.println("temp/a 디렉토리를 생성할 수 없습니다.");
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0321 {
public static void main(String[] args) throws Exception {
File dir = new File("temp2/a");
// 존재하지 않는 폴더 아래에 새 폴더를 만들 때
// => 존재하지 않는 폴더가 자동 생성되지 않는다.
// => 따라서 그 하위 폴더를 생성할 수 없다.
//
if (dir.mkdir()) {
System.out.println("temp2/a 디렉토리를 생성하였습니다.");
} else {
System.out.println("temp2/a 디렉토리를 생성할 수 없습니다.");
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0322 {
public static void main(String[] args) throws Exception {
File dir = new File("temp2/a/b");
// 디렉토리를 생성할 때 존재하지 않는 중간 디렉토리도 만들고 싶다면,
// mkdirs()를 호출하라.
//
// mkdirs()
// - 지정된 경로에 디렉토리가 존재하지 않으면 그 디렉토리도 만든다.
//
if (dir.mkdirs()) {
System.out.println("temp2/a/b 디렉토리를 생성하였습니다.");
} else {
System.out.println("temp2/a/b 디렉토리를 생성할 수 없습니다.");
}
}
}
디렉토리 삭제
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0330 {
public static void main(String[] args) throws Exception {
File dir = new File("temp");
if (dir.delete()) {
System.out.println("temp 디렉토리를 삭제하였습니다.");
} else {
// 디렉토리 안에 파일이나 다른 하위 디렉토리가 있다면 삭제할 수 없다.
// 또한 존재하지 않는 디렉토리도 삭제할 수 없다.
System.out.println("temp 디렉토리를 삭제할 수 없습니다.");
}
}
}
파일 생성
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0410 {
public static void main(String[] args) throws Exception {
// 생성할 파일의 경로 설정
File file = new File("temp2/a/test.txt");
if (file.createNewFile()) { // 파일 생성
System.out.println("test.txt 파일을 생성하였습니다.");
} else {
// 이미 파일이 있다면 다시 생성할 수 없다.
// 해당 경로에 디렉토리가 없다면 파일을 생성할 수 없다. 예외 발생!
System.out.println("test.txt 파일을 생성할 수 없습니다.");
}
}
}
파일 삭제
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0420 {
public static void main(String[] args) throws Exception {
// 삭제할 파일의 경로 설정
File file = new File("temp2/a/test.txt");
if (file.delete()) { // 파일 삭제
System.out.println("test.txt 파일을 삭제하였습니다.");
} else {
// 존재하지 않는 파일은 삭제할 수 없다.
// 경로가 존재하지 않으면 당연히 그 경로에 파일이 없으니까 삭제할 수 없다.
System.out.println("test.txt 파일을 삭제할 수 없습니다.");
}
}
}
특정 폴더를 생성하여 그 폴더에 파일을 만든다.
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0430 {
public static void main(String[] args) throws Exception {
// 생성할 파일의 경로 설정
File file = new File("temp/b/test.txt");
// 디렉토리가 존재하지 않으면 파일을 생성할 수 없다.
// - 예외 발생!
if (file.createNewFile()) { // 파일 생성
System.out.println("test.txt 파일을 생성하였습니다.");
} else {
System.out.println("test.txt 파일을 생성할 수 없습니다.");
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0431 {
public static void main(String[] args) throws Exception {
// 생성할 파일의 경로 설정
File file = new File("temp/b/test.txt");
// 파일을 생성하기 전에 존재하지 않는 폴더를 생성하고 싶다면,
// String path = file.getParent(); // => temp/b
// File dir = new File(path);
File dir = file.getParentFile(); // 위의 코드와 같다.
System.out.println(dir.getCanonicalPath());
// 먼저 디렉토리를 생성한다.
if (dir.mkdirs()) {
System.out.println("디렉토리를 생성하였습니다.");
} else {
System.out.println("디렉토리를 생성할 수 없습니다.");
}
// 그런 후 파일을 생성한다.
if (file.createNewFile()) { // 파일 생성
System.out.println("파일을 생성하였습니다.");
} else {
System.out.println("파일을 생성할 수 없습니다.");
}
}
}
디렉토리에 들어 있는 파일이나 하위 디렉토리 정보 알아내기
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0510 {
public static void main(String[] args) throws Exception {
// 현재 폴더의 정보를 알아낸다.
File dir = new File(".");
// 현재 폴더에 있는 파일이나 하위 디렉토리 이름을 알아내기
String[] names = dir.list();
for (String name : names) {
System.out.println(name);
}
}
}
디렉토리에 들어 있는 파일이나 하위 디렉토리 정보 알아내기 II
package com.eomcs.io.ex01;
import java.io.File;
import java.sql.Date;
public class Exam0520 {
public static void main(String[] args) throws Exception {
File dir = new File(".");
// 파일이나 디렉토리 정보를 File 객체로 받기
// => File은 디렉토리와 파일을 통칭하는 용어다.
//
File[] files = dir.listFiles();
for (File file : files) {
System.out.printf("%s %s %12d %s\n",
file.isDirectory() ? "d" : "-",
new Date(file.lastModified()),
file.length(),
file.getName());
}
}
}
디렉토리에 들어있는 파일(디렉토리) 목록을 꺼낼 때 필터 적용하기
package com.eomcs.io.ex01;
import java.io.File;
import java.io.FilenameFilter;
public class Exam0610 {
public static void main(String[] args) throws Exception {
class JavaFilter implements FilenameFilter {
@Override
public boolean accept(File dir/* 부모 경로 */, String name /* 파일,디렉토리 이름 */) {
// 이 메서드는 list()에서 호출한다.
// 해당 폴더에 들어 있는 파일이나 디렉토리를 찾을 때 마다 호출한다.
// (하위 폴더 아래는 뒤지지 않는다)
// 이 메서드에서 해야 할 일은 찾은 파일이나 디렉토리를
// 리턴할 배열에 포함시킬지 여부이다.
// true를 리턴하면 배열에 포함되고,
// false를 리턴하면 배열에 포함되지 않는다.
// 파일,디렉토리 이름이 .java 로 끝나는 경우만 리턴 배열에 포함시키다.
if (name.endsWith(".java"))
return true; // 조회 결과에 포함시켜라!
return false; // 조회 결과에서 제외하라!
}
}
File dir = new File(".");
// => 확장자가 .java 인 파일의 이름만 추출하기
// 1) 필터 준비
JavaFilter javaFilter = new JavaFilter();
// 2) 필터를 사용하여 디렉토리의 목록을 가져오기
String[] names = dir.list(javaFilter);
for (String name : names) {
System.out.println(name);
}
// 문제점:
// - temp.java 는 디렉토리이다.
// - 현재의 필터는 파일 이름으로만 검사한다.
// - 파일인지 디렉토리인지 여부는 검사하지 않는다.
// - 해결책?
// 다음 예제를 보라!
}
}
package com.eomcs.io.ex01;
import java.io.File;
import java.io.FilenameFilter;
public class Exam0611 {
public static void main(String[] args) throws Exception {
class JavaFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
// 해당 이름이 디렉토리 이름인지 파일 이름인지 알아내려면
// File 객체를 생성해야 한다.
//
File file = new File(dir, name);
// 디렉토리 정보와 이름을 합쳐 파일 객체를 생성할 수 있다.
if (file.isFile() && name.endsWith(".java"))
return true; // 조회 결과에 포함시켜라!
return false; // 조회 결과에서 제외하라!
}
}
File dir = new File(".");
// => 확장자가 .java 인 파일의 이름만 추출하기
// 1) 필터 준비
JavaFilter javaFilter = new JavaFilter();
// 2) 필터를 사용하여 디렉토리의 목록을 가져오기
String[] names = dir.list(javaFilter);
for (String name : names) {
System.out.println(name);
}
}
}
디렉토리에 들어있는 파일(디렉토리) 목록을 꺼낼 때 필터 적용하기 II
package com.eomcs.io.ex01;
import java.io.File;
import java.io.FileFilter;
public class Exam0620 {
public static void main(String[] args) throws Exception {
class JavaFilter implements FileFilter {
@Override
public boolean accept(File file) {
// 이 메서드는 listFiles() 메서드에서 호출한다.
// 지정한 폴더에 들어 있는 파일이나 디렉토리를 찾을 때 마다 호출한다.
// 리턴 값 File[] 에 찾은 파일 정보를 포함시킬지 여부를 결정한다.
// true 이면 배열에 포함시키고,
// false 이면 배열에서 제외한다.
//
if (file.isFile() && file.getName().endsWith(".java"))
return true; // 조회 결과에 포함시켜라!
return false; // 조회 결과에서 제외하라!
}
}
File dir = new File(".");
// => 확장자가 .java 인 파일의 이름만 추출하기
// 1) 필터 준비
JavaFilter javaFilter = new JavaFilter();
// 2) 필터를 사용하여 디렉토리의 목록을 가져오기
File[] files = dir.listFiles(javaFilter);
for (File file : files) {
System.out.printf("%s %12d %s\n",
file.isDirectory() ? "d" : "-",
file.length(),
file.getName());
}
}
}
익명 클래스로 FileFilter 만들기
package com.eomcs.io.ex01;
import java.io.File;
import java.io.FileFilter;
public class Exam0630 {
public static void main(String[] args) throws Exception {
// 필터 객체를 한 개만 만들 것이라면
// 익명 클래스로 정의하는 것이 낫다.
//
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isFile() && file.getName().endsWith(".java"))
return true;
return false;
}
};
File dir = new File(".");
File[] files = dir.listFiles(filter);
for (File file : files) {
System.out.printf("%s %12d %s\n", file.isDirectory() ? "d" : "-", file.length(),
file.getName());
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
import java.io.FileFilter;
public class Exam0640 {
public static void main(String[] args) throws Exception {
File dir = new File(".");
// 익명 클래스를 정의할 때
// 객체를 사용할 위치에 익명 클래스를 정의하는 것이
// 코드를 더 읽기 쉽게 만든다.
//
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isFile() && file.getName().endsWith(".java"))
return true;
return false;
}
});
for (File file : files) {
System.out.printf("%s %12d %s\n", file.isDirectory() ? "d" : "-", file.length(),
file.getName());
}
}
}
람다로 FileFilter 만들기
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0650 {
public static void main(String[] args) throws Exception {
File dir = new File(".");
// 메서드 한 개짜리 인터페이스인 경우
// 람다(lambda) 문법을 사용하면 훨씬 더 간결하게 코드를 작성할 수 있다.
//
// lambda class
// => 메서드가 한 개짜리인 경우 lambda 표현식을 사용할 수 있다.
// => 문법:
// (파라미터, 파라미터, ...) -> 문장 한개
// (파라미터, 파라미터, ...) -> { 문장1; 문장2; 문장3;}
// () -> 문장 한개
// () -> {문장1; 문장2; 문장3;}
//
File[] files = dir.listFiles(file -> {
if (file.isFile() && file.getName().endsWith(".java"))
return true;
return false;
});
for (File file : files) {
System.out.printf("%s %12d %s\n", file.isDirectory() ? "d" : "-", file.length(),
file.getName());
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0651 {
public static void main(String[] args) throws Exception {
File dir = new File(".");
// 메서드 한 개짜리 인터페이스인 경우
// 람다(lambda) 문법을 사용하면 훨씬 더 간결하게 코드를 작성할 수 있다.
// => (조건) ? 값1 : 값2
File[] files = dir.listFiles(file ->
(file.isFile() && file.getName().endsWith(".java")) ? true : false);
for (File file : files) {
System.out.printf("%s %12d %s\n", file.isDirectory() ? "d" : "-", file.length(),
file.getName());
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0652 {
public static void main(String[] args) throws Exception {
File dir = new File(".");
// 메서드 한 개짜리 인터페이스인 경우
// 람다(lambda) 문법을 사용하면 훨씬 더 간결하게 코드를 작성할 수 있다.
// => expression 은 return 문장을 생략할 수 있다.
File[] files = dir.listFiles(file -> file.isFile() && file.getName().endsWith(".java"));
for (File file : files) {
System.out.printf("%s %12d %s\n", file.isDirectory() ? "d" : "-", file.length(),
file.getName());
}
}
}
활용: 필터와 Lambda 표현식을 사용하여 디렉토리 이름만 추출하라.
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0660 {
public static void main(String[] args) throws Exception {
File file = new File(".");
File[] files = file.listFiles(f -> f.isDirectory());
for (File f : files) {
System.out.printf("%s %12d %s\n",
f.isDirectory() ? "d" : "-",
f.length(),
f.getName());
}
}
}
활용 - 지정한 폴더 및 그 하위 폴더까지 모두 검색하여 파일 및 디렉토리 이름을 출력하라.
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0710_01 {
public static void main(String[] args) throws Exception {
// 결과 예)
// /Users/bitcamp/git/test
// src/
// main/
// java/
// com/
// Hello.java
// Hello2.java
// build.gradle
// settings.gradle
// Hello.java
// ...
File dir = new File(".");
System.out.println(dir.getCanonicalPath());
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0710_02 {
public static void main(String[] args) throws Exception {
// 결과 예)
// /Users/bitcamp/git/test
// src/
// main/
// java/
// com/
// Hello.java
// Hello2.java
// build.gradle
// settings.gradle
// Hello.java
// ...
File dir = new File(".");
System.out.println(dir.getCanonicalPath());
printList(dir);
}
static void printList(File dir) {
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0710_03 {
public static void main(String[] args) throws Exception {
// 결과 예)
// /Users/bitcamp/git/test
// src/
// main/
// java/
// com/
// Hello.java
// Hello2.java
// build.gradle
// settings.gradle
// Hello.java
// ...
File dir = new File(".");
System.out.println(dir.getCanonicalPath());
printList(dir);
}
static void printList(File dir) {
// 현재 디렉토리의 하위 파일 및 디렉토리 목록을 알아낸다.
File[] files = dir.listFiles();
// 리턴 받은 파일 배열에서 이름을 꺼내 출력한다.
for (File file : files) {
System.out.println(file.getName());
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0710_04 {
public static void main(String[] args) throws Exception {
// 결과 예)
// /Users/bitcamp/git/test
// src/
// main/
// java/
// com/
// Hello.java
// Hello2.java
// build.gradle
// settings.gradle
// Hello.java
// ...
File dir = new File(".");
System.out.println(dir.getCanonicalPath());
printList(dir);
}
static void printList(File dir) {
// 현재 디렉토리의 하위 파일 및 디렉토리 목록을 알아낸다.
File[] files = dir.listFiles();
// 리턴 받은 파일 배열에서 이름을 꺼내 출력한다.
for (File file : files) {
if (file.isDirectory() && !file.isHidden()) {
System.out.printf("%s/\n", file.getName());
} else if (file.isFile()) {
System.out.printf("%s\n", file.getName());
}
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0710_05 {
public static void main(String[] args) throws Exception {
// 결과 예)
// /Users/bitcamp/git/test
// src/
// main/
// java/
// com/
// Hello.java
// Hello2.java
// build.gradle
// settings.gradle
// Hello.java
// ...
File dir = new File(".");
System.out.println(dir.getCanonicalPath());
printList(dir);
}
static void printList(File dir) {
// 현재 디렉토리의 하위 파일 및 디렉토리 목록을 알아낸다.
File[] files = dir.listFiles();
// 리턴 받은 파일 배열에서 이름을 꺼내 출력한다.
for (File file : files) {
if (file.isDirectory() && !file.isHidden()) {
System.out.printf("%s/\n", file.getName());
printList(file); // 하위 디렉토리 출력 재귀함수 호출
} else if (file.isFile()) {
System.out.printf("%s\n", file.getName());
}
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0710_06 {
public static void main(String[] args) throws Exception {
// 결과 예)
// /Users/bitcamp/git/test
// src/
// main/
// java/
// com/
// Hello.java
// Hello2.java
// build.gradle
// settings.gradle
// Hello.java
// ...
File dir = new File(".");
System.out.println(dir.getCanonicalPath());
printList(dir, 1);
}
static void printList(File dir, int level) {
// 현재 디렉토리의 하위 파일 및 디렉토리 목록을 알아낸다.
File[] files = dir.listFiles();
// 리턴 받은 파일 배열에서 이름을 꺼내 출력한다.
for (File file : files) {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
if (file.isDirectory() && !file.isHidden()) {
System.out.printf("%s/\n", file.getName());
printList(file, level + 1);
} else if (file.isFile()) {
System.out.printf("%s\n", file.getName());
}
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0710_07 {
public static void main(String[] args) throws Exception {
// 결과 예)
// /Users/bitcamp/git/test
// src/
// main/
// java/
// com/
// Hello.java
// Hello2.java
// build.gradle
// settings.gradle
// Hello.java
// ...
File dir = new File(".");
System.out.println(dir.getCanonicalPath());
printList(dir, 1);
}
static void printList(File dir, int level) {
// 현재 디렉토리의 하위 파일 및 디렉토리 목록을 알아낸다.
File[] files = dir.listFiles();
// 리턴 받은 파일 배열에서 이름을 꺼내 출력한다.
for (File file : files) {
printIndent(level);
if (file.isDirectory() && !file.isHidden()) {
System.out.printf("%s/\n", file.getName());
printList(file, level + 1);
} else if (file.isFile()) {
System.out.printf("%s\n", file.getName());
}
}
}
static void printIndent(int level) {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0710_08 {
public static void main(String[] args) throws Exception {
// 결과 예)
// /Users/bitcamp/git/test
// src/
// main/
// java/
// com/
// Hello.java
// Hello2.java
// build.gradle
// settings.gradle
// Hello.java
// ...
File dir = new File(".");
System.out.println(dir.getCanonicalPath());
printList(dir, 1);
}
static void printList(File dir, int level) {
// 현재 디렉토리의 하위 파일 및 디렉토리 목록을 알아낸다.
File[] files = dir.listFiles();
// 리턴 받은 파일 배열에서 이름을 꺼내 출력한다.
for (File file : files) {
printIndent(level);
if (file.isDirectory() && !file.isHidden()) {
System.out.printf("%s/\n", file.getName());
printList(file, level + 1);
} else if (file.isFile()) {
System.out.print("\\--");
System.out.printf("%s\n", file.getName());
}
}
}
static void printIndent(int level) {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
}
}
활용 - 지정한 폴더를 삭제하라.
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0720_01 {
public static void main(String[] args) throws Exception {
// temp 디렉토리를 삭제하기
File dir = new File("temp");
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0720_02 {
public static void main(String[] args) throws Exception {
// temp 디렉토리를 삭제하기
File dir = new File("temp");
deleteFile(dir);
}
static void deleteFile(File dir) {
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0720_03 {
public static void main(String[] args) throws Exception {
// temp 디렉토리를 삭제하기
File dir = new File("temp");
deleteFile(dir);
}
static void deleteFile(File dir) {
dir.delete(); // 현재 파일이나 폴더를 지우기
}
}
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0720_04 {
public static void main(String[] args) throws Exception {
// temp 디렉토리를 삭제하기
File dir = new File("temp");
deleteFile(dir);
}
static void deleteFile(File dir) {
// 주어진 파일이 디렉토리라면 하위 파일이나 디렉토리를 찾아 지운다.
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
deleteFile(file);
}
}
dir.delete(); // 현재 파일이나 폴더 지우기
}
}
활용 - 지정한 폴더에서 .class 파일만 찾아 출력하라.
package com.eomcs.io.ex01;
import java.io.File;
import java.io.FileFilter;
public class Exam0730 {
public static void main(String[] args) throws Exception {
File dir = new File("bin/main");
System.out.println(dir.getCanonicalPath());
printClasses(dir);
}
static void printClasses(File dir) {
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory() || (pathname.isFile() && pathname.getName().endsWith(".class"));
}
});
for (File file : files) {
if (file.isDirectory()) {
printClasses(file);
} else {
System.out.printf("%s\n", file.getName());
}
}
}
}
활용 - 클래스 파일 이름을 출력할 때 패키지 이름을 포함하라.
package com.eomcs.io.ex01;
import java.io.File;
import java.io.FileFilter;
public class Exam0731 {
public static void main(String[] args) throws Exception {
// 클래스 이름을 출력할 때 패키지 이름을 포함해야 한다.
// 예) ch01.Test01
// 예) ch22.a.Test14
//
File dir = new File("bin/main");
System.out.println(dir.getCanonicalPath());
printClasses(dir, "");
}
static void printClasses(File dir, String packageName) {
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory() || (pathname.isFile() && pathname.getName().endsWith(".class"));
}
});
if (packageName.length() > 0) {
packageName += ".";
}
for (File file : files) {
if (file.isDirectory()) {
printClasses(file, packageName + file.getName());
} else {
// path가 파일이면 패키지 이름과 파일 이름을 합쳐 출력하고 리턴한다.
// => 단 파일 이름에서 .class 확장자 명은 제외한다.
// => 파일 명이 Hello.class 이고 패키지명이 aaa.bbb 라면
// 출력할 이름은 aaa.bbb.Hello 이다.
System.out.println(packageName + file.getName().replace(".class", ""));
}
}
}
}
활용 - 클래스 파일 이름을 출력할 때 패키지 이름을 포함하라. (람다 문법 활용)
package com.eomcs.io.ex01;
import java.io.File;
public class Exam0732 {
public static void main(String[] args) throws Exception {
// 클래스 이름을 출력할 때 패키지 이름을 포함해야 한다.
// 예) ch01.Test01
// 예) ch22.a.Test14
//
File dir = new File("bin/main");
System.out.println(dir.getCanonicalPath());
printClasses(dir, "");
}
static void printClasses(File dir, String packageName) {
// 기존의 익명 클래스를 람다 문법으로 교체한다.
File[] files = dir.listFiles(
f -> f.isDirectory() || (f.isFile() && f.getName().endsWith(".class")));
if (packageName.length() > 0) {
packageName += ".";
}
for (File file : files) {
if (file.isDirectory()) {
printClasses(file, packageName + file.getName());
} else {
System.out.println(packageName + file.getName().replace(".class", ""));
}
}
}
}
com/eomcs/io/ex02
Byte Stream - 바이트 단위로 출력하기
package com.eomcs.io.ex02;
import java.io.FileOutputStream;
public class Exam0110 {
public static void main(String[] args) throws Exception {
// 1) 파일로 데이터를 출력하는 객체를 준비한다.
// - new FileOutputStream(파일경로)
// - 지정된 경로에 해당 파일을 자동으로 생성한다.
// - 기존에 같은 이름의 파일이 있으면 덮어쓴다.
// - 주의! 기존 파일이 삭제된다.
// - 파일 경로가 절대 경로가 아니면
// - 리눅스,유닉스: / 로 시작하지 않으면,
// - 윈도우: c:\, d:\ 등으로 시작하지 않으면,
// 현재 디렉토리가 기준이 된다.
FileOutputStream out = new FileOutputStream("temp/test1.data");
// 2) 1바이트를 출력한다.
// => write(int) : 1바이트를 출력하는 메서드이다.
// 파라미터의 타입이 int라고 해서 4바이트를 출력하는 것이 아니다.
// 오직 맨 끝 1바이트만 출력한다.
out.write(0x7a6b5c4d); // 출력하는 값은 0x4d 이다.
out.write(2); // 0x00000002
out.write(40); // 0x00000028
out.write(100); // 0x00000064
out.write(101); // 0x00000065
out.write(102); // 0x00000066
out.write(127); // 0x0000007f
out.write(255); // 0x000000ff
out.write('A'); // 0x0041
out.write('가'); // 0xac00
// 3) 출력 도구를 닫는다.
// - OS에서 관리하는 자원 중에서 한정된 개수를 갖는 자원에 대해
// 여러 프로그램이 공유하는 경우, 항상 사용 후 OS에 반납해야 한다.
// - 그래야 다른 프로그램이 해당 자원을 사용할 수 있다.
// 예) 파일, 메모리, 네트워크 연결 등
// - 이런 자원을 사용하는 클래스는 자원을 해제시키는 close()라는 메서드가 있다.
// - 보통 java.lang.AutoCloseable 인터페이스를 구현하고 있다.
// - 이번 예제에서 다루는 FileOutputStream 클래스에도 close()가 있다.
// - 따라서 FileOutputStream 객체를 사용한 후에는 close()를 호출하여
// 사용한 자원을 해제시켜야 한다.
// - close()를 호출하면,
// FileOutputStream이 작업하는 동안 사용했던 버퍼(임시메모리)를 비운다.
// - OS에서 제공한 파일과의 연결을 끊는다.
//
out.close();
// 물론, JVM을 종료하면 JVM을 실행하는 동안 사용했던 모든 자원은
// 자동으로 해제된다.
// 이런 예제처럼 짧은 시간 동안만 실행되는 경우,
// close()를 호출하지 않아도 자원을 해제시키는데 문제가 없다.
// 문제는 24시간 365일 멈추지 않고 실행하는 서버 프로그램인 경우
// 사용한 자원을 즉시 해제시키지 않으면
// 자원 부족 문제가 발생한다.
// 결론!
// - 간단한 코드를 작성하더라도 AutoCloseable 인터페이스를 구현한 클래스를 사용할 때는
// 사용하고 난 후 자원을 해제시는 close()를 반드시 호출하라.
//
System.out.println("데이터 출력 완료!");
}
}
// 파일 입출력 API 주요 클래스 (java.io 패키지)
// 1) 데이터 읽기
// InputStream (추상 클래스)
// +-- FileInputStream : 바이트 단위로 읽기 (binary stream)
//
// Reader (추상 클래스)
// +-- FileReader : 문자 단위로 읽기 (character stream)
//
// 2) 데이터 쓰기
// OutputStream (추상 클래스)
// +-- FileOutputStream : 바이트 단위로 쓰기 (binary stream)
//
// Writer (추상 클래스)
// +-- FileWriter : 문자 단위로 쓰기 (character stream)
// ## 바이너리 파일 vs 텍스트 파일
// 1) 바이너리 파일
// - character set(문자표) 규칙에 따라 작성한 파일이 아닌 파일.
// - 기본 텍스트 편집기(메모장, vi 에디터 등)로 편집할 수 없는 파일을 말한다.
// - 만약 텍스트 편집기로 변경한 후 저장하면, 파일 포맷이 깨지기 때문에 무효한 파일이 된다.
// - 예) .pdf, .ppt, .xls, .gif, .mp3, .jpg, .hwp, .mov, .avi, .exe, .lib 등
// - 바이너리 파일을 편집하려면 해당 파일 포맷을 이해하는 전용 프로그램이 필요하다.
//
// 2) 텍스트 파일
// - 특정 character set(문자표) 규칙에 따라 작성한 파일.
// - 기본 텍스트 편집기(메모장, vi 에디터 등)로 편집할 수 있는 파일을 말한다.
// - 예) .txt, .csv, .html, .js, .css, .xml, .bat, .c, .py, .php, .docx, .pptx, .xlsx 등
// - 텍스트 파일은 전용 에디터가 필요 없다.
// - 텍스트를 편집할 수 있는 에디터라면 편집 후 저장해도 유효하다.
// 바이너리 데이터 읽고, 쓰기
// - 읽고 쓸 때 중간에서 변환하는 것 없이 바이트 단위로 그대로 읽고 써야 한다.
// - InputStream/OutputStream 계열의 클래스를 사용하라.
//
// 텍스트 데이터 읽고, 쓰기
// - 읽고 쓸 때 중간에서 문자 코드표에 따라 변환하는 것이 필요하다.
// - Reader/Writer 계열의 클래스를 사용하라.
Byte Stream - 바이트 단위로 읽기
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0120 {
public static void main(String[] args) throws Exception {
// 1) 파일 데이터 읽기를 담당할 객체를 준비한다.
// - new FileInputStream(파일경로)
// - 해당 경로에 파일이 존재하지 않으면 예외가 발생한다.
//
FileInputStream in = new FileInputStream("temp/test1.data");
// 2) 1바이트를 읽는다.
// => read() 메서드의 리턴 타입이 int 라 하더라도 1바이트를 읽어 리턴한다.
// => 이유?
// 0 ~ 255까지의 값을 읽기 때문이다.
// byte는 -128 ~ 127까지의 값만 저장한다.
int b = in.read(); // 읽은 값은 0x4d 이다.
System.out.printf("%02x\n", b);
System.out.printf("%02x\n", in.read());
System.out.printf("%02x\n", in.read());
System.out.printf("%02x\n", in.read());
// read() 를 호출할 때마다 이전에 읽은 바이트의 다음 바이트를 읽는다.
// 3) 읽기 도구를 닫는다.
in.close();
}
}
Byte Stream - 바이트 단위로 읽기 II
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0130 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("temp/test1.data");
// 반복문을 이용하여 여러 바이트를 읽는다.
int b;
// while (true) {
// b = in.read();
// if (b == -1) // 파일의 끝에 도달하면 -1을 리턴한다.
// break;
// System.out.printf("%02x ", b);
// }
while ((b = in.read()) != -1) {
System.out.printf("%02x ", b);
}
in.close();
}
}
Byte Stream - 바이트 배열 출력하기
package com.eomcs.io.ex02;
import java.io.FileOutputStream;
public class Exam0210 {
public static void main(String[] args) throws Exception {
// 현재 디렉토리는 프로젝트 폴더이다.
//
FileOutputStream out = new FileOutputStream("temp/test1.data");
byte[] bytes = {0x7a, 0x6b, 0x5c, 0x4d, 0x3e, 0x2f, 0x30};
// write(byte[]) : 배열의 값 전체를 출력한다.
// write(byte[], 시작인덱스, 출력개수) : 시작 위치부터 지정된 개수를 출력한다.
//
out.write(bytes); // 바이트 배열 전체를 출력한다.
out.close();
System.out.println("데이터 출력 완료!");
}
}
Byte Stream - 바이트 배열 읽기
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0220 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("temp/test1.data");
// 바이트들을 저장할 배열을 넉넉히 준비한다.
// => 이렇게 임시 데이터를 저장하기 위해 만든 바이트 배열을 보통 "버퍼(buffer)"라 한다.
//
byte[] buf = new byte[100];
// read(byte[])
// - 버퍼가 꽉 찰 때까지 읽는다.
// - 물론 버퍼 크기보다 파일의 데이터가 적으면 파일을 모두 읽어 버퍼에 저장한다.
// - 리턴 값은 읽은 바이트의 개수이다.
// read(byte[], 저장할 위치, 저장하기를 희망하는 개수)
// - 읽은 데이터를 "저장할 위치"에 지정된 방부터 개수만큼 저장한다.
// - 리턴 값은 실제 읽은 바이트 개수이다.
int count = in.read(buf);
in.close();
System.out.printf("읽은 바이트 수: %d\n", count);
for (int i = 0; i < count; i++)
System.out.printf("%02x ", buf[i]);
System.out.println();
}
}
Byte Stream - 바이트 배열의 특정 부분을 출력하기
package com.eomcs.io.ex02;
import java.io.FileOutputStream;
public class Exam0310 {
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream("temp/test1.data");
byte[] bytes = {0x7a, 0x6b, 0x5c, 0x4d, 0x3e, 0x2f, 0x30};
// write(byte[]) : 배열의 값 전체를 출력한다.
// write(byte[], 시작인덱스, 출력개수) : 시작 위치부터 지정된 개수를 출력한다.
//
out.write(bytes, 2, 3); // 2번 데이터부터 3 바이트를 출력한다.
out.close();
System.out.println("데이터 출력 완료!");
}
}
Byte Stream - 읽은 데이터를 바이트 배열의 특정 위치에 저장하기
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0320 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("temp/test1.data");
// 데이터를 저장할 바이트 배열을 준비한다.
byte[] buf = new byte[100];
// 바이너리 데이터를 읽어 배열에 저장하기
// read(byte[])
// => 읽은 데이터를 바이트 배열에 채운다.
// => 리턴 값은 읽은 바이트 수이다.
// read(byte[], 저장할 위치, 저장하기를 희망하는 개수)
// => 읽은 데이터를 "저장할 위치"에 지정된 방부터 개수만큼 저장한다.
// => 리턴 값은 실제 읽은 바이트 개수이다.
int count = in.read(buf, 10, 40); // 40바이트를 읽어 10번 방부터 저장한다.
in.close();
System.out.printf("%d\n", count);
for (int i = 0; i < 100; i++)
System.out.printf("%d: %02x \n", i, buf[i]);
System.out.println();
}
}
FileInputStream 활용 - JPEG 파일 읽기
package com.eomcs.io.ex02;
import java.io.File;
import java.io.FileInputStream;
public class Exam0410 {
public static void main(String[] args) throws Exception {
// 1) 파일 정보를 준비한다.
File file = new File("sample/photo1.jpg");
// 2) 파일을 읽을 도구를 준비한다.
FileInputStream in = new FileInputStream(file);
// => SOI(Start of Image) Segment 읽기: 2바이트
int b1 = in.read(); // 00 00 00 ff
int b2 = in.read(); // 00 00 00 d8
int soi = b1 << 8 | b2;
// 00 00 00 ff <== b1
// 00 00 ff 00 <== b1 << 8
// | 00 00 00 d8 <== b2
// ------------------
// 00 00 ff d8
System.out.printf("SOI: %x\n", soi);
// => JFIF-APP0 Segment Marker 읽기: 2바이트
int jfifApp0Marker = in.read() << 8 | in.read();
System.out.printf("JFIF APP0 Marker: %x\n", jfifApp0Marker);
// => JFIF-APP0 Length: 2바이트
int jfifApp0Length = in.read() << 8 | in.read();
System.out.printf("JFIF APP0 정보 길이: %d\n", jfifApp0Length);
// => JFIF-APP0 정보: 16바이트(위에서 알아낸 길이)
byte[] jfifApp0Info = new byte[jfifApp0Length];
in.read(jfifApp0Info);
// => JFIF-APP0 Identifier: 5바이트
String jfifApp0Id = new String(jfifApp0Info, 0, 4);
System.out.printf("JFIF APP0 ID: %s\n", jfifApp0Id);
// SOF0(Start of Frame) 정보 읽기
// - 그림 이미지의 크기 및 샘플링에 관한 정보를 보관하고 있다
// - 0xFFC0 ~ 0xFFC2 로 표시한다.
// => SOF Marker 찾기
int b;
while (true) {
b = in.read();
if (b == -1) { // 파일 끝에 도달
break;
}
if (b == 0xFF) {
b = in.read();
if (b == -1) { // 파일 끝에 도달
break;
}
if (b >= 0xC0 && b <= 0xC2) {
break;
}
}
}
if (b == -1) {
System.out.println("유효한 JPEG 파일이 아닙니다.");
return;
}
// => SOF Length 읽기: 2바이트
int sofLength = in.read() << 9 | in.read();
System.out.printf("SOF 데이터 크기: %d\n", sofLength);
// => SOF 데이터 읽기: 17바이트(위에서 알아낸 크기)
byte[] sofData = new byte[sofLength];
in.read(sofData);
// => SOF 샘플링 정밀도: 1바이트
System.out.printf("SOF 샘플링 정밀도: %d\n", sofData[0]);
// => SOF 이미지 높이: 2바이트
int height = ((sofData[1] << 8) & 0xff00) | (sofData[2] & 0xff);
// => SOF 이미지 너비: 2바이트
int width = ((sofData[3] << 8) & 0xff00) | (sofData[4] & 0xff);
System.out.printf("SOF 이미지 크기(w x h): %d x %d\n", width, height);
// 3) 읽기 도구를 닫는다.
in.close();
}
}
Byte Stream - 텍스트 출력 하기
package com.eomcs.io.ex02;
import java.io.FileOutputStream;
public class Exam0510 {
public static void main(String[] args) throws Exception {
String str = new String("AB가각");
// String 객체의 데이터를 출력하려면
// 문자열을 담은 byte[] 배열을 리턴 받아야 한다.
// String.getBytes()
// => 특정 인코딩을 지정하지 않고 그냥 바이트 배열을 달라고 하면,
// String 클래스는 JVM 환경 변수 'file.encoding' 에 설정된 문자집합으로
// 바이트 배열을 인코딩 한다.
// => 이클립스에서 애플리케이션을 실행할 때 다음과 같이 JVM 환경변수를 자동으로 붙인다.
// $ java -Dfile.encoding=UTF-8 ....
// => 그래서 getBytes()가 리턴한 바이트 배열의 인코딩은 UTF-8이 되는 것이다.
// => 만약 이 예제를 이클립스가 아니라 콘솔창에서
// -Dfile.encoding=UTF-8 옵션 없이 실행한다면,
// getBytes()가 리턴하는 바이트 배열은
// OS의 기본 인코딩으로 변환될 것이다.
// => OS 기본 인코딩
// Windows => MS949
// Linux/macOS => UTF-8
// => OS에 상관없이 동일한 실행 결과를 얻고 싶다면, 다음과 같이 file.encoding 옵션을 붙여라
// $ java -Dfile.encoding=UTF-8 -cp bin/main .....
// => 또는 getBytes() 호출할 때 인코딩할 문자집합을 지정하라.
// str.getBytes("UTF-8")
//
// JVM에 문자를 입출력할 때 사용하는 기본 문자 집합이 무엇인지 알아 본다.
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
byte[] bytes = str.getBytes(); // 문자집합을 지정하지 않으면 file.encoding에 설정된 문자집합으로 인코딩하여 리턴한다.
//
// 이클립스:
// UCS2 ==> UTF-8
// 이클립스의 경우 자바 앱을 실행할 때 file.encoding 변수의 값을 utf-8 로 설정한다.
//
// file.encoding JVM 환경 변수의 값이 설정되어 있지 않을 경우,
// Windows: UCS2 ==> MS949
// Linux: UCS2 ==> UTF-8
// macOS: UCS2 ==> UTF-8
//
for (byte b : bytes) {
System.out.printf("%x ", b);
}
System.out.println();
// 바이트 배열 전체를 그대로 출력한다.
FileOutputStream out = new FileOutputStream("temp/utf.txt");
out.write(bytes);
out.close();
System.out.println("데이터 출력 완료!");
}
}
package com.eomcs.io.ex02;
import java.io.FileOutputStream;
public class Exam0512 {
public static void main(String[] args) throws Exception {
String str = new String("AB가각");
// String 객체의 데이터를 출력하려면
// 문자열을 담은 byte[] 배열을 리턴 받아야 한다.
// => UTF-16BE로 인코딩 하기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
byte[] bytes = str.getBytes("UTF-16BE"); // UCS2 ==> UTF-16BE
for (byte b : bytes) {
System.out.printf("%02x ", b);
}
System.out.println();
// 바이트 배열 전체를 그대로 출력한다.
FileOutputStream out = new FileOutputStream("temp/utf16be.txt");
out.write(bytes);
out.close();
System.out.println("데이터 출력 완료!");
}
}
package com.eomcs.io.ex02;
import java.io.FileOutputStream;
public class Exam0513 {
public static void main(String[] args) throws Exception {
String str = new String("AB가각");
// String 객체의 데이터를 출력하려면
// 문자열을 담은 byte[] 배열을 리턴 받아야 한다.
// => UTF-16LE로 인코딩 하기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
byte[] bytes = str.getBytes("UTF-16LE"); // UCS2 ==> UTF-16LE
for (byte b : bytes) {
System.out.printf("%02x ", b);
}
System.out.println();
// 바이트 배열 전체를 그대로 출력한다.
FileOutputStream out = new FileOutputStream("temp/utf16le.txt");
out.write(bytes);
out.close();
System.out.println("데이터 출력 완료!");
}
}
package com.eomcs.io.ex02;
import java.io.FileOutputStream;
public class Exam0514 {
public static void main(String[] args) throws Exception {
String str = new String("AB가각");
// String 객체의 데이터를 출력하려면
// 문자열을 담은 byte[] 배열을 리턴 받아야 한다.
// => UTF-8로 인코딩 하기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
byte[] bytes = str.getBytes("UTF-8"); // UCS2 ==> UTF-8
for (byte b : bytes) {
System.out.printf("%x ", b);
}
System.out.println();
// 바이트 배열 전체를 그대로 출력한다.
FileOutputStream out = new FileOutputStream("temp/utf8.txt");
out.write(bytes);
out.close();
System.out.println("데이터 출력 완료!");
}
}
Byte Stream - 텍스트 데이터 읽기
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0520 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("sample/ms949.txt");
int b = 0;
// MS949로 인코딩된 텍스트 읽기
// - 단순히 1바이트를 읽어서는 안된다.
// - 영어는 1바이트를 읽으면 되지만,
// 한글은 2바이트를 읽어야 한다.
while ((b = in.read()) != -1) {
if (b >= 0x81) { // 읽은 바이트가 한글에 해당한다면
// 1바이트를 더 읽어서 기존에 읽은 바이트 뒤에 붙여 2바이트로 만든다.
b = b << 8 | in.read();
}
System.out.printf("%x\n", b);
}
in.close();
}
}
Byte Stream - 텍스트 데이터 읽기 II
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0521 {
public static void main(String[] args) throws Exception {
// JVM 환경 변수 'file.encoding' 값
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
FileInputStream in = new FileInputStream("sample/utf8.txt");
// 파일의 데이터를 한 번에 읽어보자.
byte[] buf = new byte[1000];
int count = in.read(buf); // <== 41 42 ea b0 80 ea b0 81 (AB가각)
in.close();
// 읽은 바이트 수를 출력해보자.
System.out.printf("읽은 바이트 수: %d\n", count);
// 읽은 바이트를 String 객체로 만들어보자.
// - 바이트 배열에 저장된 문자 코드를
// JVM이 사용하는 문자 집합(UCS2=UTF16BE)의 코드 값으로 변환한다.
// - 바이트 배열에 들어 있는 코드 값이 어떤 문자 집합의 값인지 알려주지 않는다면,
// JVM 환경 변수 file.encoding에 설정된 문자 집합으로 가정하고 변환을 수행한다.
String str = new String(buf, 0, count); // new String(buf) 가능
// 바이트 배열이 어떤 문자집합으로 인코딩 된 것인지 알려주지 않으면,
// file.encoding에 설정된 문자집합으로 인코딩된 것으로 간주한다.
System.out.println(str);
// 바이트가 어떤 문자 집합으로 인코딩 되었는지 알려주지 않는다면?
// String 객체를 생성할 때 다음의 규칙에 따라 변환한다.
// => JVM 환경 변수 'file.encoding' 에 설정된 문자집합으로 가정하고 UCS2 문자 코드로 변환한다.
//
// 1) 이클립스에서 실행 => 성공!
// - JVM 실행 옵션에 '-Dfile.encoding=UTF-8' 환경 변수가 자동으로 붙는다.
// - 그래서 String 클래스는 바이트 배열의 값을 UCS2로 바꿀 때 UTF-8 문자표를 사용하여 UCS2 로 변환한다.
// - 예1)
// utf8.txt => 41 42 ea b0 80 ea b0 81
// UCS2 => 0041 0042 ac00 ac01 <== 정상적으로 바뀐다.
//
// 2) Windows 콘솔에서 실행 => 실패!
// - JVM을 실행할 때 file.encoding을 설정하지 않으면
// OS의 기본 문자집합으로 설정한다.
// - Windows의 기본 문자집합은 MS949 이다.
// - 따라서 file.encoding 값은 MS949가 된다.
// - 바이트 배열은 UTF-8로 인코딩 되었는데,
// MS949 문자표를 사용하여 UCS2로 변환하려 하니까
// 잘못된 문자로 변환되는 것이다.
// - 해결책?
// JVM을 실행할 때 file.encoding 옵션에 정확하게 해당 파일의 인코딩을 설정하라.
// 즉 utf8.txt 파일은 UTF-8로 인코딩 되었기 때문에
// '-Dfile.encoding=UTF-8' 옵션을 붙여서 실행해야 UCS2로 정상 변환된다.
//
// 3) Linux/macOS 콘솔에서 실행 => 성공!
// - Linux와 macOS의 기본 문자 집합은 UTF-8이다.
// - 따라서 JVM을 실행할 때 '-Dfile.encoding=UTF-8' 옵션을 지정하지 않아도
// 해당 파일을 UTF-8 문자로 간주하여 UTF-8 문자표에 따라 UCS2로 변환한다.
//
}
}
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0522 {
public static void main(String[] args) throws Exception {
// JVM 환경 변수 'file.encoding' 값
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
FileInputStream in = new FileInputStream("sample/ms949.txt"); // 41 42 b0 a1 b0 a2(AB가각)
// 파일의 데이터를 한 번에 읽어보자.
byte[] buf = new byte[1000];
int count = in.read(buf);
in.close();
String str = new String(buf, 0, count);
// 바이트 배열에 MS949 문자집합에 따라 인코딩 된 데이터가 들어 있는데,
// String 클래스는 UTF-8 문자집합으로 인코딩 되었다고 가정하기 때문에
// UTF-16으로 정확하게 변환할 수 없는 것이다.
System.out.println(str);
// ms949.txt 파일을 읽을 때 문자가 깨지는 이유?
// - 한글이 다음과 같이 MS949 문자 집합으로 인코딩 되어 있다.
// ms949.txt => 41 42 b0 a1 b0 a2
// - String 객체를 생성할 때 바이트 배열의 문자집합을 알려주지 않으면
// JVM 환경 변수 'file.encoding'에 설정된 문자집합이라고 가정한다.
//
// 1) 이클립스에서 실행 => 실패!
// - 이클립스에서 JVM을 실행할 때 '-Dfile.encoding=UTF-8' 옵션을 붙인다.
// - 따라서 String 클래스는 바이트 배열의 값을 UCS2로 변환할 때 UTF-8 문자표를 사용한다.
// - 문제는, 바이트 배열의 값이 MS949로 인코딩 되어 있다는 사실이다.
// 즉 잘못된 문자표를 사용하니까 변환을 잘못한 것이다.
//
// 2) Windows 콘솔에서 실행 => 성공!
// - JVM을 실행할 때 'file.encoding' 환경 변수를 지정하지 않으면,
// OS의 기본 문자 집합으로 설정한다.
// - Windows의 기본 문자 집합은 MS949이다.
// - 따라서 file.encoding의 값은 MS949로 설정된다.
// - 바이트 배열의 값이 MS949 이기 때문에 MS949 문자표로 변환하면
// UCS2 문자 코드로 잘 변환되는 것이다.
//
// MS949 코드를 UTF-8 문자로 가정하고 다룰 때 한글이 깨지는 원리!
// - ms949.txt
// => 01000001 01000010 10110000 10100001 10110000 10100010 = 41 42 b0 a1 b0 a2
// - MS949 코드를 변환할 때 UTF-8 문자표를 사용하면 다음과 같이 잘못된 변환을 수행한다.
// byte(UTF-8) => char(UCS2)
// 01000001 -> 00000000 01000001 (00 41) = 'A' <-- 정상적으로 변환되었음.
// 01000010 -> 00000000 01000010 (00 42) = 'B' <-- 정상적으로 변환되었음.
// 10110000 -> 꽝 (xx xx) <-- 해당 바이트가 UTF-8 코드 값이 아니기 때문에 UCS2로 변환할 수 없다.
// 10100001 -> 꽝 (xx xx) <-- 그래서 꽝을 의미하는 특정 코드 값이 들어 갈 것이다.
// 10110000 -> 꽝 (xx xx) <-- 그 코드 값을 문자로 출력하면 => �
// 10100010 -> 꽝 (xx xx)
}
}
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0523 {
public static void main(String[] args) throws Exception {
// JVM 환경 변수 'file.encoding' 값
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
FileInputStream in = new FileInputStream("sample/ms949.txt");
// 파일의 데이터를 한 번에 읽어보자.
byte[] buf = new byte[1000];
int count = in.read(buf);
in.close();
// JVM 환경 변수 'file.encoding'에 설정된 문자표에 상관없이
// String 객체를 만들 때 바이트 배열의 인코딩 문자 집합을 정확하게 알려준다면,
// UCS2 코드 값으로 정확하게 변환해 줄 것이다.
String str = new String(buf, 0, count, "CP949"); // MS949 = CP949
System.out.println(str);
}
}
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0524 {
public static void main(String[] args) throws Exception {
// JVM 환경 변수 'file.encoding' 값
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
FileInputStream in = new FileInputStream("sample/utf16be.txt"); // 0041 0042 ac00 ac01(AB가각)
// 파일의 데이터를 한 번에 읽어보자.
byte[] buf = new byte[1000];
int count = in.read(buf);
in.close();
// JVM 환경 변수 'file.encoding'에 설정된 문자표에 상관없이
// String 객체를 만들 때 바이트 배열의 인코딩 문자 집합을 정확하게 알려준다면,
// UCS2 코드 값으로 정확하게 변환해 줄 것이다.
String str = new String(buf, 0, count, "UTF-16"); // UTF-16 == UTF-16BE
System.out.println(str);
}
}
package com.eomcs.io.ex02;
import java.io.FileInputStream;
public class Exam0525 {
public static void main(String[] args) throws Exception {
// JVM 환경 변수 'file.encoding' 값
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
FileInputStream in = new FileInputStream("sample/utf16le.txt");
// 파일의 데이터를 한 번에 읽어보자.
byte[] buf = new byte[1000];
int count = in.read(buf);
in.close();
// JVM 환경 변수 'file.encoding'에 설정된 문자표에 상관없이
// String 객체를 만들 때 바이트 배열의 인코딩 문자 집합을 정확하게 알려준다면,
// UCS2 코드 값으로 정확하게 변환해 줄 것이다.
String str = new String(buf, 0, count, "UTF-16LE");
System.out.println(str);
}
}
com.eomcs.io.ex03
character stream - 문자 단위로 출력하기
package com.eomcs.io.ex03;
import java.io.FileWriter;
public class Exam0110 {
public static void main(String[] args) throws Exception {
// JVM의 문자열을 파일로 출력할 때
// FileOutputStream 과 같은 바이트 스트림 클래스를 사용하면
// 문자집합을 지정해야 하는 번거로움이 있었다.
// => 이런 번거로움을 해결하기 위해 만든 스트림 클래스가 있으니,
// 문자 스트림 클래스이다.
// => 즉 Reader/Writer 계열의 클래스이다.
// 1) 문자 단위로 출력할 도구 준비
FileWriter out = new FileWriter("temp/test2.txt");
// 2) 문자 출력하기
// - JVM은 문자 데이터를 다룰 때 UCS2(UTF16BE, 2바이트) 유니코드를 사용한다.
// - character stream 클래스 FileWriter는 문자 데이터를 출력할 때
// UCS2 코드를 JVM 환경변수 file.encoding 에 설정된 character set 코드로 변환하여 출력한다.
// - JVM을 실행할 때 -Dfile.encoding=문자집합 옵션으로 기본 문자 집합을 설정한다.
// 만약 file.encoding 옵션을 설정하지 않으면 OS의 기본 문자집합으로 자동 설정된다.
//
// Linux, macOS 의 기본 character set => UTF-8
// Windows 의 기본 character set => MS-949
//
// - file.encoding 옵션을 설정하지 않은 상태에서는
// 어느 OS에서 실행하느냐에 따라 출력되는 코드 값이 달라진다.
//
// - 이클립스에서 실행할 경우,
// 이클립스가 file.encoding 옵션의 문자집합을 UTF-8로 설정한다.
//
// - 명령창(콘솔창)에서 실행한다면,
// 위에서 설명한대로 OS에 따라 다르게 인코딩 된다.
//
// - OS에 상관없이 동일한 character set으로 출력하고 싶다면
// JVM을 실행할 때 file.encoding 프로퍼티에 character set 이름을 지정하라.
//
// - JVM을 실행할 때 출력 데이터의 문자 코드표를 지정하는 방법
// java -Dfile.encoding=문자코드표 -cp 클래스경로 클래스명
// 예) java -Dfile.encoding=UTF-8 -cp bin/main com.eomcs.io.ex03.Exam0110
//
// - 단, character set을 지정할 때는 해당 OS에서 사용가능한 문자표이어야 한다.
// MS Windows에서는 ms949 문자표를 사용할 수 있지만,
// 리눅스나 macOS에서는 ms949 문자표를 사용할 수 없다.
// 왜?
// 국제 표준이 아니기 때문이다.
//
// [이클립스에서 실행]
// - JVM을 실행할 때 '-Dfile.encoding=UTF-8' 옵션을 자동으로 붙인다.
// - 그래서 출력할 때, UCS2를 UTF-8 코드로 변환하여 파일에 쓴다.
//
// [콘솔창에서 실행]
// 1) file.encoding 환경 변수를 지정하지 않으면,
// - OS가 기본으로 사용하는 문자 코드로 변환하여 파일에 쓴다.
// - windows : MS949
// - linux/unix/macOS : UTF-8
//
// 2) JVM을 실행할 때 '-Dfile.encoding=문자코드표' 옵션을 지정한다면,
// - 해당 옵션에 지정된 문자 코드로 변환하여 파일에 쓴다.
//
// [결론]
// - OS에 영향 받지 않으려면,
// JVM을 실행할 때 반드시 file.encoding JVM 환경 변수를 설정하라.
// - 문자집합은 UTF-8을 사용하라.
// - 국제 표준이다.
// - linux, macOS의 기본 문자 집합이다.
//
// 현재 JVM 환경 변수 'file.encoding' 값 알아내기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
// => 이 예제를 이클립스에서 실행한다면,
// 앞의 2바이트는 버리고,
// 뒤의 2바이트(UCS2)를 UTF-8 코드표에 따라
// 1 ~ 4 바이트 값으로 변환하여 파일에 쓴다.
// => 즉 이클립스에서 자바 프로그램을 실행할 때
// -Dfile.encoding=UTF-8 옵션을 붙여 실행하기 때문이다.
// => OS의 기본 문자표로 출력하고 싶다면,
// 콘솔창에서 위 옵션 없이 직접 이 클래스를 실행하라.
//
// UCS2에서 한글 '가'는 ac00이다.
out.write(0x7a6bac00);
// - 앞의 2바이트(7a6b)는 버린다.
// - 뒤의 2바이트(ac00)은 UTF-8(eab080) 코드 값으로 변환되어 파일에 출력된다.
// UCS2에서 영어 A는 0041이다.
// 출력하면, UTF-8 코드 값(41)이 파일에 출력된다.
out.write(0x7a5f0041); //
// - 앞의 2바이트(7a5f)는 버린다.
// - 뒤의 2바이트(0041)는 UTF-8(41) 코드 값으로 변환되어 파일에 출력된다.
out.close();
System.out.println("출력 완료!");
}
}
character stream - 출력할 문자 집합 설정하기
package com.eomcs.io.ex03;
import java.io.FileWriter;
import java.nio.charset.Charset;
public class Exam0111 {
public static void main(String[] args) throws Exception {
System.out.println(Charset.isSupported("EUC-KR"));
// 1) 출력 스트림 객체를 생성할 때 문자 집합을 지정하면
// UCS2 문자열을 해당 문자집합으로 인코딩 한다.
Charset charset = Charset.forName("EUC-KR");
FileWriter out = new FileWriter("temp/test2.txt", charset);
// 현재 JVM 환경 변수 'file.encoding' 값 알아내기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
// UCS2에서 한글 '가'는 ac00이다.
out.write(0x7a6bac00);
// - 앞의 2바이트(7a6b)는 버린다.
// - 뒤의 2바이트(ac00)은 MS949(b0a1) 코드 값으로 변환되어 파일에 출력된다.
// UCS2에서 영어 'A'는 0041이다.
out.write(0x7a5f0041); //
// - 앞의 2바이트(7a5f)는 버린다.
// - 뒤의 2바이트는 MS949(41) 코드 값으로 변환되어 파일에 출력된다.
out.close();
System.out.println("출력 완료!");
}
}
package com.eomcs.io.ex03;
import java.io.FileWriter;
import java.nio.charset.Charset;
public class Exam0112 {
public static void main(String[] args) throws Exception {
// 1) 출력 스트림 객체를 생성할 때 문자 집합을 지정하면
// UCS2 문자열을 해당 문자집합으로 인코딩 한다.
Charset charset = Charset.forName("UTF-16BE");
FileWriter out = new FileWriter("temp/test2.txt", charset);
// 현재 JVM 환경 변수 'file.encoding' 값 알아내기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
// UCS2에서 한글 '가'는 ac00이다.
out.write(0x7a6bac00);
// - 앞의 2바이트(7a6b)는 버린다.
// - 뒤의 2바이트(ac00)은 UTF-16BE(ac00) 코드 값으로 변환되어 파일에 출력된다.
// UCS2에서 영어 'A'는 0041이다.
out.write(0x7a5f0041); //
// - 앞의 2바이트(7a5f)는 버린다.
// - 뒤의 2바이트는 UTF-16BE(0041) 코드 값으로 변환되어 파일에 출력된다.
out.close();
System.out.println("출력 완료!");
}
}
character stream - 문자 단위로 읽기
package com.eomcs.io.ex03;
import java.io.FileReader;
public class Exam0120 {
public static void main(String[] args) throws Exception {
// 1) 파일의 데이터를 읽는 일을 하는 객체를 준비한다.
FileReader in = new FileReader("sample/utf8.txt"); // 41 42 ea b0 81 ea b0 81
// 2) JVM 환경 변수 'file.encoding'에 설정된 문자코드표에 따라
// 바이트를 읽어서 UCS2로 바꾼 후에 리턴한다.
//
// - JVM을 실행할 때 다음 옵션을 지정하지 않으면
// -Dfile.encoding=문자표
// - JVM은 OS의 기본 문자표라고 가정하고 파일을 읽는다.
// 만약 이클립스에서 실행한다면,
// UTF-8이라고 가정하고 읽는다.
// 만약 명령창(콘솔창)에서 실행한다면,
// OS에 따라 다르게 읽는다.
//
// 현재 JVM 환경 변수 'file.encoding' 값 알아내기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
// file.encoding이 UTF-8로 되어 있다면,
// => 영어는 1바이트를 읽어서 2바이트 UCS2로 변환한다.
int ch1 = in.read(); // 41 => 0041('A')
int ch2 = in.read(); // 42 => 0042('B')
// => 한글은 3바이를 읽어서 2바이트 UCS2로 변환한다.
int ch3 = in.read(); // ea b0 80 => ac00('가')
int ch4 = in.read(); // ea b0 81 => ac01('각')
// 3) 읽기 도구를 닫는다.
in.close();
System.out.printf("%04x, %04x, %04x, %04x\n", ch1, ch2, ch3, ch4);
}
}
package com.eomcs.io.ex03;
import java.io.FileReader;
public class Exam0122 {
public static void main(String[] args) throws Exception {
// 1) 파일의 데이터를 읽을 객체를 준비한다.
FileReader in = new FileReader("sample/ms949.txt"); // 41 42 b0 a1 b0 a2
// 2) 출력 스트림 객체를 생성할 때 파일의 문자 집합을 지정하지 않으면,
// JVM 환경 변수 'file.encoding'에 설정된 문자코드표에 따라
// 바이트를 읽어서 UCS2로 바꾼 후에 리턴한다.
// 현재 JVM 환경 변수 'file.encoding' 값 알아내기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
// file.encoding이 UTF-8로 되어 있다면,
// => 영어는 1바이트를 읽어서 2바이트 UCS2로 변환한다.
// => MS949도 영어인 경우 UTF-8과 같기 때문에 변환하는데 문제가 없다.
int ch1 = in.read(); // 41 => 0041('A')
int ch2 = in.read(); // 42 => 0042('B')
// => 한글은 MS949와 UTF-8이 다르다.
// MS949로 인코딩 된 것을 UTF-8로 간주하여 변환한다면,
// UTF-8 문자가 아니기 때문에
// 다음과 같이 잘못되었다는 의미로 특정 값(fffd)으로 변환한다.
int ch3 = in.read(); // b0 a1 => fffd => �
int ch4 = in.read(); // b0 a2 => fffd => �
// 3) 읽기 도구를 닫는다.
in.close();
System.out.printf("%04x, %04x, %04x, %04x\n", ch1, ch2, ch3, ch4);
}
}
package com.eomcs.io.ex03;
import java.io.FileReader;
import java.nio.charset.Charset;
public class Exam0123 {
public static void main(String[] args) throws Exception {
// 1) 파일의 데이터를 읽을 객체를 준비한다.
// => 읽어들일 파일의 문자집합이 file.encoding 환경변수에 지정된 값과 다르다면,
// 다음과 같이 출력 스트림을 생성할 때 파일의 문자집합을 알려줘라.
FileReader in = new FileReader("sample/ms949.txt", Charset.forName("MS949")); // 41 42 b0 a1 b0 a2
// 2) 출력 스트림 객체를 생성할 때 파일의 문자 집합을 지정하면,
// JVM 환경 변수 'file.encoding'에 설정된 문자집합을 무시한다.
// 현재 JVM 환경 변수 'file.encoding' 값 알아내기
System.out.printf("file.encoding=%s\n", System.getProperty("file.encoding"));
// file.encoding이 UTF-8로 설정되어 있지만,
// 출력 스트림에 'MS949'를 사용한다고 했기 때문에
// MS949 문자표에 따라 UCS2로 변환할 것이다.
int ch1 = in.read(); // 41 => 0041('A')
int ch2 = in.read(); // 42 => 0042('B')
// 한글
int ch3 = in.read(); // b0 a1 => ac00 => '가'
int ch4 = in.read(); // b0 a2 => ac01 => '각'
// 3) 읽기 도구를 닫는다.
in.close();
System.out.printf("%04x, %04x, %04x, %04x\n", ch1, ch2, ch3, ch4);
}
}
Character Stream - 문자 배열 출력하기
package com.eomcs.io.ex03;
import java.io.FileWriter;
public class Exam0210 {
public static void main(String[] args) throws Exception {
FileWriter out = new FileWriter("temp/test2.txt");
char[] chars = new char[] {'A', 'B', 'C', '0', '1', '2', '가', '각', '간', '똘', '똥'};
// FileOutputStream 은 byte[] 을 출력하지만,
// FileWriter 는 char[] 을 출력한다.
out.write(chars); // 문자 배열 전체를 출력한다.
// 당연히 UCS2를 JVM 환경 변수 'file.encoding'에 설정된 문자 코드표에 따라 변환하여 출력한다.
// JVM이 입출력 문자 코드표로 UTF-8을 사용한다면
// 영어는 1바이트로 변환되어 출력될 것이고,
// 한글은 3바이트로 변환되어 출력될 것이다.
// JVM(UCS2) File(UTF-8)
// 00 41 ==> 41
// 00 42 ==> 42
// 00 43 ==> 43
// 00 30 ==> 30
// 00 31 ==> 31
// 00 32 ==> 32
// ac 00 ==> ea b0 80
// ac 01 ==> ea b0 81
// ac 04 ==> ea b0 84
// b6 18 ==> eb 98 98
// b6 25 ==> eb 98 a5
out.close();
System.out.println("데이터 출력 완료!");
}
}
Character Stream - 문자 배열 읽기
package com.eomcs.io.ex03;
import java.io.FileReader;
public class Exam0220 {
public static void main(String[] args) throws Exception {
FileReader in = new FileReader("temp/test2.txt");
// UCS2 문자 코드 값을 저장할 배열을 준비한다.
// => 이렇게 임시 데이터를 저장하기 위해 만든 바이트 배열을 보통 "버퍼(buffer)"라 한다.
char[] buf = new char[100];
// read(버퍼의주소)
// => 버퍼가 꽉 찰 때까지 읽는다.
// => 물론 버퍼 크기보다 파일의 데이터가 적으면 파일을 모두 읽어 버퍼에 저장한다.
// => 리턴 값은 읽은 문자의 개수이다. 바이트의 개수가 아니다!!!!!
// FileInputStream.read()의 리턴 값은 읽은 바이트의 개수였다.
// => 파일을 읽을 때 JVM 환경 변수 'file.encoding'에 설정된 문자코드표에 따라 바이트를 읽는다.
// 그리고 2바이트 UCS2 코드 값으로 변환하여 리턴한다.
// => JVM의 문자코드표가 UTF-8이라면,
// 파일을 읽을 때, 영어나 숫자, 특수기호는 1바이트를 읽어 UCS2으로 변환할 것이고
// 한글은 3바이트를 읽어 UCS2으로 변환할 것이다.
int count = in.read(buf);
// File(UTF-8) JVM(UCS2)
// 41 ==> 00 41
// 42 ==> 00 42
// 43 ==> 00 43
// 30 ==> 00 30
// 31 ==> 00 31
// 32 ==> 00 32
// ea b0 80 ==> ac 00
// ea b0 81 ==> ac 01
// ea b0 84 ==> ac 04
// eb 98 98 ==> b6 18
// eb 98 a5 ==> b6 25
in.close();
System.out.printf("%d\n", count);
for (int i = 0; i < count; i++)
System.out.printf("%c(%04x)\n", buf[i], (int)buf[i]);
System.out.println();
}
}
Character Stream - char[] ==> String 변환하기
package com.eomcs.io.ex03;
import java.io.FileReader;
public class Exam0221 {
public static void main(String[] args) throws Exception {
FileReader in = new FileReader("temp/test2.txt");
char[] buf = new char[100];
int count = in.read(buf); // char 배열에 담을 때 UTF-16BE 코드 값으로 변환한다.
String str = new String(buf, 0, count); // 그래서 String 객체를 만들 때 문자집합을 지정할 필요가 없다.
in.close();
System.out.printf("[%s]\n", str);
}
}
Character Stream - 문자 배열의 특정 부분을 출력하기
package com.eomcs.io.ex03;
import java.io.FileWriter;
public class Exam0310 {
public static void main(String[] args) throws Exception {
FileWriter out = new FileWriter("temp/test2.txt");
char[] chars = new char[] {'A','B','C','가','각','간','똘','똥'};
out.write(chars, 2, 3); // 2번 문자부터 3 개의 문자를 출력한다.
out.close();
System.out.println("데이터 출력 완료!");
}
}
Character Stream - 읽은 데이터를 문자 배열의 특정 위치에 저장하기
package com.eomcs.io.ex03;
import java.io.FileReader;
public class Exam0320 {
public static void main(String[] args) throws Exception {
FileReader in = new FileReader("temp/test2.txt");
char[] buf = new char[100];
// read(버퍼의주소, 저장할위치, 읽을바이트개수)
// => 리턴 값은 실제 읽은 문자의 개수이다.
int count = in.read(buf, 10, 40); // 40개의 문자를 읽어 10번 방부터 저장한다.
in.close();
System.out.printf("%d\n", count);
for (int i = 0; i < 20; i++)
System.out.printf("%c(%04x) ", buf[i], (int) buf[i]);
System.out.println();
}
}
Character Stream - String 출력하기
package com.eomcs.io.ex03;
import java.io.FileWriter;
public class Exam0410 {
public static void main(String[] args) throws Exception {
FileWriter out = new FileWriter("temp/test2.txt");
String str = new String("AB가각");
out.write(str);
out.close();
System.out.println("데이터 출력 완료!");
}
}
Character Stream - 텍스트 읽기
package com.eomcs.io.ex03;
import java.io.FileReader;
import java.nio.CharBuffer;
public class Exam0420 {
public static void main(String[] args) throws Exception {
FileReader in = new FileReader("temp/test2.txt");
// FileReader 객체가 읽을 데이터를 저장할 메모리를 준비한다.
CharBuffer charBuf = CharBuffer.allocate(100);
// 읽은 데이터를 CharBuffer 에 저장한다.
int count = in.read(charBuf);
in.close();
System.out.printf("%d\n", count);
// 버퍼의 데이터를 꺼내기 전에 읽은 위치를 0으로 초기화시킨다.
// - read() 메서드가 파일에서 데이터를 읽어서 버퍼에 채울 때 마다 커서의 위치는 다음으로 이동한다.
// - 버퍼의 데이터를 읽으려면 커서의 위치를 처음으로 되돌려야 한다.(flip)
// - flip() 메서드를 호출하여 커서를 처음으로 옮긴다. 그런 후에 버퍼의 텍스를 읽어야 한다.
charBuf.flip();
System.out.printf("[%s]\n", charBuf.toString());
}
}
Character Stream - 텍스트 읽기 II
package com.eomcs.io.ex03;
import java.io.BufferedReader;
import java.io.FileReader;
public class Exam0430 {
public static void main(String[] args) throws Exception {
FileReader in = new FileReader("temp/test2.txt");
// 데코레이터를 붙인다.
// => 버퍼 기능 + 한 줄 읽기 기능
BufferedReader in2 = new BufferedReader(in);
System.out.println(in2.readLine());
in.close();
}
}
com.eomcs.io.ex04
데이터 출력 - int 값 출력
package com.eomcs.io.ex04;
import java.io.FileOutputStream;
public class Exam0110 {
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream("temp/test3.data");
int money = 1_3456_7890; // = 0x080557d2
out.write(money); //항상 출력할 때는 맨 끝 1바이트만 출력한다.
out.close();
System.out.println("데이터 출력 완료!");
}
}
데이터 읽기 - int 값 읽기
package com.eomcs.io.ex04;
import java.io.FileInputStream;
public class Exam0120 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("temp/test3.data");
// Exam0110 실행하여 출력한 데이터를 read()로 읽는다.
// read()는 1바이트를 읽어 int 값으로 만든 후 리턴한다.
int value = in.read(); // 실제 리턴한 값은 0xD2이다.
in.close();
System.out.printf("%1$x(%1$d)\n", value);
}
}
데이터 출력 - int 값 출력 II
package com.eomcs.io.ex04;
import java.io.FileOutputStream;
public class Exam0210 {
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream("temp/test3.data");
int money = 1_3456_7890; // = 0x080557d2
// int 메모리의 모든 바이트를 출력하려면,
// 각 바이트를 맨 끝으로 이동한 후 write()로 출력한다.
// 왜?
// write()는 항상 변수의 마지막 1바이트만 출력하기 때문이다.
out.write(money >> 24); // 00000008|0557d2
out.write(money >> 16); // 00000805|57d2
out.write(money >> 8); // 00080557|d2
out.write(money); // 080557d2
out.close();
System.out.println("데이터 출력 완료!");
}
}
데이터 읽기 - int 값 읽기 II
package com.eomcs.io.ex04;
import java.io.FileInputStream;
public class Exam0220 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("temp/test3.data");
// Exam02_1을 실행하여 출력한 데이터를 read()로 읽는다.
// => 파일에서 4바이트를 읽어 4바이트 int 변수에 저장하라!
// => 읽은 바이트를 비트이동 연산자를 값을 이동 시킨 후 변수에 저장해야 한다.
// => 파일에 들어 있는 값 예: 080557d2
int value = in.read() << 24; // 00000008 => 08000000
value += (in.read() << 16); // 00000005 => + 00050000
value += (in.read() << 8); // 00000057 => + 00005700
value += in.read(); // 000000d2 => + 000000d2
//==========================================> 080557d2
in.close();
System.out.printf("%08x(%1$d)\n", value);
}
}
데이터 출력 - long 값 출력
package com.eomcs.io.ex04;
import java.io.FileOutputStream;
public class Exam0310 {
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream("temp/test3.data");
// 우리나라 1년 예산
long money = 400_0000_0000_0000L; // = 0x00016bcc41e90000
// long 메모리의 모든 바이트를 출력하려면,
// 각 바이트를 맨 끝으로 이동한 후 write()로 출력한다.
// 왜? write()는 항상 변수의 마지막 1바이트만 출력하기 때문이다.
out.write((int)(money >> 56)); // 00000000|00000000|016bcc41e90000
out.write((int)(money >> 48)); // 00000000|00000001|6bcc41e90000
out.write((int)(money >> 40)); // 00000000|0000016b|cc41e90000
out.write((int)(money >> 32)); // 00000000|00016bcc|41e90000
out.write((int)(money >> 24)); // 00000000|016bcc41|e90000
out.write((int)(money >> 16)); // 00000001|6bcc41e9|0000
out.write((int)(money >> 8)); // 0000016b|cc41e900|00
out.write((int)money); // 00016bcc|41e90000|
out.close();
System.out.println("데이터 출력 완료!");
}
}
데이터 읽기 - long 값 읽기
package com.eomcs.io.ex04;
import java.io.FileInputStream;
public class Exam0320 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("temp/test3.data");
// Exam0310을 실행하여 출력한 데이터를 read()로 읽는다.
// => 파일에서 8바이트를 읽어 8바이트 long 변수에 저장하라!
// => 읽은 바이트를 비트이동 연산자를 값을 이동 시킨 후 변수에 저장해야 한다.
// => 파일에 들어 있는 값 예: 00016bcc41e90000
long value = (long)in.read() << 56;
value += (long)in.read() << 48;
value += (long)in.read() << 40;
value += (long)in.read() << 32;
value += (long)in.read() << 24;
value += (long)in.read() << 16;
value += (long)in.read() << 8;
value += in.read();
in.close();
System.out.printf("%016x\n", value);
}
}
데이터 출력 - String 출력
package com.eomcs.io.ex04;
import java.io.FileOutputStream;
public class Exam0410 {
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream("temp/test3.data");
String str = "AB가각간";
// str.getBytes(문자코드표)
// => 문자열을 지정한 문자코드표에 따라 인코딩하여 바이트 배열을 만든다.
// => str.getBytes("UTF-8")
// UCS2 문자 ===> UTF-8 문자
out.write(str.getBytes("UTF-8"));
out.close();
System.out.println("데이터 출력 완료!");
}
}
데이터 읽기 - String 값 읽기
package com.eomcs.io.ex04;
import java.io.FileInputStream;
public class Exam0420 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("temp/test3.data");
byte[] buf = new byte[100];
int count = in.read(buf);
// Exam0410의 실행 결과로 만들어진 파일을 읽어라!
// 바이트 배열에 들어있는 값을 사용하여 String 인스턴스를 만든다.
// new String(바이트배열, 시작번호, 개수, 문자코드표)
// => 예) new String(buf, 0, 10, "UTF-8")
// buf 배열에서 0번부터 10개의 바이트를 꺼낸다.
// 그 바이트는 UTF-8 코드로 되어 있다.
// 이 UTF-8 코드 배열을 UCS2 문자 배열로 만들어 String 객체를 리턴한다.
String str = new String(buf, 0, count, "UTF-8");
in.close();
System.out.printf("%s\n", str);
}
}
FileOutputStream: float, double 값 출력
package com.eomcs.io.ex04;
import java.io.FileOutputStream;
public class Exam0510 {
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream("test6.data");
float f = 12.375f; // hex: 41460000
double d = 12.375; // hex: 4028c00000000000
// f 출력
out.write(Float.floatToIntBits(f) >> 24);
out.write(Float.floatToIntBits(f) >> 16);
out.write(Float.floatToIntBits(f) >> 8);
out.write(Float.floatToIntBits(f));
// d 출력
out.write((int)(Double.doubleToLongBits(d) >> 56));
out.write((int)(Double.doubleToLongBits(d) >> 48));
out.write((int)(Double.doubleToLongBits(d) >> 40));
out.write((int)(Double.doubleToLongBits(d) >> 32));
out.write((int)(Double.doubleToLongBits(d) >> 24));
out.write((int)(Double.doubleToLongBits(d) >> 16));
out.write((int)(Double.doubleToLongBits(d) >> 8));
out.write((int)(Double.doubleToLongBits(d)));
out.close();
System.out.println("실행 완료!");
}
}
FileInputStream: float, double 값 읽기
package com.eomcs.io.ex04;
import java.io.FileInputStream;
public class Exam0520 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("test6.data");
// float 값에 해당하는 바이트 읽기
int temp = (in.read() << 24)
+ (in.read() << 16)
+ (in.read() << 8)
+ in.read();
// int 변수에 저장된 것을 float 변수에 담기
float f = Float.intBitsToFloat(temp);
System.out.printf("%f\n", f);
// double 값에 해당하는 바이트 읽기
long temp2 = (((long) in.read()) << 56)
+ (((long) in.read()) << 48)
+ (((long) in.read()) << 40)
+ (((long) in.read()) << 32)
+ (((long) in.read()) << 24)
+ (((long) in.read()) << 16)
+ (((long) in.read()) << 8)
+ in.read();
// long 변수에 저장된 것을 double 변수에 담기
double d = Double.longBitsToDouble(temp2);
System.out.printf("%f\n", d);
in.close();
System.out.println("실행 완료!");
}
}
com.eomcs.io.ex05
객체 출력 - 인스턴스의 값을 출력
package com.eomcs.io.ex05;
import java.io.FileOutputStream;
public class Exam0110 {
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream("temp/test4.data");
Member member = new Member();
member.name = "AB가각간";
member.age = 27;
member.gender = true;
// 인스턴스의 값을 출력하라!
// 1) 이름 출력
byte[] bytes = member.name.getBytes("UTF-8");
out.write(bytes.length); // 1 바이트
out.write(bytes); // 문자열 바이트
// 2) 나이 출력 (4바이트)
out.write(member.age >> 24);
out.write(member.age >> 16);
out.write(member.age >> 8);
out.write(member.age);
// 3) 성별 출력 (1바이트)
if (member.gender)
out.write(1);
else
out.write(0);
out.close();
System.out.println("데이터 출력 완료!");
}
}
package com.eomcs.io.ex05;
public class Member {
String name;
int age;
boolean gender; // true(여자), false(남자)
@Override
public String toString() {
return "Member [name=" + name + ", age=" + age + ", gender=" + gender + "]";
}
}
객체 읽기 - 파일이 데이터를 읽어 인스턴스로 만들기
package com.eomcs.io.ex05;
import java.io.FileInputStream;
public class Exam0120 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("temp/test4.data");
Member member = null;
member = new Member();
// 1) 이름 읽기
int size = in.read(); // 이름이 저장된 바이트 배열의 수
byte[] buf = new byte[size];
in.read(buf); // 이름 배열 개수 만큼 바이트를 읽어 배열에 저장한다.
member.name = new String(buf, "UTF-8");
// 2) 나이(int) 읽기
member.age = in.read() << 24;
member.age += in.read() << 16;
member.age += in.read() << 8;
member.age += in.read();
// 3) 성별 읽기
if (in.read() == 1)
member.gender = true;
else
member.gender = false;
in.close();
System.out.printf("%s\n", member);
}
}
DataFileOutputStream을 이용하여 객체 출력 - 인스턴스의 값을 출력
package com.eomcs.io.ex05;
public class Exam0210 {
public static void main(String[] args) throws Exception {
DataFileOutputStream out = new DataFileOutputStream("temp/test4_2.data");
Member member = new Member();
member.name = "AB가각간";
member.age = 27;
member.gender = true;
// 인스턴스의 값을 출력하라!
// 1) 이름 출력
out.writeUTF(member.name);
// 2) 나이 출력 (4바이트)
out.writeInt(member.age);
// 3) 성별 출력 (1바이트)
out.writeBoolean(member.gender);
out.close();
System.out.println("데이터 출력 완료!");
}
}
package com.eomcs.io.ex05;
import java.io.FileOutputStream;
public class DataFileOutputStream extends FileOutputStream {
public DataFileOutputStream(String filename) throws Exception {
super(filename);
}
public void writeUTF(String str) throws Exception {
// 상속 받은 write() 메서드를 사용하여 문자열 출력
byte[] bytes = str.getBytes("UTF-8");
this.write(bytes.length);
this.write(bytes);
}
public void writeInt(int value) throws Exception {
// 상속 받은 write() 메서드를 사용하여 int 값 출력
this.write(value >> 24);
this.write(value >> 16);
this.write(value >> 8);
this.write(value);
}
public void writeLong(long value) throws Exception {
// 상속 받은 write() 메서드를 사용하여 long 값 출력
this.write((int)(value >> 56));
this.write((int)(value >> 48));
this.write((int)(value >> 40));
this.write((int)(value >> 32));
this.write((int)(value >> 24));
this.write((int)(value >> 16));
this.write((int)(value >> 8));
this.write((int)value);
}
public void writeBoolean(boolean value) throws Exception {
// 상속 받은 write() 메서드를 사용하여 boolean 값 출력
if (value)
this.write(1);
else
this.write(0);
}
}
DataFileInputStream으로 객체 읽기 - 파일이 데이터를 읽어 인스턴스로 만들기
package com.eomcs.io.ex05;
public class Exam0220 {
public static void main(String[] args) throws Exception {
DataFileInputStream in = new DataFileInputStream("temp/test4_2.data");
Member member = null;
member = new Member();
// 1) 이름 읽기
member.name = in.readUTF();
// 2) 나이(int) 읽기
member.age = in.readInt();
// 3) 성별 읽기
member.gender = in.readBoolean();
in.close();
System.out.printf("%s\n", member);
}
}
package com.eomcs.io.ex05;
import java.io.FileInputStream;
public class DataFileInputStream extends FileInputStream {
public DataFileInputStream(String filename) throws Exception {
super(filename);
}
public String readUTF() throws Exception {
// 상속 받은 read() 메서드를 사용하여 문자열 출력
int size = this.read();
byte[] bytes = new byte[size];
this.read(bytes); // 이름 배열 개수 만큼 바이트를 읽어 배열에 저장한다.
return new String(bytes, "UTF-8");
}
public int readInt() throws Exception {
// 상속 받은 read() 메서드를 사용하여 int 값 출력
int value = 0;
value = this.read() << 24;
value += this.read() << 16;
value += this.read() << 8;
value += this.read();
return value;
}
public long readLong() throws Exception {
// 상속 받은 read() 메서드를 사용하여 long 값 출력
long value = 0;
value += (long) this.read() << 56;
value += (long) this.read() << 48;
value += (long) this.read() << 40;
value += (long) this.read() << 32;
value += (long) this.read() << 24;
value += (long) this.read() << 16;
value += (long) this.read() << 8;
value += this.read();
return value;
}
public boolean readBoolean() throws Exception {
// 상속 받은 read() 메서드를 사용하여 boolean 값 출력
if (this.read() == 1)
return true;
else
return false;
}
}
'네이버클라우드 AIaaS 개발자 양성과정 1기 > Java' 카테고리의 다른 글
[비트캠프] 61일차(13주차3일) - Java(네트워킹), myapp-29~32 (0) | 2023.02.01 |
---|---|
[비트캠프] 60일차(13주차2일) - Java(데코레이터, I/O stream), myapp-27~28 (0) | 2023.01.31 |
[비트캠프] 59일차(13주차1일) - Java(컬렉션 API, 파일 입출력), myapp-26 (0) | 2023.01.30 |
[비트캠프] 58일차(12주차3일) - Java(람다, 메서드 레퍼런스, 제네릭), myapp-24, 25 (0) | 2023.01.27 |
[비트캠프] 57일차(12주차2일) - Java(중첩 클래스: static, non-static, local, 익명), myapp-23, backend-app 익명 클래스 적용 (0) | 2023.01.26 |