문자열로 이동하기 위해 OutputStream
에서 pre-Base64로 인코딩 된 데이터가 필요하기 때문에 Java에서 StringOutputStream
클래스를 작성하고 있습니다. 이것을 W3C XML Document
에 넣으므로 String으로 필요합니다.문자열로 큰 스트림 복사 -
모든 것이 좋겠지 만 (상대적으로) 큰 개체를 다루고 있습니다. 결과 객체는 (문자열 표현 이전에) 약 25MB로 밝혀졌습니다. 애플릿으로 실행 중이므로 66 MB의 힙 공간이 매우 빨리 소모됩니다.
는 지금까지 몇 가지 방법을 시도 :
- 이 String 객체에 수신 된 바이트를 추가 (
strObj.concat((byte) b)
및strObj += new String((byte) b)
사용) 및 - 를 버퍼링없이
StringBuffer
- 에 수신 된 바이트 추가 바이트를 바이트 배열에 추가 한 다음 문자열을 원할 때 해당 바이트 배열을 문자열로 변환
숫자 1은 abo까지 작동합니다. ut 11 MB, 이전 String과 새 String이 연결될 때 너무 많은 공간을 사용하는 경우.
2 번은 총 실패로 약 7MB에 불과합니다.
3 번이 (아마도?) 가장 좋았습니다. 전체 스트림을 저장하지만, 문자열을 얻으려고하면 당연히 실패합니다.
어떻게하면됩니까? 가능한가?
나는 결과 문자열을 저장할 수있는 공간을 가지고 있다고 생각하지만 문제는 복사입니다 (기존 사본의 원본과 대상이 필요하므로). 나는 문자열이 변경되지 않는다는 것을 알고 있지만, 끝에 문자를 추가하는 방법이 있습니까?
은 여기 내 세 가지 예를의 : 코드에 대한
package com.myorg.SigningServer.Util.Security;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import com.technicolor.SigningServer.Applet.SigningApplet;
public class StringOutputStream extends OutputStream {
byte[] array = new byte[1024*1024*22];
StringBuffer sb = new StringBuffer();
String output = "";
int prevByte = -1;
long numBytes = 0;
int bufferPos = 0;
int bufferSize = 512*1024;
byte[] buffer = new byte[bufferSize];
public void write2(int b) throws IOException {
sb.append((byte) b);
}
public void write3(int b) throws IOException {
array[(int) numBytes] = (byte) b;
numBytes++;
}
public void write1(int b) throws IOException {
numBytes++;
bufferPos++;
buffer[bufferPos] = (byte) b;
if(bufferPos == bufferSize-1)
{
bufferPos = 0;
System.gc();
System.out.println("Generating string "+numBytes+"; String length "+output.length());
output = output.concat(new String(buffer));
System.gc();
}
}
public void flush1() {
output = output.concat(new String(Arrays.copyOf(buffer, bufferPos)));
bufferPos = 0;
System.gc();
}
public String toString2()
{
return sb.toString();
}
public String toString3()
{
return new String(array);
}
public String toString1()
{
return output;
}
}
몇 가지 참고 사항 : 분명히, 당신은() 및 toString()를 작성하는 데 사용할 방법을 변경합니다. 또한, 바이트 배열은 (현재) 정적으로 할당되어 있지만 그 경로로 이동하면 (다른 메소드에서는 사용되지 않음) 변경됩니다.
편집 1 : 내 전반적인 문제에 더 많은 정보 :
이 서버에 데이터 표시를하고 업로드를 취하는 큰 응용 프로그램의 일부입니다. 나는 파일을 읽고, SHA-1 해쉬를 가져 와서 암호화하고, XML 문서 (시간과 같은 몇 가지 다른 것들을 포함하여)를 만들어야한다. 그런 다음 해당 XML 문서는 XML DSig (별칭 : javax.xml.crypto.dsig.XMLSignatureFactory
)를 통해 서명하고 서버에 다시 업로드해야합니다.
서명 할 파일의 크기는 1KB에서 50MB 사이입니다.
- XML DSIG의 현재 자바 구현 구문 분석 및 XML하지 않는 스트림, 단지 W3C 노드 :
은 몇 가지 문제가 있습니다.(나는 다른 구현을 찾을 수 없다.)
- 내 상사는 최소한의 클라이언트 측 설치가 필요하지 않으므로 애플릿이 선택된 이유는 서명 된 애플릿이므로 클라이언트의 모든 항목에 액세스 할 수 있기 때문입니다. .
'java.io.ByteArrayOutputStream' 또는'java.io.StringWriter'가 효과가없는 이유를 설명 할 수 있습니까? – Pointy
ByteArrayOutputStream은 메서드 3과 똑같습니다. 모든 것을 복사 한 다음 toString을 호출 할 때 메모리가 부족합니다. StringWriter는 메소드 2와 거의 동일한 10MB에서 메모리가 부족합니다. – HalfBrian
해결하려는 문제에 대해 질문에 더 추가 할 수 있습니까? 이것은 모든 사람이 상자 밖에서 생각하고 다른 각도에서 문제를 해결하는 데 도움이 될 수 있습니다. 예 : 22MB의 데이터에 초점을 맞 춥니 다. 서명 된 데이터가 고정되어 있습니까? 크기에 대한 상한선입니까? – mdma