// 문자 기반 스트림

Reader, Writer -> 인터페이스

 

// Reader

// 데이터를 읽어온다

read(), read(char[] c), read(char[] c, int off, int len)

 

// Writer

writer(int c), writer(char[] c), writer(char[] c, int off, int len)

writer(String srt), writer(String str, int off, int len)

 

// 문자 기반 보조 스트림

BufferedReader, BufferWriter

 

FileReader, Filewriter 로 문자열 읽어오기

import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderTest1 {

	public static void main(String[] args) {
		// FileReader, Filewriter

		try {
			FileInputStream fis = new FileInputStream("test.txt");
			FileReader fr = new FileReader("test.txt");

			int data = 0;
			while ((data = fis.read()) != -1) {
				System.out.print((char) data);
			}

			System.out.println();
			fis.close();

			while ((data = fr.read()) != -1) {
				System.out.print((char) data);
			}

			fr.close();

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

	}

}

 

파일 내용 :

Hello, 안녕하세요?

 

출력 :

Hello, 안녕하세요? // 바이트 기반으로 읽어오면 한글 깨짐이 생긴다
Hello, 안녕하세요? // 문자 기반으로 읽어오면 한글 깨짐이 생기지 않는다

 

 

문자 기반 보조 스트림으로 파일 읽어오기

BufferedReader, BufferWriter

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderTest {

	public static void main(String[] args) {

		try {
			FileReader fr = new FileReader("src/BufferedReaderTest.java");
			BufferedReader br = new BufferedReader(fr); // 보조스트림(메인스트림)

			String line = "";

			// 보조스트림을 사용해 문자열을 라인단위로 읽어올 수 있다.
			// 더 이상 읽을 값이 없으면 null을 반환한다.
			for (int i = 1; (line = br.readLine()) != null; i++) {
				System.out.println(line);
			}

			br.close();

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

	}

}

 

출력 :

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderTest {

	public static void main(String[] args) {

		try {
			FileReader fr = new FileReader("src/BufferedReaderTest.java");
			BufferedReader br = new BufferedReader(fr); // 보조스트림(메인스트림)

			String line = "";

			// 보조스트림을 사용해 문자열을 라인단위로 읽어올 수 있다.
			// 더 이상 읽을 값이 없으면 null을 반환한다.
			for (int i = 1; (line = br.readLine()) != null; i++) {
				System.out.println(line);
			}

			br.close();

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

	}

}

 

 

BufferedReader의 line으로 파일 복사하기

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedReaderTest {

	public static void main(String[] args) {

		try {
			FileReader fr = new FileReader("src/BufferedReaderTest.java"); // BufferedReaderTest.bak
			BufferedReader br = new BufferedReader(fr); // 보조스트림(메인스트림)
			FileWriter fw = new FileWriter("BufferedReaderTest.bak");

			String line = "";
			
			// 보조스트림을 사용해 문자열을 라인단위로 읽어올 수 있다.
			// 더 이상 읽을 값이 없으면 null을 반환한다.
			
			while ((line = br.readLine()) != null) {
				if ( !line.endsWith("\n")) {
					line += "\n";
				}
				System.out.println(line);
				fw.write(line);
			}
			
			br.close();
			fw.close();

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

	}

}

 

결과 :

 

				if ( !line.endsWith("\n")) {
					line += "\n";
				}

위 구문을 써야하는 이유 :

BufferedReader.readLine() 메서드는 **줄 끝 문자(\\n 또는 \\r\\n)**를 만날 때까지 문자열을 읽어 하나의 문자열로 반환

때문에 저 구문 없이 실행하면 ‘BufferedReaderTest.bak’ 파일에는 다 한줄로 코드가 복사된다.

 

 

line 과 data 로 파일을 읽어오는 방법 비교

출저 : 구글 gemini

 

 

✨ 파일클래스

파일과 관련된 정보, 작업을 처리

출저 : 자바 API

맥에서 파일경로 찾기 : command + i

 

 

파일다루기

import java.io.File;
import java.io.IOException;

public class FileTest1 {

	public static void main(String[] args) {
		// File 
		// 자바에서 제공하는 라이브러리
		// 파일 또는 디렉토리 정보를 다루는 기능
		// 생성자에 정의하는파일 정보가 없어도 오류가 발생하지 않는다.
		// 파일이 존재하지 않아도 결과가 나온다. 
		
		// File f = new File("/Users/yunakang/eclipse-workspace/IOStreamProject0530/src/FileTest1.java");
		// File f = new File("/Users/yunakang/eclipse-workspace/IOStreamProject0530/src","/FileTest1.java");
		File f = new File("/Users/yunakang/eclipse-workspace/IOStreamProject0530/src","/ABC.txt");
		
		// 파일 새로 만들기
		try {
			f.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		// 파일 이름 알기
		String fileName = f.getName();
		
		System.out.println(fileName); // FileTest1.java
		
		// 파일의 경로 찾기
		System.out.println(f.getPath()); // /Users/yunakang/eclipse-workspace/IOStreamProject0530/src/FileTest1.java
		
		// 파일의 절대경로
		System.out.println(f.getAbsolutePath());
		
		// 파일 이름을 바꾸며 똑같은 내용을 가진 파일을 새로 생성 (복사의 개념)
		File newFile = new File("/Users/yunakang/eclipse-workspace/IOStreamProject0530/src","/rename.txt");
		
		f.renameTo(newFile);
		
		// 필요없는 기존 파일 지우기 
		f.delete();
		
		System.out.println(newFile.getName()); 

	}

}

 

결과 :

파일이 새로 생겼다. (자바파일로 잘못만들어서 txt파일로 고쳐줬다.)

그 후 renameTo()를 이용해 파일의 이름을 바꿔 새 파일을 만들고 기존의 파일은 삭제하는 작업까지 해보았다.

 

 

파일의 목록 읽어오기

import java.io.File;

public class FileTest2 {

	public static void main(String[] args) {
		// 파일의 목록을 읽어오는 프로그래밍
		// 목록을 읽어오기 위해서 배열로 가지고 와서 저장
		
		File f = new File("/Users/yunakang/eclipse-workspace/IOStreamProject0530");
		
		// 파일이 없을 때 체크
		if (!f.exists() || !f.isDirectory()) {
			System.out.println("파일 정보가 존재하지 않습니다");
			// 프로그램 강제 종료
			System.exit(0);
		}
		
		File[] files = f.listFiles();
		
		for (int i = 0; i < files.length; i++) {
			String fileName = files[i].getName();
			// 파일인지 디렉토리인지 구분, 파일이면 괄호 안에 이름
			System.out.println(files[i].isDirectory() ? "[" + fileName + "]" : fileName) ;
		}

	}

}

 

결과 :

FileCopy.bak
score.data
.DS_Store
[bin]
.classpath
BufferedReaderTest.bak
[.settings]
.project
test.txt
123.txt
sample.data
[src]

파일들의 목록이 잘 나온다.

 

 

 

✨ 네트워크

네트워크 : 물리적으로 떨어진 컴퓨터 간의 인터넷 망을 이용해서 연결

클라이언트와 서버 간 요청과 응답을 반복하는 구조

예를 들어 카톡의 경우, 우리가 카톡을 보내면 바로 상대에게 가는 것이 아니라 서버측에 전송한 후 서버가 전송해주는 구조. 서버는 중간관리자

회사에서도 개발팀에 서버측과 클라이언트측이 있음. 연차가 낮으면 클라이언트측, 연차가 높으면 서버측.

서버가 어렵다. 중요한 기술이 많다!

→ 향후 모델은 다름!

앞으로는 내 컴퓨터가 클라이언트이자 서버

예 ) 토랜트

 

 

컴퓨터의 주소 : IP

서버와 클라이언트 간 통신을 위해 주소가 필요함.

고정IP : 사용자 계정(아이디)에 IP주소 지정, 독점

유동IP : 서버에 여러 개의 IP주소 존재, 서버에 접속하는 순간 임의의 IP주소 할당

우리가 쓰는 것은 로컬IP

 

통신규약 (TCP)/ IP

데이터에 따라 보내는 방식이 다름.

데이터를 보낼 때 IP를 사용.

→ 데이터를 보낼 때는 무조건 스트림이 필요하다.

 

스트림 : 데이터를 보내는 통로

스트림을 주고 받을 때는 in 과 out, 두 개의 스트림이 필요하다.

스크림의 in/out은 상대적.

 

소켓 Socket 으로 컴퓨터를 연결해주면 스트림으로 컴퓨터와 통신

소켓도 서버와 클라이언트 하나씩 존재

서버는 두 개의 소켓과 하나의 포트로 구성

  • ServerSocket → 감시용
  • Socket → 통신용
  • port (아파트의 동과 호)

→ 포트번호는 고유하다

 

클라이언트의 소켓은 한 가지

  • Socket

서버소켓이 하는 일 : 항상 돌아가며 감지하기

 

서버와 클라이언트 만들어보기

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpIpClient {

	public static void main(String[] args) {
		// 서버의 IP주소와 포트번호를 알아야 한다

		String serverIp = "192.168.105.80";

		System.out.println("서버에 연결 중 입니다. 서버IP :" + serverIp);

		Socket socket;
		try {

			socket = new Socket(serverIp, 7777);
			InputStream in = socket.getInputStream();
			DataInputStream dis = new DataInputStream(in);

			System.out.println("서버로부터 받은 메세지 : " + dis.readUTF());
			System.out.println("연결종료");

			dis.close();
			socket.close();

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

		}
	}

}

클라이언트는 결과가 출력되고 실행이 안되지만 서버는 계속 돌아가고 있다.

서버를 꺼줘야 오류가 생기지 않는다.

 

 

 

🍀 문자채팅이 가능한 서버와 클라이언트 만들기

항상 서버 먼저 실행 후 클라이언트 실행

하나의 파일 안에 하나의 클래스에만 퍼블릭을 붙일 수 있다

 

서버 :

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpIpSever2 {

	public static void main(String[] args) {

		ServerSocket serverSocket = null;
		Socket socket = null;

		try {
			serverSocket = new ServerSocket(7777);
			System.out.println("서버가 준비되었습니다.");

			socket = serverSocket.accept();

			// 데이터 전송
			Sender sender = new Sender(socket);

			// 데이터 수신
			Receiver receiver = new Receiver(socket);
			
			// 독립적인 스레드로 각각 동작한다
			sender.start();
			receiver.start();

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

	}

}

// 데이터 전송
class Sender extends Thread {

	// 소켓 정보를 초기화하는 생성자
	Socket socket;
	DataOutputStream out;
	String name;

	public Sender(Socket socket) {

		this.socket = socket;

		// DataOutputStream 초기화
		// getOutputStream()을 쓸 때는 예외처리
		try {
			out = new DataOutputStream(socket.getOutputStream());
			// 사용자의 IP 주소와 포트번호 받아오기
			name = "[" + socket.getInetAddress() + " : " + socket.getPort() + "]";
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		// 입력된 값을 처리해서 보내는 부분
		Scanner sc = new Scanner(System.in);

		// 데이터를 받을 상대가 있는지 없는지 체크
		while (out != null) {
			try {
				System.out.print(">>");
				out.writeUTF(name + sc.nextLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}

//데이터 수신
class Receiver extends Thread {

	Socket socket;
	DataInputStream in;

	public Receiver(Socket socket) {
		this.socket = socket;

		try {
			in = new DataInputStream(socket.getInputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	@Override
	public void run() {
		while (in != null) {
			try {
				System.out.println(in.readUTF());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}

 

클라이언트 :

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpIpClient2 {

	public static void main(String[] args) {
		String serverIp = "192.168.105.80";

		System.out.println("서버에 연결 중 입니다. 서버IP :" + serverIp);
		
		Socket socket;
		
		try {
			
			socket = new Socket(serverIp, 7777);
			
			Sender sender = new Sender(socket);
			Receiver receiver = new Receiver(socket);
			
			sender.start();
			receiver.start();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

서버에 연결되었다.

혼자 대화를 해보았다.

 

 

다른 사람과 채팅해보기

클라이언트가 대화하려는 사람의 아이피를 받아 클라이언트에 넣어주기

그 다음 서버 실행하면 클라이언트 측 실행

와이파이는 와이파이끼리, 같은 와이파이를 써야한다

성공~!

 

 

 

 

다음 주, 맥 오라클 깔아야함 11g Enterprise

docker pull paliari/oracle-xe-11g

docker run --name oracle -d -p 1521:1521 paliari/oracle-xe-11g

+ Recent posts