[이것이 자바다] 18. 데이터 입출력

SeonJin·2023년 9월 16일
0

Java

목록 보기
11/11
post-custom-banner

📚 이것이 자바다 [개정판]


sec01. 입출력 스트림

  • 데이터 입출력 : 데이터가 키보드, 파일, 프로그램으로부터 입출력, 저장 또는 전송되는 모든 것의 총칭
  • 스트림 : 단방향으로 데이터가 흐르는 것

sec02. 바이트 출력 스트림

  • 그림, 멀티미디어, 문자 등 모든 종류의 데이터 출력 시 사용
  • 최상위 클래스 OutputStream
  • 하위 클래스
    • FileOutputStream
    • PrintStream
    • BufferedOutputStream
    • DataOutputStream
public class WriteEx {
	public static void main(String[] args) {
		try {
			OutputStream os = new FileOutputStream("test1.db");
            
            // 1. 1byte씩 출력하는 경우
			byte a= 10, b=20, c=30; 
            os.write(a); // 1byte씩 출력
			os.write(b);
			os.write(c);
            
            // 2. 바이트 배열로 출력하는 경우
            byte[] array = {10,20,30}; 
            os.write(array); // 배열의 모든 바이트 출력
            // 특정 인덱스까지 출력하는 경우 os.write(array, 0, 1);
			
            // 공통부분
			os.flush(); // 내부 버퍼에 잔류하는 바이트를 출력 후 비움
			os.close(); // 출력 스트림을 닫고 사용 메모리 해제
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
// OutputStream은 내부에 작언 buffer를 가지고 있다
// write()는 버퍼에 바이트를 저장하고, 끝 1byte를 순서대로 출력한다
// flush()는 내부 버터에 잔류하는 모든 바이트 출력 후 버퍼를 비운다
// close()로 더이상 출력 스트림을 사용하지 않을 경우 메모리를 해제한다

sec03. 바이트 입력 스트림

  • 최상위 클래스 InputStream
  • 하위 클래스
    • FileInputStream
    • BufferedInputStream
    • DataInputStream
 public class ReadEx {
	public static void main(String[] args) {
		try {
			InputStream is = new FileInputStream("test1.db");
            
            // 1. 1byte씩 입력하는 경우
			while(true) {
				int data = is.read(); // 1byte씩 읽기
                if(data == -1) break; 
                // 더이상 읽을 수 없는 경우(끝) -1 반환하기 때문
				System.out.println(data);
			}
            
            // 2. 바이트 배열로 출력하는 경우
            byte[] data = new byte[100];
            while(true) {
            	int num = is.read(data);
                if(num == -1) break; // 파일 끝에 도달한 경우
                for(int i=0; i<num; i++) {
                	System.out.println(data[i]); // 읽은 데이터 출력
                }
            }
            
            // 공통 부분
			is.close(); // 입력 스트림을 닫고 사용 메모리 해제
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}

++ 파일 복사 방법

// FileInputStream에서 읽은 바이트를 바로 FileOutputStream으로 출력
public class CopyEx {
	public static void main(String[] args) throws Exception {
		String originalFileName = "k.jpg";
		String targetFileName = "k_copy.jpg";

		InputStream is = new FileInputStream(originalFileName);
		OutputStream os = new FileOutputStream(targetFileName);

		byte[] data = new byte[1024]; // 읽은 파일을 저장할 배열
		while (true) {
			int num = is.read(data);
			if (num == -1)break;
			os.write(data, 0, num); // 읽은 바이트 수만큼 출력
		}
		os.flush(); // 내부 버퍼 잔류 바이트 출력 후 비움
		os.close();
		is.close();

		System.out.println("복사 성공");
	}
}

sec04. 문자 입출력 스트림

문자 입출력 시 사용

  • 최상위 클래스 Write(출력) / Reader(입력)
  • 하위 클래스
    • FileWriter / FileReader
    • PrintWriter
    • BufferedWriter / bufferedReader
    • OutputStreamWriter / InputStreamReader

<문자 출력>

public class WriteEx {
	public static void main(String[] args) {
		try {
			// 문자 기반 출력 스트림 생성
			Writer writer = new FileWriter("test.txt");
			
			// 1. 1문자씩 출력
			char a = 'A';
			writer.write(a);
			char b = 'B';
			writer.write(b);
			
			// 2. char 배열 출력
			char[] arr = {'C','D','E'};
			writer.write(arr);
			
			// 3. 문자열 출력
			writer.write("FGH");
			
			// 버퍼 잔류 문자 출력, 비움
			writer.flush();
			// 출력 스트림 닫고 메모리 해제
			writer.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
// 파일 생성 결과 : ABCDEFGH

<문자 읽기>

public class ReadEx {
	public static void main(String[] args) {
		try {
			Reader reader = null;

			// 1. 1문자씩 읽기
			reader = new FileReader("test.txt");
			while (true) {
				int data = reader.read(); // 문자 읽음
				if (data == -1)
					break; // 파일을 다 읽으면 while문 종료
				System.out.println((char) data); // 읽은 문자 출력
			}
			reader.close();
			System.out.println();

			// 2. 문자 배열로 읽기
			reader = new FileReader("test.txt");
			char[] data = new char[100]; // 문자를 저장할 배열 생성
			while (true) {
				int num = reader.read(data);
				if (num == -1) break;
				for (int i = 0; i < num; i++) { // 읽은 문자 수만큼 출력
					System.out.println(data[i]);
				}
			}
			reader.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

sec05. 보조 스트림

다른 스트림과 연결되어 여러 가지 편리한 기능을 제공해주는 스트림
자체적으로 입출력을 수행할 수 없음
-> 직접 생성된 입출력 스트림에 연결하여 사용
보조스트림 변수 = new 보조스트림(입출력스트림);

  • BufferedInputStream BufferedOutputStream

sec06. 문자 변환 스트림 InputStreamReader

바이트 스트림을 문자 스트림으로 변환
문자를 바로 입출력하는 편리함 제공, 문자셋의 종류 지정 가능

// InputStream을 Reader로 변환
InputStream is = new FileInputStream("test.txt");
Reader reader = new InputStreamReader(is);

// OutputStream을 Writer로 변환
OutputStream os = new FileOutputStream("test.txt");
Writer writer = new OutputStreamReader(os);

// 예제
public class CharacterConvertStreamEx {

	public static void main(String[] args) throws Exception{
		write("문자 변환 스트림을 사용합니다.");
		String data = read();
		System.out.println(data);
	}
	
	public static void write(String str) throws Exception {
		//FileOutputStream에 OutputStreamWriter 보조스트림 연결
		OutputStream os = new FileOutputStream("test.txt");
		Writer writer = new OutputStreamWriter(os, "UTF-8");
		writer.write(str); // 보조스트림을 이용하여 문자 출력
		writer.flush();
		writer.close();
	}
	
	public static String read() throws Exception {
		//InputStream에 InputStreamReader 보조스트림을 연결
		InputStream is = new FileInputStream("test.txt");
		Reader reader = new InputStreamReader(is, "UTF-8");
		char[] data = new char[100];
		int num = reader.read(data); // 보조스트림을 이용하여 문자 입력
		reader.close();
		String str = new String(data, 0, num); // 배열에서 읽은 문자 수만큼 반환
		return str;
	}
}

sec07. 성능 향상 스트림 Buffered~

성능 향상을 위해 프로그램이 중간에 메모리 버퍼와 작업하도록 설정
데이터가 쌓이기를 기다렸다가 꽉 차는 순간 데이터를 한번에 보냄

public class BufferEx {
	public static void main(String[] args) throws Exception{
		// FileReader에 BufferedReader 보조스트림 연결
		BufferedReader br = new BufferedReader(new FileReader("test.txt"));
		
		int lineNo = 1;
		while(true) {
			String str = br.readLine(); // 한 행을 읽음
			
			if(str == null) break; // 더이상 읽을 내용이 없으면 while문 종료
			System.out.println(lineNo + "\t" + str);
			lineNo++;
		}
		br.close();
	}
}

sec08. 기본 타입 스트림 Data~Stream

기본 타입인 boolean, char, short, int, long, float, double 값 입출력 가능

public class DataInputOutputStreamEx {
	public static void main(String[] args) throws Exception{
		// DateOutputStream 생성
		FileOutputStream fos = new FileOutputStream("test.db");
		DataOutputStream dos = new DataOutputStream(fos);
		
		// 기본 타입 출력
		dos.writeUTF("홍길동");
		dos.writeDouble(95.5);
		dos.writeInt(1);
	
		dos.writeUTF("차길동");
		dos.writeDouble(90.3);
		dos.writeInt(2);
		
		dos.flush();
		dos.close();
		fos.close();
		
		// DataInputStream 생성
		FileInputStream fis = new FileInputStream("test.db");
		DataInputStream dis = new DataInputStream(fis);
		
		// 기본 타입 출력
		for(int i=0; i<2; i++) {
			String name = dis.readUTF();
			double score = dis.readDouble();
			int order = dis.readInt();
			System.out.println(name + ":" + score + ":" + order);
		}
		dis.close();
		fis.close();
	}
}

sec10. 객체 스트림 Object~Stream

메모리에 생성된 객체를 파일 또는 네트워크로 출력
객체 출력시 필드값을 일렬로 늘어선 바이트로 변경하는 과정 -> 직렬화
직렬화된 바이트를 객체의 필드값으로 복원하는 과정 -> 역직렬화

class Member implements Serializable {
	private static final long serialVersionUID = -622284561026719240L;
	private String id;
	private String name;
	public Member(String id, String name) {
		this.id = id;
		this.name = name;
	}
	@Override
	public String toString() {
		return id + ": " + name;
	}
}

class Product implements Serializable {
	private static final long serialVersionUID = -621812868470078544L;
	private String name;
	private int price;
	public Product(String name, int price) {
		this.name = name;
		this.price = price;
	}
	@Override
	public String toString() {
		return name + ": " + price;
	}
}

public class ObjectInputOutputStream {
	public static void main(String[] args) throws Exception{
		//FileOutputStream에 ObjectOutputStream 보조스트림 연결
		FileOutputStream fos = new FileOutputStream("object.dat");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		
		// 객체 생성
		Member m1 = new Member("fall", "단풍이");
		Product p1 = new Product("노트북", 1500000);
		int[] arr1 = {1,2,3};
		
		// 객체 역직렬화하여 파일에 저장
		oos.writeObject(m1);
		oos.writeObject(p1);
		oos.writeObject(arr1);
		
		oos.flush();
		oos.close();
		fos.close();
		
		FileInputStream fis = new FileInputStream("object.dat");
		ObjectInputStream ois = new ObjectInputStream(fis);
		
		// 파일을 읽고 역직렬화하여 객체로 복원
		Member m2 = (Member) ois.readObject();
		Product p2 = (Product) ois.readObject();
		int[] arr2 = (int[]) ois.readObject();
		
		ois.close();
		fis.close();
		
		// 복원된 객체 내용 확인
		System.out.println(m2);
		System.out.println(p2);
		System.out.println(Arrays.toString(arr2));
	}
}

sec11. File, Files

파일과 디렉토리 정보를 가지고 있는 클래스
File file = new File("경로")
boolean isExist = file.exists(); 존재한다면 true 리턴

<File 클래스>

public class FileEx {

	public static void main(String[] args) throws Exception{
		// File 객체 생성
		File dir = new File("images");
		File file1 = new File("file1.txt");
		File file2 = new File("file2.txt");
		File file3 = new File("file3.txt");
		
		// 존재하지 않으면 디렉토리 또는 파일 생성
		if(dir.exists() == false) {dir.mkdirs();} // 폴더 생성
		if(file1.exists() == false) {file1.createNewFile();} // 파일 생성
		if(file2.exists() == false) {file2.createNewFile();}
		if(file3.exists() == false) {file3.createNewFile();}
		
		// 폴더 내용 출력
		File temp = new File("D:\\seonjin\\javaStudy\\javaStudy\\ThisIsJava");
		File[] contents = temp.listFiles();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a HH:mm");
		for(File file : contents) {
			System.out.printf("%-25s", sdf.format(new Date(file.lastModified())));
			if(file.isDirectory()) {
				System.out.printf("%-10s%-20s", "<DIR>", file.getName());
			} else {
				System.out.printf("%-10s%-20s", file.length(), file.getName());
			}
			System.out.println();
		}
	}
}

<Files 클래스>

public class FilesEx {
	public static void main(String[] args) {
		try {
			String data = "" 
					+ "id: winter\n" 
					+ "email: winter@w.com\n" 
					+ "tel: 010-0000-0000";
			
			// Path 객체 생성
			Path path = Paths.get("user.txt");
			
			// 파일 생성 및 데이터 저장
			Files.writeString(Paths.get("user.txt"), data, Charset.forName("UTF-8"));
			
			// 파일 정보 얻기
			System.out.println("파일 유형: " + Files.probeContentType(path));
			System.out.println("파일 크기: " + Files.size(path) + "byte");
			
			// 파일 읽기
			String content = Files.readString(path, Charset.forName("UTF-8"));
			System.out.println(content); // 파일 내용
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
profile
study notebook
post-custom-banner

0개의 댓글