Java는 ByteArrayOutputStream 및 ByteArrayInputStream을 사용하여 구성 파일을 반복적으로 읽지 않도록 합니다.

Byte Array Output Stream 클래스는 그 실례를 만들 때 프로그램 내부에byte 형식의 버퍼를 만들고 Byte Array Output Stream과 Byte Array Input Stream의 실례를 이용하여 그룹에 byte 형식의 데이터를 쓰거나 읽는 것입니다.네트워크 전송에서 우리는 왕왕 많은 변수를 전송해야 한다. 우리는 Byte Array Output Stream을 이용하여 모든 변수를 한데 모은 다음에 데이터를 한꺼번에 보낼 수 있다.구체적인 사용법은 다음과 같다.
ByteArray OutputStream: 메모리 버퍼의 데이터를 포착하여 바이트 그룹으로 변환할 수 있습니다.
ByteArrayInputStream: 바이트 그룹을 입력 흐름으로 변환
ByteArray InputStream 클래스에는 다음과 같은 두 가지 기본 구조 함수가 있습니다.
Byte Array Input Stream(byte[]b): 한 바이트 그룹의 모든 데이터를 데이터 원본으로 사용합니다. 프로그램은 입력 흐름 방식처럼 바이트를 읽을 수 있습니다. 가상 파일로 볼 수 있고 파일로 그 안의 데이터를 읽을 수 있습니다.
Byte Array Input Stream(byte[]b, int offset, int length): 수조 중의 offset부터 시작해서 이 바이트를 데이터 원본으로 계속 꺼냅니다.
ByteArrayOutputStream 클래스에도 두 가지 기본 구조 함수가 있습니다.
ByteArrayOutputStream(): 32바이트 버퍼 만들기
ByteArrayOutputStream(int): 매개 변수에 따라 크기를 지정하여 버퍼 만들기
최근에 github의 개원 프로젝트인 Mycat에 참여했습니다. 이것은 mysql의 라이브러리 테이블의 중간부품입니다.그 중에서 프로필을 읽는 코드를 발견하면 여러 번 반복해서 열고, 읽고, 닫는 문제가 빈번하게 존재한다. 코드는 매우 초보적으로 쓰여 있다. 일부 프레임워크 원본을 조금 본 사람은 이런 오류를 범하지 않을 것이다.그래서 그것에 대해 약간의 최적화를 진행하였다.
이전 코드를 최적화하려면 다음과 같이 하십시오.

private static Element loadRoot() {
  InputStream dtd = null;
  InputStream xml = null;
  Element root = null;
  try {
    dtd = ConfigFactory.class.getResourceAsStream("/mycat.dtd");
    xml = ConfigFactory.class.getResourceAsStream("/mycat.xml");
    root = ConfigUtil.getDocument(dtd, xml).getDocumentElement();
  } catch (ConfigException e) {
    throw e;
  } catch (Exception e) {
    throw new ConfigException(e);
  } finally {
    if (dtd != null) {
      try {
        dtd.close();
      } catch (IOException e) { }
    }
    if (xml != null) {
      try {
        xml.close();
      } catch (IOException e) { }
    }
  }
  return root;
} 
그리고 다른 방법으로 loadRoot()을 자주 호출합니다.

@Override
public UserConfig getUserConfig(String user) {
  Element root = loadRoot();
  loadUsers(root);
  return this.users.get(user);
}
@Override
public Map<String, UserConfig> getUserConfigs() {
  Element root = loadRoot();
  loadUsers(root);
  return users;
}
@Override
public SystemConfig getSystemConfig() {
  Element root = loadRoot();
  loadSystem(root);
  return system;
}
// ... ... 
ConfigUtil.getDocument(dtd, xml) 방법은 다음과 같습니다.

public static Document getDocument(final InputStream dtd, InputStream xml) throws ParserConfigurationException,
      SAXException, IOException {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//factory.setValidating(false);
    factory.setNamespaceAware(false);
    DocumentBuilder builder = factory.newDocumentBuilder();
    builder.setEntityResolver(new EntityResolver() {
      @Override
      public InputSource resolveEntity(String publicId, String systemId) {
        return new InputSource(dtd);
      }
    });
    builder.setErrorHandler(new ErrorHandler() {
      @Override
      public void warning(SAXParseException e) {
      }
      @Override
      public void error(SAXParseException e) throws SAXException {
        throw e;
      }
      @Override
      public void fatalError(SAXParseException e) throws SAXException {
        throw e;
      }
    });
    return builder.parse(xml);
  } 
분명히 이것은 좋은 처리 방식이 아니다.구성 파일이 여러 번 반복됩니다.
1. 1차 최적화:
왜 한 번 읽지 않고 캐시합니까?그리고 다른 방법은loadRoot () 를 호출할 때 캐시에 있는 것을 직접 사용하면 됩니다.그러나 한 가지 문제에 부딪히면 InputStream은 캐시된 다음에 다시 읽을 수 없습니다. 왜냐하면 InputStream이 일단 읽히면pos 바늘 등이 바뀌어 중복 읽을 수 없기 때문입니다.따라서 프로필의 내용을 읽기 처리하고byte[]에 넣고 캐시한 다음ByteArrayOutputStream에 맞추면byte[] 캐시의 내용을 반복해서 읽을 수 있습니다.그리고 ByteArray OutputStream을 이용하여 InputStream을 구성하면 프로필을 한 번 읽고 InputStream을 다시 구성하여 다음과 같은 코드를 반복합니다.

//   loadRoot   /mycat.dtd   /mycat.xml, ,
//  ,  LocalLoader  , 。
private static byte[] xmlBuffer = null;
private static byte[] dtdBuffer = null;
private static ByteArrayOutputStream xmlBaos = null;
private static ByteArrayOutputStream dtdBaos = null;
static {
  InputStream input = ConfigFactory.class.getResourceAsStream("/mycat.dtd");
  if(input != null){
    dtdBuffer = new byte[1024 * 512];
    dtdBaos = new ByteArrayOutputStream();
    bufferFileStream(input, dtdBuffer, dtdBaos);
  }
  input = ConfigFactory.class.getResourceAsStream("/mycat.xml");
  if(input != null){
    xmlBuffer = new byte[1024 * 512];
    xmlBaos = new ByteArrayOutputStream();
    bufferFileStream(input, xmlBuffer, xmlBaos);
  }
} 
bufferFileStream 방법:

private static void bufferFileStream(InputStream input, byte[] buffer, ByteArrayOutputStream baos){
  int len = -1;
  try {
    while ((len = input.read(buffer)) > -1 ) {
      baos.write(buffer, 0, len);
    }
    baos.flush();
  } catch (IOException e) {
    e.printStackTrace();
    logger.error(" bufferFileStream error: " + e.getMessage());
  }
} 
loadRoat 최적화 이후:

private static Element loadRoot() {
  Element root = null;
  InputStream mycatXml = null;
  InputStream mycatDtd = null;
  if(xmlBaos != null)
    mycatXml = new ByteArrayInputStream(xmlBaos.toByteArray());
  if(dtdBaos != null)
    mycatDtd = new ByteArrayInputStream(dtdBaos.toByteArray());
  try {
  root = ConfigUtil.getDocument(mycatDtd, mycatXml).getDocumentElement();
  } catch (ParserConfigurationException | SAXException | IOException e1) {
    e1.printStackTrace();
    logger.error("loadRoot error: " + e1.getMessage());
  }finally{
    if(mycatXml != null){
      try { mycatXml.close(); } catch (IOException e) {}
    }
    if(mycatDtd != null){
      try { mycatDtd.close(); } catch (IOException e) {}
    }
  }
  return root;
} 
이렇게 최적화된 후에 loadRoot () 방법을 자주 호출해도 프로필을 반복적으로 읽지 않고 byte [] 내용을 사용하여 InputStream을 재구성할 뿐입니다.
사실 그 원리는byte[]를 중간 용기로 이용하여byte를 캐시하는 것이다. Byte Array Output Stream은 Input Stream이 읽는 byte를 byte[] 용기와 같이 저장한 다음에 Byte Array Input Stream을 이용하여byte[] 용기에서 내용을 읽고 Input Stream을 구축한다. 이 캐시 용기가 존재하기만 하면 여러 번 반복해서 Input Stream을 구성할 수 있다.그래서 프로필을 한 번 읽고 InputStream을 반복적으로 구성하여 매번 InputStream을 구성할 때마다 프로필을 한 번 읽는 문제를 피했다.
2. 2차 최적화:
아마도 당신은 더 좋은 방법을 생각할 것이다. 예를 들면:
왜 우리는 private static Element root =null를 사용하지 않습니까?클래스 속성으로서 캐시를 하면 구성 파일을 다시 열고 닫을 필요가 없습니다. 다음과 같이 수정합니다.

public class LocalLoader implements ConfigLoader {
  private static final Logger logger = LoggerFactory.getLogger("LocalLoader");
  // ... ..  
  private static Element root = null;
  //   loadRoot  :
  private static Element loadRoot() {
    InputStream dtd = null;
    InputStream xml = null;
//    Element root = null;
    if(root == null){
      try {
        dtd = ConfigFactory.class.getResourceAsStream("/mycat.dtd");
        xml = ConfigFactory.class.getResourceAsStream("/mycat.xml");
        root = ConfigUtil.getDocument(dtd, xml).getDocumentElement();
      } catch (ConfigException e) {
        throw e;
      } catch (Exception e) {
        throw new ConfigException(e);
      } finally {
        if (dtd != null) {
          try {
            dtd.close();
          } catch (IOException e) { }
        }
        if (xml != null) {
          try {
            xml.close();
          } catch (IOException e) { }
        }
      }
    }
    return root;
  } 
이렇게 하면 필요 없이 프로필을 열고 닫는 것을 반복하지 않을 것이다.루트 속성이 회수되지 않으면 루트가 도입한 Document 대상도 캐시에 있습니다.이것은 분명히 첫 번째 최적화보다 훨씬 낫다. 왜냐하면 첫 번째 최적화는byte[]에서 InputStream을 재구성하고 build에서 Document 대상을 재구성해야 하기 때문이다.
3. 3차 최적화
위에는 private static Element root =null;반복 읽기를 피하기 위해 속성으로 캐시합니다.그러면 우리는 왜 Document 객체를 하나의 속성으로 캐시하지 않습니까?그리고 더 좋은 의미를 가지고 코드가 더 잘 이해된다.코드는 다음과 같습니다.

public class LocalLoader implements ConfigLoader {
  private static final Logger logger = LoggerFactory.getLogger("LocalLoader");
  // ... ...
  //   loadRoot   /mycat.dtd   /mycat.xml,  Document  ,
  private static Document document = null;
  private static Element loadRoot() {
    InputStream dtd = null;
    InputStream xml = null;    
    if(document == null){
      try {
        dtd = ConfigFactory.class.getResourceAsStream("/mycat.dtd");
        xml = ConfigFactory.class.getResourceAsStream("/mycat.xml");
        document = ConfigUtil.getDocument(dtd, xml);
        return document.getDocumentElement();
      } catch (Exception e) {
        logger.error(" loadRoot error: " + e.getMessage());
        throw new ConfigException(e);
      } finally {
        if (dtd != null) {
          try { dtd.close(); } catch (IOException e) { }
        }
        if (xml != null) {
          try { xml.close(); } catch (IOException e) { }
        }
      }
    }    
    return document.getDocumentElement();
  } 
이렇게 해야만 비교적 합격된 실현이다.Anyway, 첫 번째 최적화는 ByteArray Output Stream과 ByteArray Input Stream과byte[]를 결합하여 사용하는 방법을 배웠다.
분할선
참고문:http://blog.csdn.net/it_magician/article/details/9240727
때때로 우리는 같은 InputStream 객체에 대해 여러 번 사용해야 합니다.예를 들어 클라이언트가 서버에서 데이터를 얻고 HttpURLConnection의 get Input Stream () 방법을 이용하여 Stream 대상을 얻는다. 이때 데이터를 프론트 데스크톱에 표시해야 할 뿐만 아니라 파일을 로컬로 캐시하려고 한다.
그러나 InputStream 객체를 처음 읽은 후 두 번째 다시 읽을 때 Stream의 끝에 도달했거나 Stream이 닫혔을 수 있습니다.
InputStream 객체 자체는 Cloneable 인터페이스를 구현하지 못했기 때문에 복제할 수 없습니다.이때 InputStream을 Byte Array Output Stream으로 바꾸고 다음에 Input Stream 대상을 사용할 때 Byte Array Output Stream에서 바꾸면 됩니다.코드는 다음과 같습니다.

InputStream input = httpconn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = input.read(buffer)) > -1 ) {
  baos.write(buffer, 0, len);
}
baos.flush();       
InputStream stream1 = new ByteArrayInputStream(baos.toByteArray());
//TODO: 
InputStream stream2 = new ByteArrayInputStream(baos.toByteArray());
//TODO:  
java에서 ByteArray InputStream 및 ByteArray OutputStream 클래스 사용
ByteArray InputStream 및 ByteArray OutputStream은 바이트 그룹 내용에 대한 읽기와 쓰기를 IO 흐름으로 수행하여 메모리 가상 파일이나 메모리 맵 파일과 같은 기능을 지원합니다.
인스턴스:

import java.io.*; 
public class ByteArrayStreamTest { 
  public static void main(String [] args) { 
    String str = "abcdef"; 
    ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes()); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    transform(in, out); 
    byte[] result = out.toByteArray(); 
    System.out.println(out); 
    System.out.println(new String(result)); 
    transform(System.in, System.out); //  ,  
  } 
  public static void transform(InputStream in, OutputStream out) { 
    int ch = 0; 
    try { 
      while ((ch = in.read()) != -1) { 
        int upperChar = Character.toUpperCase((char)ch); 
        out.write(upperChar); 
      } // close while 
    } catch (Except

좋은 웹페이지 즐겨찾기