본문 바로가기

JAVA 공책/수업 메모

Map추가 & PrintWriter & Serializable : 복습 꼭 필요!

Map추가 & PrintWriter & Serializable


{Map}

- key와 value를 쌍으로 저장하는 자료구조
- key와 value 모두 Generic 적용
- key는 set으로 구성(중복되지 않는다는 뜻)

[구현된 클래스]
1) HashMap : 진짜로 순서를 모름
2) LinkedHashMap : 순서를 기억
3) TreeMap : Tree라고 하면 '정렬'을 생각하면 되고, 넣는 즉시 정렬합니다
-사진 첨부

[메소드]
- void put(key, value) : 저장 or 동일한 키가 있으면 갱신
- Object(Generic) get(key) : 키에 해당하는 데이터 리턴
- 만들 때 Generic을 사용하면 Generic으로, Generic을 사용하지 않으면 Object로 리턴.
-key를 입력하면 null 리턴(한번도 저장한 적이 없다는 뜻)
- remove(key) : 삭제

※ 참고
Set keyset() : 
- for(★ : 컬렉션[각주:1]), 여기서 다른 언어에서는 디션어리와 맵도 집어 넣을 수 있는데 자바는 안되기 때문에 있는 클래스와 메소드입니다.
- key들을 set으로 리턴합니다.
-그러면 모든 데이터를 출력하는 for(★:컬렉션) 구문에서 Map을 set으로 바꾸어 집어 넣을 수 있습니다. 

※ 참고
데이터 처리의 순서도
데이터
데이터 읽기 〓 자료구조[각주:2]
전처리 〓 불필요한 데이터 제거 & 잘못된 데이터 수정
저장
처리 〓 알고리즘
분석
시각화

소스코드를 보고(얘가 뭘 하려고 했는지) → 안 보고 비슷하게 만들어 보고 → 많이 쓰면서 외우는 것(일부러 외우는 것은 바보 같은 짓이다)

 파일- 통신

 스트림 생성

 바이트 스트림

(바이트 단위 - 텍스트 파일을 제외한 모든 자료)

 캐릭터 스트림

(텍스트 파일)

ObjectInputStream

ObjectOutputStream

파일을 읽고 출력 시키기 위한

 FileReader

FileWriter 

 FileInputStream

 FileOutputStream

 ↓

 ↓

 

 

 버퍼를 하기 위한

 BufferedReader

 PrintWriter

 BufferedInputStream

 PrintStream



{로그파일을 읽어서 ip 별 접속횟수 출력하기}

※ 참고
import 단축키 : ctrl + shift + o 

- 로그 파일을 읽을 수 있는 스트림을 생성합니다.
- 로그 파일은 문자열이 기록된 파일이므로 Character Stream을 이용해야 합니다.
읽을 때는 네이티브 메소드 호출횟수를 줄이기 위해서 버퍼를 사용해서 읽고 쓰는 것이 좋습니다.
- BufferedReader를 이용해서 읽는 것이 좋습니다.

1. BufferedReader 객체 만들기

BufferedReader br = null;
try {
    br = new BufferedReader(new FileReader("./access_log.txt"));
} catch (Exception e) {
    System.out.println(e.getMessage());
} finally {
    try {
        if (br != null)
            br.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

2. 줄 단위로 데이터를 읽어서 출력
- BufferedReader 클래스의 readLine 이라는 메소드가 줄 단위로 읽어서 String으로 리턴해주는 메소드입니다.
이 메소드는 읽은 데이터가 없으면 null을 리턴합니다.
- null이 나올때까지 일어야 하며, ~때까지는 while반복문을 생각할 수 있습니다. ~부터 ~까지는 for반복문을 생각할 수 있습니다.
- BufferedReader 객체를 생성하는 부분 뒤에 작성


while(true) {
    String line = br.readLine();
    if(line == null) {
        break;
    }
    System.out.println(line);
}


3. 줄 단위로 읽은 데이터를 공백으로 분할해서 첫번째에 있는 데이터만 출력
- 문자열을 분할을 할 때는 split 이나 substring이라는 메소드를 이용합니다.
- split은 문자열이나 패턴을 가지고 분할하고 substring은 위치를 가지고 분할합니다.


while(true) {
    String line = br.readLine();
    if(line == null) {
        break;
    }
    //System.out.println(line);
    String [] ar = line.split(" ");
    System.out.println(ar[0]);
}


4. HashMap을 활용해서 첫번째 데이터의 횟수를 저장하고 출력하기
- Map은 동일한 키를 가지고 데이터를 저장하면 수정이 발생하고 없는 키의 값을 읽을려고 하면 null을 리턴합니다.


//4.HashMap을 이용해서 접속한 IP 별 횟수를 출력
HashMap<String, Integer> map =
    new HashMap<>();
while(true) {
    String line = br.readLine();
    if(line == null) {
        break;
    }
    String [] ar = line.split(" ");
    //ip로 저장된 데이터를 가져옵니다.
    Integer count = map.get(ar[0]);
    //저장된 데이터가 없으면 1을 저장합니다.
    if(count == null) {
        map.put(ar[0], 1);
    }
    //저장된 데이터가 있으면 1을 더해서 저장합니다.
    else {
        map.put(ar[0], count + 1);
    }
}
            
//맵의 모든 데이터를 출력
Set<String> keySet = map.keySet();
for(String key : keySet) {
    System.out.println(key + ":" + map.get(key));
}


5. ip 별 트래픽의 합계를 저장해서 출력
- 트래픽을 한 줄을 기준으로 공백으로 분할하면 10번째에 존재
- - 와 "-" 라는 이상한 데이터가 포함되어 있습니다.


//4.HashMap을 이용해서 접속한 IP 별 횟수를 출력
HashMap<String, Integer> map =
    new HashMap<>();

//5.HashMap을 이용해서 접속할 IP 별 트래픽 합계 출력
HashMap<String, Integer> traffic =
    new HashMap<>();

while(true) {
    String line = br.readLine();
    if(line == null) {
        break;
    }
    String [] ar = line.split(" ");
    //ip로 저장된 데이터를 가져옵니다.
    Integer count = map.get(ar[0]);
    //저장된 데이터가 없으면 1을 저장합니다.
    if(count == null) {
        map.put(ar[0], 1);
    }
    //저장된 데이터가 있으면 1을 더해서 저장합니다.
    else {
        map.put(ar[0], count + 1);
    }
                
    Integer traf = traffic.get(ar[0]);
    if(traf == null) {
        if(!ar[9].equals("\"-\"") && !ar[9].equals("-")) {
            traffic.put(ar[0],Integer.parseInt(ar[9]));
    }
    }else {
        if(!ar[9].equals("\"-\"") && !ar[9].equals("-")) {
            traffic.put(ar[0], traf + Integer.parseInt(ar[9]));
        }
    }
                
}
            
//맵의 모든 데이터를 출력
Set<String> keySet = map.keySet();
for(String key : keySet) {
    System.out.println(key + ":" + map.get(key));
}
            
System.out.println("================");
keySet = traffic.keySet();
for(String key : keySet) {
    System.out.println(key + ":" + traffic.get(key));
}


내 완성 →
//로그파일을 읽어서 아이피 별 접속횟수 출력하기
         //<--작업 순서도-->
         //1. 로그 파일을 읽을 수 있는 스트림을 생성한다.
         //->로그 파일은 문자열이 기록된 파일이므로 CharacterStream을 이용해야 합니다.
         //->읽을 대는 네이티브 메소드 호출횟수를 줄이기 위해서 버퍼를 사용해서 읽고 쓰는 것이 좋습니다.
         //->BufferedReader를 이용해서 읽는 것이 좋습니다.
         
         //줄단위로 읽어 올 수 있는 메소드가 있는 BufferedReader
         BufferedReader bfr = null;
         
                   try {
                       bfr = new BufferedReader(new FileReader("C:\\Users\\503-26\\Desktop\\access_log.txt"));
                       ArrayList dataLine = new ArrayList();
                       HashMap<String, Integer> map = new HashMap<>();
                       //5.HashMap을 이용해서 접속할 아이피 별 트래픽 합계 출력
                       HashMap<String, Integer> traffic = new HashMap<>();
                       while(true) {
                            String oneLine = bfr.readLine();
                            if(oneLine == null) break;
                            //공백 단위로 저장
                            String [] ar = oneLine.split(" ");
                            //ip 출력
                            //System.out.println(ar[0]);
                            //4.아이피로 저장된 데이터를 가져오기
                            Integer count = map.get(ar[0]);
                            System.out.println(count);
                            //저장된 데이터가 없으면 1을 저장하기
                            if(count == null) {
                                 map.put(ar[0],1);
                            }else {
                                 map.put(ar[0],count+1);
                            }
                            //이쪽이 잘 못 됨.
                            Integer traf = traffic.get(ar[0]);
                            System.out.println(traf);
                            if(traf == null) {
                                 if(!ar[0].equals("-") && ar[0].equals("\"-\"")) {
                                      traffic.put(ar[0], Integer.parseInt(ar[9]));
                                 }
                            }else {
                                 if(!ar[0].equals("-") && ar[0].equals("\"-\"")) {
                                      traffic.put(ar[0],traf+Integer.parseInt(ar[9]));
                                 }
                            }
                            //맵의 모든 데이터 출력
                            Set<String> keyset = map.keySet();
                            for(String key : keyset) {
                                 System.out.println(key);
                            }
                            
                            Set<String> trafset = traffic.keySet();
                            for(String trafsum : trafset) {
                                 System.out.println(trafsum);
                            }
                       }
                   }catch(Exception e) {
                        System.out.println(e.getMessage());
                   }finally {
                            try {
                                 if(bfr != null)
                                 bfr.close();
                            } catch (IOException e) {
                                 // TODO Auto-generated catch block
                                 e.printStackTrace();
                            }

{PirntWriter}

- 파일이나 네트워크에서 문자 단위로 데이터를 전송하기 위한 클래스
- 버퍼링을 이용해서 전송을 하기 때문에 네이티브 메소드[각주:3] 횟수를 줄여서 출력 효율을 높여 줍니다.

1. 생성자
- 문자열로 파일의 경로를 받아서 생성 가능
- File 객체로 파일을 받아서 생성 가능
- OutputStream 객체를 받아서 생성 가능
- Writer 객체를 받아서 생성 가능

2. 메소드
- print, printf, println 으로 전송할 수 있고 flush 메소드를 이용해서 버퍼의 내용을 전부 전송합니다.


{Serializable}

- 파일이나 네트워크에 데이터를 전송할 대 객체 단위로 전송할 수 있도록 해주는 인터페이스입니다.
- ObjectInputStream과 ObjectOutputStream 클래스를 이용합니다.
- Serializable 인터페이스를 implements 한 객체 단위로 데이터를 전송하게 되면 그 클래스가 없으면 데이터를 읽을 수 없습니다.
- 응용 프로그램을 만들 때는 데이터를 위한 클래스를 만들고 이 클래스의 객체 단위로 데이터를 저장해서 다른 응용 프로그램에서 데이터를 읽을 수 없도록 합니다.
- serializable에서 제외하고자 하는 변수가 있는 경우에는 transient라는 예약어를 이용.

[ObjectInputStream]
- 객체 생성은 InputStream을 받아서 합니다.
- 파일에서 읽어올 때는 FileInputStream을 만들어서 대입하면 되고 네트워크 일 때는 네트워크의 InputStream을 받아서 생성하면 됩니다.
- 데이터를 읽을 때는 readObject 메소드를 이용하는데 리턴되는 데이터 타입이 Object로 리턴되기 때문에 출력만 할 때는 바로 하면 되지만 사용할 때는 강제 형변환을 해서 원래의 자료형으로 되돌려 사용합니다.

[ObjectOutputStream]
- 객체 생성은 OutputStream을 받아서 합니다.
- 파일에서 기록 할 때는 FileOutputStream을 만들어서 대입하면 되고 네트워크 일 때는 네트워크의 OutputStream을 받아서 생성하면 됩니다.
- 기록은 writerObject 메소드를 이용해서 저장할 객체를 대입하면 됩니다.

[안드로이드]
- 안드로이드의 Activity 전환에서 데이터를 전달 할 때는 이 방식을 이용하기 때문에 Serializable 인터페이스를 implements 한 객체만 전달이 가능합니다.


{파일에 객체 단위로 기록하고 읽기}

1. 기록할 객체의 클래스 생성 - Serializable 인터페이스를 implements


public class Member implements Serializable{
    private String email;
    private String pw;
    private String phone;
    
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPw() {
        return pw;
    }
    public void setPw(String pw) {
        this.pw = pw;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    
    @Override
    public String toString() {
        return "Member [email=" + email + ", pw=" + pw + ", phone=" + phone + "]";
    }
}


2. 1번에서 만든 클래스의 객체를 파일에 기록하는 작업을 위한 main메소드를 소유한 클래스 생성


public class ObjectMain {

    public static void main(String[] args) {
        //객체 단위로 데이터를 기록할 수 있는 클래스의 변수 선언
        ObjectOutputStream oos = null;
        try {
            //파일에 객체 단위로 기록할 수 있는 클래스의
            //객체 만들기
            oos = new ObjectOutputStream(
                new FileOutputStream("./oos.txt"));
            
            Member member = new Member();
            member.setEmail("ggangpae1@gmail.com");
            member.setPw("1234");
            member.setPhone("01037901997");
            
            //객체를 파일에 기록
            oos.writeObject(member);
            
        }catch(Exception e) {
            System.out.println(e.getMessage());
        }finally {
            if(oos != null)
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    }

}


3. 메인을 변경해서 읽기


public class ObjectMain {

    public static void main(String[] args) {
        //객체 단위로 데이터를 기록할 수 있는 클래스의 변수 선언
        ObjectInputStream ois = null;
        try {
            //파일에 객체 단위로 기록할 수 있는 클래스의
            //객체 만들기
            ois = new ObjectInputStream(
                new FileInputStream("./oos.txt"));
            //read로 읽어올 때 Object 타입으로 리턴하기 때문에
            //강제 형 변환을 해서 원래의 자료형으로
            //되돌려서 사용해야 합니다.
            Member member = (Member)ois.readObject();
            System.out.println(member.getEmail());
            
            
        }catch(Exception e) {
            System.out.println(e.getMessage());
        }finally {
            if(ois != null)
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    }

}

내 완성→









  1. 배열, List, Set [본문으로]
  2. (자료구조를 사용하려면 어떤것에 적합한지, 자료를 쭉 읽어봐야 합니다.) [본문으로]
  3. 운영체제가 파일을 주고받기 위해 사용하는 메소드 [본문으로]

'JAVA 공책 > 수업 메모' 카테고리의 다른 글

조건문&반복문  (0) 2018.07.23
네트워크  (0) 2018.07.23
java.io.File  (0) 2018.07.19
Swing  (0) 2018.07.19
[완전 중요] Object 클래스에 관하여  (0) 2018.07.19