2016-08-22 3 views
2

base64를 사용하여 인코딩 된 내용을 얻는 데 필요한 많은 PDF 파일이 있습니다. 파일을 스트림으로 가져 와서 많은 파일 작업자에게 배포하여 이러한 파일을 인코딩하고 각 파일에 base64 문자열을 반환하는 Akka 앱이 있습니다. 나는 인코딩을위한 기본적인 솔루션을 가지고 :스트림 용 Java 버퍼가있는 base64 인코더

org.apache.commons.codec.binary.Base64InputStream; 
    ... 
    Base64InputStream b64IStream = null; 
    InputStreamReader reader = null; 
    BufferedReader br = null; 
    StringBuilder sb = new StringBuilder(); 
    try { 
     b64IStream = new Base64InputStream(input, true); 
     reader = new InputStreamReader(b64IStream); 
     br = new BufferedReader(reader); 
     String line; 
     while ((line = br.readLine()) != null) { 
      sb.append(line); 
     } 
    } finally { 
     if (b64IStream != null) { 
      b64IStream.close(); 
     } 
     if (reader != null) { 
      reader.close(); 
     } 
     if (br != null) { 
      br.close(); 
     } 
    } 

그것은 작동을하지만 난 버퍼를 사용하여 파일을 인코딩 할 수있는 가장 좋은 방법은 무엇 무엇인지 알고 싶습니다 빠른 대안이에있는 경우.

나는 다음과 같은 몇 가지 다른 접근 테스트 :
  • sun.misc.BASE64Encoder
  • Base64.encodeBase64

    • Base64.getEncoder을
    • javax.xml.bind.DatatypeConverter.printBase64
    • com.google.guava.BaseEncoding.base64

    더 빠르지 만 전체 파일이 필요합니다. 맞습니까? 또한 1 PDF 파일을 인코딩하는 동안 다른 스레드를 차단하고 싶지 않습니다.

    모든 입력이 정말 도움이됩니다. 고맙습니다!

  • +0

    "버퍼 사용"이란 무엇입니까? 무엇이 입력이 될 것이며 출력은 무엇을 기대합니까? 스트림? 채널? 문자열? – RealSkeptic

    +0

    입력이 InputStream이면 출력은 base64 문자열 내용입니다. 버퍼는 BufferedReader가됩니다. –

    답변

    3

    재미있는 사실 Base64 : 3 바이트가 걸리며 4 글자로 변환됩니다. 즉, 3으로 나눌 수있는 청크로 이진 데이터를 읽는 경우 청크를 Base64 인코더로 보내면 전체 파일을 입력 한 것과 같은 방식으로 인코딩됩니다. 완벽하게 합법적이다 - - 당신이 원하는 경우

    지금, 당신의 출력 스트림은 Base64로 데이터를 하나 개의 긴 라인이 될 다음 당신이해야 할 모든의 라인을 따라 뭔가 :이 있음을 의미

    private static final int BUFFER_SIZE = 3 * 1024; 
    
    try (BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE);) { 
        Base64.Encoder encoder = Base64.getEncoder(); 
        StringBuilder result = new StringBuilder(); 
        byte[] chunk = new byte[BUFFER_SIZE]; 
        int len = 0; 
        while ((len = in.read(chunk)) == BUFFER_SIZE) { 
         result.append(encoder.encodeToString(chunk)); 
        } 
        if (len > 0) { 
         chunk = Arrays.copyOf(chunk,len); 
         result.append(encoder.encodeToString(chunk)); 
        } 
    } 
    

    마지막 청크 만 3으로 나눌 수없는 길이를 가질 수 있으므로 패딩 문자가 포함됩니다.

    위 예제는 Java 8 Base64를 사용하지만 실제로 임의의 길이의 바이트 배열을 사용하고 해당 바이트 배열의 base64 문자열을 반환하는 인코더를 사용할 수 있습니다.

    즉, 원하는대로 버퍼 크기로 재생할 수 있습니다.

    출력을 MIME과 호환되도록하려면 출력을 줄로 구분해야합니다. 이 경우, 위의 예제에서 청크 크기를 4/3으로 곱하면 라운드 수를 줄 수 있습니다. 예를 들어, 한 줄에 64자를 넣으려는 경우 각 줄은 48 바이트 인 64/4 * 3을 인코딩합니다. 48 바이트를 인코딩하면 한 줄을 얻을 수 있습니다. 480 바이트를 인코딩하면 10 개의 전체 줄을 얻을 수 있습니다.

    따라서 위의 BUFFER_SIZE를 4800과 같이 수정하십시오. Base64.getEncoder() 대신 Base64.getMimeEncoder(64,new byte[] { 13, 10})을 사용하십시오. 그리고 나서, 인코딩 할 때 마지막 덩어리를 제외한 각 덩어리에서 전체 크기의 100 줄을 얻을 수 있습니다. while 루프에 result.append("\r\n")을 추가해야 할 수도 있습니다.

    +0

    많은 감사합니다 !! 필자는 java 6을 사용하기 때문에 인코더를 전환해야했습니다.이 변경 이전에 인코딩하는 데 900ms가 걸렸으므로 이제는 동일한 파일에 대해 평균 103ms가 소요됩니다. –