자바 바이트 흐름 과 문자 흐름 총 결 IO 흐름!

수신 입력 값 부터 말하자면
일상적인 개발 응용 에서 키보드 와 같은 외부 장치 의 입력 값 을 직접 받 아야 할 때 가 있 습 니 다.이런 데이터 의 수신 방식 에 대해 우 리 는 보통 세 가지 방법 이 있 습 니 다.바이트 흐름 읽 기,문자 흐름 읽 기,Scanner 도구 류 읽 기 입 니 다.
바이트 흐름 읽 기
예 를 직접 보 세 요.

public class Demo01SystemIn {
    public static void main(String[] args) throws IOException {
        int a = System.in.read();
        System.out.println(a);
        char c = 'a';
        System.out.println((int) c);
    }
}
프로그램 을 실행 한 후에 read 방법 에 의 해 막 힐 것 입 니 다.이때 콘 솔 에 문자 a 를 입력 하면 위의 프로그램 두 마디 가 97 을 출력 합 니 다.이것 은 문제 가 없습니다.소문 자 a 가 대응 하 는 것 이 97 이기 때 문 입 니 다.만약 에 우리 가 중국 어 를 입력 하면 어떤 결과 가 나 올 까요?
위의 예제 중의 a 를 중 으로 수정 한 다음 에 프로그램 을 실행 합 니 다.콘 솔 에서 같은 입력 을 하면 228 과 20013 을 얻 을 수 있 습 니 다.이것 은 우리 콘 솔 이 입력 한 것 을 모두 읽 지 않 았 다 는 것 을 설명 합 니 다.그 이 유 는 read 가 1 바이트 만 읽 을 수 있 기 때 문 입 니 다.결론 을 더욱 검증 하기 위해 우 리 는 위의 예 를 바 꾸 었 습 니 다.

public class Demo01SystemIn {
    public static void main(String[] args) throws IOException {
        char a = (char) System.in.read();//      
        System.out.println(a);
        char c = ' ';
        System.out.println(c);
    }
}
실행 후 다음 과 같은 결 과 를 얻 을 수 있 습 니 다:

첫 번 째 출력 이 엉망 이 된 것 을 볼 수 있 습 니 다.System.in.read()는 한 번 에 한 바이트 만 읽 을 수 있 고 중국 어 는 utf-8 인 코딩 에서 3 바이트 만 사용 합 니 다.read 방법 은 한 번 에 한 바이트 만 읽 을 수 있 기 때문에 그 범 위 는-1~255 사이 에 만 있 을 수 있 습 니 다.-1 은 끝 까지 읽 었 음 을 표시 합 니 다.[참고 문헌
그렇다면 중국 어 를 완전히 읽 으 려 면 어떻게 해 야 할 까?
문자 흐름 읽 기
우 리 는 먼저 다음 예 를 보 자.

public class Demo01SystemIn {
    public static void main(String[] args) throws IOException {
        InputStreamReader inputStreamReader1 = new InputStreamReader(System.in);
        int b = inputStreamReader1.read();//       
        System.out.println(b);
        InputStreamReader inputStreamReader2 = new InputStreamReader(System.in);
        char[] chars = new char[2];
        int c = inputStreamReader2.read(chars);//     char  ,           
        System.out.println("       :" + c);
        System.out.println(chars[0]);
        System.out.println(chars[1]);
    }
}//  Java      :756584822      
실행 후 출력 결 과 는 다음 과 같 습 니 다.

이 럴 때 우 리 는 이미 한 문 자 를 읽 을 수 있 습 니 다.물론 최적화 하기 위해 서 우 리 는 Buffered Reader 를 사용 하여 진일보 한 포장 을 해 야 합 니 다.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
이런 방식 은 중국 어 를 읽 으 면 코드 가 흐 트 러 지 는 문 제 를 해 결 했 지만 사용 하기에 도 불편 하기 때문에 일반적으로 키보드 입력 정 보 를 읽 을 때 우 리 는 모두 Scnner 로 읽는다.
스캐너 읽 기
Scanner 는 실제 적 으로 System.in 을 패키지 하고 다양한 문자 형식 을 읽 는 일련의 방법 을 제공 했다.예 를 들 어 nextInt,nextFloat,next 등 이다.

public class Demo02Scnner {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()){
            System.out.println(scanner.nextInt());
        }
    }//  Java      :756584822      
}
IO 흐름 이란 무엇 인가
흐름 은 추상 적 인 개념 으로 데이터 의 비구 조 화 된 전송(바 이 두 백과 에서 발췌)을 대표 한다.IO 흐름 에 대응 하 는 것 은 InPut 와 Output,즉 입 출력 이다.입력 과 출력 이라는 개념 은 응용 프로그램 에 대한 것 입 니 다.예 를 들 어 현재 프로그램 에서 파일 의 내용 을 읽 어야 합 니 다.이것 이 바로 입력 입 니 다.프로그램 자체 의 데 이 터 를 다른 응용 프로그램 에 보 내 려 면 출력 에 대응 합 니 다.
바이트 흐름 과 문자 흐름
흐름 에 따라 흐름 을 두 가지 유형 으로 나 눌 수 있 습 니 다.바이트 흐름 과 문자 흐름 입 니 다.
바이트 흐름
바이트 흐름 이 읽 는 기본 단 위 는 바이트 이 고 ASCII 인 코딩 을 사용 합 니 다.보통 바 이 너 리 데 이 터 를 처리 하 는 데 사 용 됩 니 다.맨 위 에 있 는 추상 적 인 종 류 는 InputStream 과 OutputStream 입 니 다.예 를 들 어 상기 예제 에서 System.in 은 실제 적 으로 InputStream 류 를 얻 었 습 니 다.
자바 의 흐름 가족 은 매우 크 고 다양한 기능 을 가 진 흐름 을 제공 하 며 실제 응용 에서 우 리 는 서로 다른 조합 을 선택 하여 목적 을 달성 할 수 있다.
바이트 입력 흐름
다음 그림 은 바이트 입력 흐름 가족 관계 설명도 입 니 다.

위의 그림 에서 볼 수 있 듯 이 이런 구 조 는 매우 뚜렷 하 다.먼저 가장 꼭대기 층 의 인터페이스 이 고 그 다음은 서로 다른 기능 의 기초 흐름 이다.예 를 들 어 우리 가 가장 자주 사용 하 는 FileInputStream 은 파일 을 읽 는 데 쓰 인 다.그 중에서 FilterInputStream 흐름 이 있 는데 이 흐름 은 주로 기초 흐름 기능 을 확장 하 는 데 쓰 인 다.그 자 체 는 부모 클래스 InputStream 의 모든 방법 을 간단하게 덮어 씌 웠 을 뿐 특별한 처 리 를 하지 않 았 습 니 다.진정한 기능 확장 은 여러 하위 클래스 에 의존 해 야 합 니 다.예 를 들 어 가장 자주 사용 하 는 BufferedInputStream 은 데이터 버퍼 를 제공 하여 읽 기 흐름 의 효율 을 향상 시 켰 고 DataInputStream 은 바 이 너 리 데 이 터 를 처리 할 수 있 습 니 다.
이러한 다양한 기능 의 흐름 을 통 해 조합 하면 우리 가 필요 로 하 는 데 이 터 를 유연 하 게 읽 을 수 있다.예 를 들 어 바 이 너 리 파일 을 읽 으 려 면 DataInputStream 을 사용 해 야 합 니 다.DataInputStream 자 체 는 파일 내용 을 직접 읽 는 기능 이 없 기 때문에 FileInputStream 과 결합 해 야 합 니 다.

FileInputStream fin = new FileInputStream("E:\\test.txt");
DataInputStream din = new DataInputStream(fin);
System.out.println(din.readInt());
또한 버퍼 메커니즘 을 사용 하려 면 BufferedInputStream 을 더 조립 할 수 있 습 니 다.

FileInputStream fin = new FileInputStream("E:\\test.txt");
DataInputStream din = new DataInputStream(new BufferedInputStream(fin));
System.out.println(din.readInt());
또 하나의 흐름 이 재 미 있 습 니 다.바로 Pushback InputStream 입 니 다.이 흐름 은 읽 은 데 이 터 를 다시 흐름 으로 되 돌 릴 수 있 습 니 다.

public class Demo03 {
    public static void main(String[] args) throws IOException {
        FileInputStream fin = new FileInputStream("E:\\test.txt");//      abcd
        PushbackInputStream pin = new PushbackInputStream(new BufferedInputStream(fin));
//  Java      :756584822      
        int a = pin.read();//   a
        System.out.println(a);
        if (a != 'b'){
            pin.unread(a);//  a     
        }
        System.out.println(pin.read());//      a
        System.out.println(pin.read());//    b
        System.out.println(pin.read());//     c
    }
}
바이트 출력 흐름
다음 그림 은 바이트 출력 흐름 가족 관계 설명도 입 니 다.

이 구 조 는 입력 흐름 의 구조 와 기본적으로 유사 하 며,같은 우리 도 조합 을 통 해 서로 다른 출력 을 실현 할 수 있다.
예 를 들 어 일반적인 출력 파일 은 FileOutputStream 흐름 을 사용 할 수 있 습 니 다.

FileOutputStream fout = new FileOutputStream("E:\\test2.txt");
fout.write(1);
fout.write(2);
바 이 너 리 형식 을 출력 하려 면 DataOutput Stream 흐름 을 조합 할 수 있 습 니 다.

FileOutputStream fout = new FileOutputStream("E:\\test2.txt");
DataOutputStream dout = new DataOutputStream(fout);
dout.write(9);//  Java      :756584822      
dout.write(10);
완충 류 의 원리
IO 작업 은 시간 이 걸 리 는 작업 입 니 다.바이트 흐름 의 read 방법 은 한 번 에 한 바이트 만 되 돌아 갈 수 있 습 니 다.그러면 여러 바이트 를 읽 어야 할 때 읽 을 때마다 IO 작업 이 발생 합 니 다.버퍼 흐름 내 부 는 8192 크기 의 byte 배열 을 정의 합 니 다.버퍼 흐름 을 사용 할 때데 이 터 를 읽 을 때 최대 8192 개의 바이트 를 한꺼번에 읽 어 메모리 에 넣 고 하나씩 돌아 오 면 IO 횟수 가 크게 줄어든다.마찬가지 로 데 이 터 를 쓸 때 버퍼 흐름 은 데 이 터 를 메모리 에 먼저 기록 합 니 다.우리 가 쓸 데 이 터 를 다 썼 을 때 디스크 등 지정 한 위치 로 한꺼번에 새로 고 칩 니 다.
문자 흐름
문자 흐름 이 읽 는 기본 단 위 는 문자 이 고 유 니 코드 인 코딩 을 사용 합 니 다.read 방법 은 유 니 코드 인 코딩(0~65535)을 되 돌려 줍 니 다.
문자 흐름 은 보통 텍스트 데 이 터 를 처리 하 는 데 사 용 됩 니 다.최상 위 추상 류 는 Reader 와 Write 입 니 다.예 를 들 어 글 의 첫 번 째 예제 중의 InputStreamReader 는 바로 Reader 류 를 계승 하 는 것 입 니 다.
문자 입력 흐름
다음 그림 은 문자 입력 흐름 가족 관계 설명도 입 니 다:

위의 그림 에서 알 수 있 듯 이 최상 위 Reader 류 를 제외 하고 문자 흐름 도 텍스트 데 이 터 를 처리 하 는 기본 적 인 문자 흐름 을 제공 합 니 다.예 를 들 어 우 리 는 텍스트 에서 내용 을 읽 어야 합 니 다.

public class Demo05Reader {
    public static void main(String[] args) throws Exception {
        //   
        FileInputStream fin = new FileInputStream("E:\\test.txt");//     “    ”
        System.out.println(fin.read());//372
        //   
        //  Java      :756584822      
        InputStreamReader ir = new InputStreamReader(new FileInputStream("E:\\test.txt"));//     “    ”
        System.out.println(ir.read());//21452
        char s = ' ';
        System.out.println((int)s);//21452
    }
}
출력 한 후에 차이 점 을 뚜렷하게 볼 수 있 습 니 다.바이트 흐름 은 한 번 에 한 바이트 씩 읽 고 문 자 는 한 번 에 한 문 자 를 읽 습 니 다.
물론 저 희 는 자 유 롭 게 조합 하 는 방식 으로 문자 읽 기 를 더욱 유연 하 게 할 수 있 습 니 다.예 를 들 어 저 희 는 Buffered Reader 와 결합 하여 전체 줄 의 데 이 터 를 읽 을 수 있 습 니 다.

public class Demo05Reader {
    public static void main(String[] args) throws Exception {
        InputStreamReader ir = new InputStreamReader(new FileInputStream("E:\\test.txt"));//     “    ”
        BufferedReader br = new BufferedReader(ir);
        String s;
        while (null != (s = br.readLine())){
            System.out.println(s);//      
        }
    }
}
문자 출력 흐름
다음 그림 은 문자 출력 흐름 가족 관계 설명도 입 니 다.

텍스트 출력,우리 가 가장 많이 사용 하 는 것 은 PrintWriter 입 니 다.이런 종 류 는 대부분 친구 들 이 사용 한 적 이 있다 고 생각 합 니 다.

public class Demo06Writer {
    public static void main(String[] args) throws Exception{
        PrintWriter printWriter = new PrintWriter("E:\\test3.txt");
        printWriter.write("    ");
        printWriter.flush();
    }
}
바이트 흐름 과 의 차 이 는 다 쓴 후에 flush 방법 을 수 동 으로 호출 해 야 한 다 는 것 입 니 다.그렇지 않 으 면 데이터 가 손실 되 고 파일 에 쓰 이지 않 습 니 다.
왜 문자 흐름 은 flush 가 필요 하고 바이트 흐름 은 필요 하지 않 습 니까?
바이트 흐름 은 flush 작업 이 필요 하지 않 습 니 다.바이트 흐름 은 바이트 입 니 다.중간 에 어떠한 변환 도 할 필요 가 없 기 때문에 파일 을 직접 조작 할 수 있 습 니 다.문자 흐름 은 결국 그 밑 에 있 는 것 이 바이트 흐름 입 니 다.그러나 문자 흐름 은 바 이 트 를 문자 로 바 꾸 는 데 도움 을 주 었 습 니 다.이 전환 은 문자 표 에 의존 해 야 합 니 다.따라서 문자 와 바이트 가 바 뀐 후에 flush 작업 을 통 해 디스크 에 닦 아야 합 니 다.
주의해 야 할 것 은 바이트 출력 흐름 의 최상 위 클래스 인 OutputStream 에서 도 flush 방법 을 제공 하지만 빈 방법 입 니 다.하위 클래스 가 필요 하 다 면 flush 방법 을 실현 할 수 있 습 니 다.
RandomAccessFile
RandomAccessFile 은 파일 의 임의의 위치 에서 데 이 터 를 찾 거나 기록 할 수 있 는 무 작위 접근 파일 클래스 입 니 다.

public class Demo07RandomAccessFile {
    public static void main(String[] args) throws Exception {
        //      lonely wolf
        RandomAccessFile inOut = new RandomAccessFile(new File("E:\\test.txt"),"rw");
        System.out.println("     :" + inOut.getFilePointer());//   0
        System.out.println((char) inOut.read());//   l
        System.out.println("     :" + inOut.getFilePointer());
        inOut.seek(7L);//     7   
        System.out.println((char) inOut.read());//   w
        inOut.seek(7);//    7
        //  Java      :756584822      
        inOut.write(new byte[]{'c','h','i','n','a'});//   china,   wolf   
        inOut.seek(7);//      7
        System.out.println((char) inOut.read());//     wolf   china  ,     c
    }
}
위의 예제 에서 출력 결 과 를 보면 RandomAccessFile 류 는 랜 덤 으로 지침 을 지정 하고 랜 덤 으로 읽 기와 쓰 기 를 할 수 있어 기능 이 매우 강하 다.
또한 설명 해 야 할 것 은 RandomAccessFile 을 구성 할 때 하나의 모델 이 들 어 와 야 하 는데 모델 은 주로 4 가지 가 있다.
  • r:읽 기 전용 모드 입 니 다.이 때 write 관련 방법 을 호출 하면 IOException 을 던 집 니 다.
  • rw:읽 기와 쓰기 모드.파일 이 존재 하지 않 으 면 읽 기와 쓰 기 를 지원 합 니 다.
  • rws:읽 기와 쓰기 모드.쓰기 작업 을 할 때마다 내용 이나 메타 데 이 터 를 디스크 에 동기 화 합 니 다.
  • rwd:읽 기와 쓰기 모드.쓰기 작업 을 할 때마다 변 경 된 내용 을 디스크 에 동기 화하 여 새로 고 칩 니 다.
  • 총결산
    본 고 는 주로 자바 중의 IO 흐름 을 정리 하고 이 를 바이트 흐름 과 문자 흐름,그리고 입력 흐름 과 출력 흐름 으로 나 누 어 각각 통 계 를 통 해 자바 중의 IO 흐름 전체 에 대한 개념 을 구축 했다.마지막 으로 사례 를 통 해 서로 다른 유형의 흐름 을 통 해 강력 하고 유연 한 입력 과 출력 을 어떻게 조합 하 는 지 보 여 주 었 다.마지막 으로입력 과 출력 을 동시에 지원 하 는 RandomAccessFile 을 소개 했다.
    이 글 은 여기까지 입 니 다.당신 에 게 도움 을 줄 수 있 기 를 바 랍 니 다.또한 당신 이 우리 의 더 많은 내용 에 관심 을 가 져 주 실 수 있 기 를 바 랍 니 다!

    좋은 웹페이지 즐겨찾기