MappedByteBuffer 소결
1.가상 메모 리 를 사용 하기 때문에 분배(map)의 메모리 크기 는 JVM 의-Xmx 매개 변수 에 제한 을 받 지 않 지만 크기 제한 이 있 습 니 다.우선 그 는 이론 적 으로 Integer.MAX 를 초과 할 수 없습니다.VALUE 는 32 비트 운영 체제 의 2G 이다.그 다음으로 실제 값 은 운영 체 제 를 사용 하지 않 아 도 다르다.win 7 32 비트 운영 체제 에서 그 는 1.5G 를 초과 할 수 없고 구체 적 으로 얼마 인지 측정 하지 못 했 으 며 무슨 원인 인지 모른다.
2.큰 파일 을 읽 어야 합 니 다.파일 이 1.5G 제한 을 초과 하면 다시 맵 을 하고 POSITION 매개 변 수 를 통 해 파일 뒤의 내용 을 가 져 올 수 있 습 니 다.
3.읽 기와 반복 읽 기 는 보통 IO 보다 빠 르 지 않 지만 단순 한 기록 은 일반 I/O 의 일반 속도 보다 못 합 니 다.이 결론 은 다음 과 같은 테스트 코드 에서 나온다.
package com.chat;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
public class FileChannelStudy
{
static String filename1 = "d:\\work\\code\\filechannelstudy.txt";
static String filename2 = "d:\\work\\code\\file.txt";
static String content = "abcdefghijk\r
";
static long size = 1024000000l;
static long num = size / 10*6;
static long startT = 0;
static long endT = 0;
public static void setStartT()
{ mbb = null;
if(cnt %50 == 0)
{
System.gc();
System.out.println("call gc");
}
startT = System.currentTimeMillis();
}
public static long ellipseT()
{
endT = System.currentTimeMillis();
long consumeT = endT - startT;
System.out.println("consume time :"+ consumeT/1000 + " second");
return consumeT / 1000;
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException
{
// readFile1();
createFile(true);
preparedFile1();
preparedFile2();
}
public static void createFile(boolean bReCreate) throws IOException
{
if(!bReCreate)
{
File f = new File(filename1);
if(!f.exists()) f.createNewFile();
f = new File(filename2);
if(!f.exists()) f.createNewFile();
}
else
{
File f = new File(filename1);
if(f.exists()) f.delete();
f.createNewFile();
f = new File(filename2);
if(f.exists()) f.delete();
f.createNewFile();
}
}
public static void preparedFile2() throws IOException
{
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(filename2));
try
{
System.out.println("fill file by io");
setStartT();
for (int i = 0; i < num; i++)
{
bo.write(content.getBytes());
}
ellipseT();
}
finally
{
if(bo != null) bo.close();
}
}
public static void preparedFile1() throws IOException
{
long mapsize = content.getBytes().length*1000000*100;
long position = 0;
FileChannel ch = new RandomAccessFile(filename1,"rw").getChannel();
MappedByteBuffer mbb = ch.map(MapMode.READ_WRITE, position, mapsize);
int cnt = 0;
try
{
System.out.println("fill file by nio");
setStartT();
for (int i = 0; i < num; i++)
{
if(mbb.remaining() < content.getBytes().length)
{
cnt ++;
position += mbb.position();
mbb = null;
if(cnt %50 == 0)
{
System.gc();
System.out.println("call gc");
}
mbb = ch.map(MapMode.READ_WRITE, position, mapsize);
}
mbb.put(content.getBytes());
}
ellipseT();
}
finally
{
if(ch != null) ch.close();
}
}
public static void readFile1() throws IOException
{
long mapsize = content.getBytes().length*1000000;
long position = 0;
//long rper = 2000000000;
long rper = 1300000000;
FileChannel ch = new RandomAccessFile(filename1,"rw").getChannel();
MappedByteBuffer mbb = ch.map(MapMode.READ_WRITE, 0, rper);
int rs = 102400;
byte dst[] = new byte[rs];
int cnt = 0;
while(mbb.hasRemaining())
{
ByteBuffer bb = mbb.get(dst);
cnt ++;
if(cnt %50 == 0) System.out.println(bb.toString());
}
}
}
4.FileOutputStream 에 도 channel 기능 이 있 지만 메모리 맵 파일 로 파일 을 쓰 려 면 RandomAccessFile 만 사용 할 수 있 습 니 다.쓸 때 읽 기 때문에 사용 할 수 밖 에 없습니다.
5.그 는 다른 ByteBuffer 와 다른 점 이 있 습 니 다.다른 ByteBuffer 는 channel.write/read 로 대상 의 데 이 터 를 기록 하고 읽 어야 합 니 다.MappedByteBuffer 는 목표 에 대한 것 입 니 다.그 수정 은 PRIVATE 를 설정 하지 않 는 한 디스크 에 자동 으로 기 록 됩 니 다.
6.메모리 넘 침 문 제 는 크기 제한 을 제외 하고 큰 파일 을 쓸 때 끊임없이 맵 을 다시 작성 하기 때문에 메모리 가 넘 치 거나 gc 가 메모 리 를 회수 하지 못 할 수도 있 습 니 다.예 를 들 어 상기 프로그램 에서 prepareFile 1 의
mbb = null;
if(cnt %50 == 0)
{
System.gc();
System.out.println("call gc");
}
코드 가 삭제 되면 3G 정도 에 메모리 가 넘 칩 니 다.mbb=null 만 유지 하면;5G 좌우 에 메모리 가 넘 치고,모두 유지 하면 메모리 넘 침 을 알 리 지 않 는 다.따라서 System.gc()를 수 동 으로 실행 해 야 합 니 다.
7.중국어 읽 기와 쓰기 에 있어 서 코드 를 바 꿔 야 합 니 다.
물론 원래 io 도 코드 를 바 꿔 야 하지만 InputStreamReader 에서 문자 집합 을 지정 할 수 있 기 때문에 스스로 코드 를 쓰 지 않 아 도 됩 니 다.
코드 를 바 꾸 지 않 으 면 UE 등의 도구 로 파일 을 열 면 난 코드 가 보이 지만 자바 의 MappedByteBuffer 로 읽 기 처 리 는 중국어 입 니 다.
코드:
public static ByteBuffer getBytes(String str)
{// ( )
Charset cs = Charset.forName("GBK");
ByteBuffer bb = ByteBuffer.wrap(str.getBytes(cs));
return bb;
}
public static String getChars(ByteBuffer bb)
{// ( )
Charset cs = Charset.forName("GBK");
bb.flip();
CharBuffer cb = cs.decode(bb);
return cb.toString();
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.