2014-04-17 4 views
1

배열에 매우 큰 파일을 읽으려고합니다. 나는 그것이 순간에 배열에 그것을 읽지 않고 있다는 것이 분명하다. 그러나 그것은 내가 가지고있는 문제가 아니다. 약 6 억 자릿수이며 오류가 발생하는 것으로 보입니다. 스레드 "주요"java.lang.OutOfMemoryError와의 예외 : Java 힙 공간배열에 큰 파일 읽기 java.lang.OutOfMemoryError : Java 힙 공간

BufferedReader brWorld = null; 
String World; 
brWorld = new BufferedReader(new FileReader("Saves/" + Name)); 
World = brWorld.readLine(); 
String Numbers = World; 
String[] LoadWorld = Numbers.split(""); 
for(int x = 0; x < MaterialArray.length * MaterialArray.length; x++){ 
    System.out.println(String.valueOf(LoadWorld[x])); 
} 

임 내 게임에 대한 배열로 것로드. 이 큰 텍스트 파일을로드 할 수있는 방법이 있습니까? 감사 리암

메모리가 부족 왜 여기
+1

메모리에 전체 파일이 정말로 필요한 경우에만 증가 RAM이었습니다. 그렇지 않으면 청크로 청크 읽기 – kosa

+0

대문자의 첫 문자로 변수의 이름을 지정하지 말고, 소문자로 변수를 시작하는 강력한 Java 규칙이 있으며 Java 개발자가 코드를 읽을 수 없도록하십시오. – amit

+0

String [] LoadWorld = Numbers.split ""); 정말로 빈 문자열이 있었습니까? 너는 무엇을 성취하려고 하는가? – amit

답변

0

은 다음과 같습니다

brWorld = new BufferedReader(new FileReader("Saves/" + Name)); 
World = brWorld.readLine(); 
String Numbers = World; 
String[] LoadWorld = Numbers.split(""); 

당신은 먼저 모든 숫자로 읽는 :

600,000,000 chars = 600,000,000 bytes = 600 MB 

을 그래서 이미 적어도 6백메가바이트에 있습니다. 그런 다음 완전히 새로운 문자열 배열을 만듭니다. 즉, 배열의 각 문자에 대해 String 포인터를 작성 중입니다. 아키텍처에 따라이 크기는 4 바이트 이상일 수 있습니다.

600 MB + 600,000,000 * 4 = 600 MB + 2,400 MB = 3,000 MB = 3 GB 

*이 수치는 추정치이며 실제 용량은 매우 클 것입니다.

여기서 알 수 있듯이, 이는 실현 가능한 해결책이 아닙니다. 이것은 훨씬 더 나은 해결책입니다 :

BufferedReader brWorld = null; 
String world; 
brWorld = new BufferedReader(new FileReader("Saves/" + Name)); 
world = brWorld.readLine(); 
for(int x = 0; x < MaterialArray.length * MaterialArray.length; x++){ 
    System.out.println(String.valueOf(world.charAt(x))); 
} 
+1

이것은 600MB가 넘는 방법입니다. 그는 600,000,000 개의'String' 객체를 만들고 있는데, 각각 1B보다 큰 가중치가 있습니다. – amit

+0

@amit 나는 코드를 잘못 읽었습니다. – John

3

우선, 많은 메모리가 필요합니다. 몇 GB의 RAM, GC 룸은 포함되지 않습니다.

600M 자릿수의 "한 줄"을 읽는다면 결국에는 실제로 읽은 후에도 (600 자릿수의 문자열에는 1.2GB가 필요함) 메모리, 단순히 문자.

Java는 문자열을 문자 배열로 저장하고 문자는 내부적으로 2 바이트 인 UTF-16으로 저장됩니다.

그 자체만으로도 지붕을 통해 메모리 요구 사항을 보냅니다.

분할 할 때 각 숫자가 개별 문자열로 바뀝니다. 이제 600M 문자열과 그 이상의 모든 머리 부분이 생깁니다. 최소한 기본 문자열에 대한 포인터, 배열에 대한 오프셋 및 문자열 길이를 저장하므로 문자열 당 최소 16 바이트를 찾고 있습니다. 고맙게도, split은 실제로 기본 배열을 재사용 할 것이지만, 여기서는별로 도움이되지 않습니다.

16 바이트 * 600M은 9.6GB입니다.

이제는 "우스꽝스러운"메모리 요구 사항을 맞이하게되었습니다.

실제로 원하는 것을 말하지 않습니다. 당신은 "파일을로드"하고 싶지만 당신은 무엇을 말하지 않습니다. 따라서 어떻게해야하는지에 대한 권장 사항을 제시하는 것은 어렵습니다. 파일을 인쇄하기 만하면 각 문자를 하나씩 읽고 인쇄 할 수 있습니다.하지만 분명히 목표는 아닙니다.

그래, 네가이 문제에 "기억을 던질"수 있지만, 그러고 싶지는 않아. 문제를 연구하고 거기에서 성취하려고 노력하는 것을보다 잘 표현할 필요가 있습니다.

관련 문제