Java에서 문자 흐름과 바이트 흐름의 차이점 이해

본고는 여러분을 위해 자바에서의 문자 흐름과 바이트 흐름의 차이를 분석하여 참고하고자 합니다. 구체적인 내용은 다음과 같습니다.
1. 흐름이란 무엇인가
자바의 흐름은 바이트 서열에 대한 추상적이다. 우리는 수도관이 있다고 상상할 수 있다. 그러나 현재 수도관에 흐르는 것은 물이 아니라 바이트 서열이다.물 흐름과 마찬가지로 Java의 흐름도'흐르는 방향'을 가지고 있으며, 보통 바이트 서열을 읽을 수 있는 대상을 입력 흐름이라고 부른다.바이트 시퀀스에 쓸 수 있는 대상을 출력 흐름이라고 합니다.
2.바이트 흐름
Java의 바이트 흐름 처리의 가장 기본적인 단위는 단일 바이트이며, 보통 2진 데이터를 처리하는 데 쓰인다.Java에서 가장 기본적인 두 바이트 흐름은 InputStream과 OutputStream이다. 이것은 각각 그룹의 기본적인 입력 바이트 흐름과 출력 바이트 흐름을 대표한다.InputStream 클래스와 OutputStream 클래스는 모두 추상적인 클래스입니다. 우리는 실제 사용에서 자바 라이브러리에서 제공하는 일련의 하위 클래스를 사용합니다.다음은 InputStream 클래스를 예로 들어 자바의 바이트 흐름을 소개합니다.
InputStream 클래스에서는 바이트 흐름에서 바이트를 읽는 기본적인 방법인 read를 정의합니다. 이 방법의 정의는 다음과 같습니다.
public abstract int read() throws IOException;
이것은 추상적인 방법이다. 즉, InputStream에서 파생된 입력 바이트 흐름은 모두 이 방법을 실현해야 한다는 것이다. 이 방법의 기능은 바이트 흐름에서 바이트를 읽고 끝에 이르면 -1, 그렇지 않으면 읽은 바이트를 되돌려주는 것이다.이 방법에 관해서 우리가 주의해야 할 것은, 읽은 바이트나 -1로 돌아가는 것을 계속 막는다는 것이다.또한 바이트 흐름은 기본적으로 캐시를 지원하지 않습니다. 이것은 한 번 호출할 때마다read 방법으로 운영체제에 바이트를 읽으라고 요청하는 것을 의미합니다. 이것은 디스크 IO를 한 번 수반하기 때문에 효율이 비교적 낮습니다.어떤 친구들은 InputStream 클래스에서read의 바이트 그룹을 매개 변수로 하는 재부팅 방법이 디스크 IO를 빈번하게 하지 않고 한 번에 여러 바이트를 읽을 수 있다고 생각할 수도 있다.그렇다면 과연 그럴까?이 방법의 원본을 살펴보겠습니다.

public int read(byte b[]) throws IOException {
  return read(b, 0, b.length);
}
그것은 다른 버전의read 재부팅 방법을 호출했다. 그러면 우리는 이어서 아래로 쫓아간다.

  public int read(byte b[], int off, int len) throws IOException {
    if (b == null) {
      throw new NullPointerException();
    } else if (off < 0 || len < 0 || len > b.length - off) {
      throw new IndexOutOfBoundsException();
    } else if (len == 0) {
      return 0;
    }

    int c = read();
    if (c == -1) {
      return -1;
    }
    b[off] = (byte)c;

    int i = 1;
    try {
      for (; i < len ; i++) {
        c = read();
        if (c == -1) {
          break;
        }
        b[off + i] = (byte)c;
      }
    } catch (IOException ee) {
    }
    return i;
  }

이상의 코드에서 알 수 있듯이 실제로read(byte[]) 방법은 내부적으로read() 방법을 순환적으로 호출하여'한 번'에 바이트 그룹을 읽는 것을 실현하기 때문에 본질적으로 이 방법도 메모리 버퍼를 사용하지 않았다.읽기 효율을 높이기 위해 메모리 버퍼를 사용하려면 Buffered InputStream을 사용해야 합니다.
 3. 문자 흐름
Java의 문자 흐름 처리의 가장 기본적인 단원은 유니코드 코드 코드 (크기 2 바이트) 이며, 보통 텍스트 데이터를 처리하는 데 쓰인다.이른바 유니코드 코드, 즉 유니코드 코드 단원으로 범위는 0x0000~0xFFF이다.위 범위의 모든 숫자는 한 문자와 대응하며, 자바의 String 형식은 기본적으로 문자를 유니코드 규칙으로 인코딩한 후 메모리에 저장합니다.그러나 메모리에 저장된 것과 달리 디스크에 저장된 데이터는 통상적으로 각양각색의 인코딩 방식을 가지고 있다.서로 다른 인코딩 방식을 사용하면 같은 문자는 서로 다른 이진 표시를 할 수 있다.실제 문자 흐름은 다음과 같이 작동합니다.
출력 문자 흐름: 파일에 쓸 문자 시퀀스 (실제로는 유니코드 코드 코드 시퀀스) 를 지정한 인코딩 방식의 바이트 시퀀스로 바꾸고 파일에 쓰기;
입력 문자 흐름: 읽을 바이트 시퀀스를 지정한 인코딩 방식에 따라 해당 문자 시퀀스로 디코딩합니다. (실제로는 유니코드 코드 코드 원본 시퀀스에서) 메모리에 존재할 수 있습니다.
우리는 demo를 통해 이 과정에 대한 이해를 깊이 있게 한다. 예시 코드는 다음과 같다.

import java.io.FileWriter;
import java.io.IOException;


public class FileWriterDemo {
  public static void main(String[] args) {
    FileWriter fileWriter = null;
    try {
      try {
        fileWriter = new FileWriter("demo.txt");
        fileWriter.write("demo");
      } finally {
        fileWriter.close();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

위의 코드에서 우리는 FileWriter를 사용하여 demo로 향합니다.txt에 "demo"라는 네 글자가 기록되어 있습니다. 16진 편집기인 WinHex로 demo를 보십시오.txt 내용:
위의 그림에서 알 수 있듯이 우리가 쓴'demo'는'64 65 6D 6F'로 인코딩되었지만, 우리는 위의 코드에서 인코딩 방식을 명시적으로 지정하지 않았습니다. 실제로 우리가 지정하지 않았을 때 사용하는 것은 운영체제의 기본 문자 인코딩 방식으로 우리가 쓰고자 하는 문자를 인코딩하는 것입니다.
문자 흐름은 출력하기 전에 사실상 유니코드 코드 코드 코드 서열을 인코딩 방식의 바이트 서열로 변환해야 하기 때문에 메모리 버퍼를 사용하여 변환된 바이트 서열을 저장하고 변환이 끝난 후에 디스크 파일에 함께 쓰기를 기다립니다.   
4. 문자 흐름과 바이트 흐름의 차이
위의 설명을 통해 바이트 흐름과 문자 흐름 사이의 주요 차이점은 다음과 같은 몇 가지 측면에 나타난다는 것을 알 수 있다.
바이트 흐름 조작의 기본 단원은 바이트이다.문자 흐름 작업의 기본 단원은 유니코드 코드입니다.
바이트 흐름은 기본적으로 버퍼를 사용하지 않습니다.문자 흐름은 버퍼를 사용합니다.
바이트 흐름은 보통 2진 데이터를 처리하는 데 사용되지만, 실제로는 임의의 형식의 데이터를 처리할 수 있지만, 유니코드 코드를 직접 쓰거나 읽는 것은 지원하지 않는다.문자 흐름은 일반적으로 텍스트 데이터를 처리하며, 유니코드 코드를 쓰고 읽는 것을 지원합니다.   
이상은 제가 자바에서 문자 흐름과 바이트 흐름에 대한 인식입니다. 만약에 서술이 명확하지 않거나 정확하지 않은 부분이 있으면 여러분이 지적해 주십시오. 감사합니다.

좋은 웹페이지 즐겨찾기