package com.fourinone;
import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.Buffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.channels.FileLock;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.lang.reflect.Method;
import com.fourinone.FileBatch.TryByteReadAdapter;
import com.fourinone.FileBatch.TryByteWriteAdapter;
import com.fourinone.FileBatch.TryIntReadAdapter;
import com.fourinone.FileBatch.TryIntWriteAdapter;
import java.util.Date;
import java.io.FilenameFilter;
import java.nio.channels.OverlappingFileLockException;
public class FileAdapter extends File
{
private RandomAccessFile raf = null;
private FileChannel fc = null;
private ByteBuffer mbread=null,mbwrite=null;
public static final short[] ConstBit = new short[]{0<<1,1<<1,1<<2,1<<3,3<<1,5<<1,6<<1,7<<1,1<<0};
public static long k(long num)
{
return 0x400*num;
}
public static long m(long num)
{
return 0x400*k(num);
}
public static long g(long num)
{
return 0x400*m(num);
}
public FileAdapter(String filePath)
{
super(filePath);
//fl = new File(filePath);
}
public FileAdapter(String parentPath, String filePath)
{
super(parentPath, filePath);
//fl = parentPath!=null?new File(parentPath, filePath):new File(filePath);
}
FileLock flk = null;
public boolean readLock(){
return readLock(0L, Long.MAX_VALUE);
}
public boolean readLock(long beginIndex, long bytesNum){
return setLock("r", 0L, Long.MAX_VALUE, true);
}
public boolean writeLock(){
return writeLock(0L, Long.MAX_VALUE);
}
public boolean writeLock(long beginIndex, long bytesNum){
if(!this.exists())
createFile(this.getPath());
return setLock("rw", 0L, Long.MAX_VALUE, false);
}
boolean setLock(String rw, long beginIndex, long bytesNum, boolean s){
if(!this.exists())
return false;
try{
raf = new RandomAccessFile(this, rw);
fc = raf.getChannel();
flk = fc.lock(beginIndex, bytesNum, s);
}catch(OverlappingFileLockException oe){
LogUtil.warn("[SetLock]", "[No effect]", "the region has already been locked");
return false;
}catch(Exception e){
LogUtil.info("[SetLock]", "[No effect]", e);
return false;
}
return true;
}
public boolean releaseLock(){
if(!this.exists()||flk==null)
return false;
try{
flk.release();
}catch(Exception e){
LogUtil.info("[ReleaseLock]", "[No effect]", e);
return false;
}
return true;
}
public static ByteReadParser getByteReadParser(byte[] array){
if(array==null)
array=new byte[0];
FileAdapter fa = new FileAdapter("");
fa.mbread = ByteBuffer.wrap(array);
return fa.getReader(Long.MIN_VALUE,Long.MAX_VALUE);
}
public static ByteReadParser getByteReadParser(){
return getByteReadParser(null);
}
public interface ByteReadParser{
public byte[] read(int totalnum);
public byte[] readLine();
public byte[] read(byte[] split);
public byte[] readLast(byte[] split);
public void jump(int num);
public int getReadIndex();
public short readShort();
public int readInt();
public long readLong();
public float readFloat();
public double readDouble();
public Date readDate();
public String readString(int length);
public byte[] readCharsBytes(int length);
public String readChars(int length);
public Object readObject(int length);
public ByteReadParser reset(byte[] array);
public boolean reading();
}
public interface ByteReadAdapter extends ByteReadParser,TryByteReadAdapter{
public byte[] readAll();
public byte[] readAllSafety() throws FileException;
}
public interface IntReadAdapter extends TryIntReadAdapter{
public int[] readIntAll();
public int[] readIntAllSafety() throws FileException;
public int[] readInt(int totalnum);
public int readInt();
public List<Integer> readListIntAll();
public List<Integer> readListInt(int totalnum);
}
public interface ReadAdapter extends ByteReadAdapter,IntReadAdapter{}
private boolean initRead(long beginIndex, long bytesNum)
{
if(beginIndex==Long.MIN_VALUE&&bytesNum==Long.MAX_VALUE)
return true;
try{
if(raf==null)
{
raf = new RandomAccessFile(this, "r");//fl
fc = raf.getChannel();
}
long readnum = Math.min(this.length()-beginIndex, bytesNum);//fl
//if(readnum==0)return false;
mbread = fc.map(MapMode.READ_ONLY, beginIndex, readnum);
}catch(Exception e){
//System.out.println(e);
LogUtil.info("[FileAdapter]", "[ReadAdapter]", e.getMessage());
return false;
}
return true;
}
public interface IntWriteAdapter extends TryIntWriteAdapter{
public int writeInt(int[] its);
public int writeIntSafety(int[] its) throws FileException;
public int writeListInt(List<Integer> ls);
}
public interface ByteWriteAdapter extends TryByteWriteAdapter{
public int write(byte[] bytes);
public int writeSafety(byte[] bytes) throws FileException;
}
public interface WriteAdapter extends ByteWriteAdapter,IntWriteAdapter{}
class NameFilter implements FilenameFilter{
private String namestr;
private boolean onlyFile=false;
public NameFilter(String namestr, boolean onlyFile){
this.namestr = namestr;
this.onlyFile = onlyFile;
}
public boolean accept(File dir, String name){
if(name.startsWith(namestr)){
if(onlyFile){
File dirfile = new File(dir,name);
if(dirfile.isFile())
return true;
else return false;
}else return true;
}else return false;
}
}
public interface ByteWriteParser{
public ByteWriteParser writeBytes(byte[] bts);
public ByteWriteParser writeShort(short n);
public ByteWriteParser writeInt(int n);
public ByteWriteParser writeDouble(double n);
public ByteWriteParser writeLong(long n);
public ByteWriteParser writeFloat(float n);
public ByteWriteParser writeDate(Date time);
public ByteWriteParser writeString(String n);
public ByteWriteParser writeCharsBytes(byte[] bts);
public ByteWriteParser writeChars(String n);
public ByteWriteParser writeObject(Object n);
public int getBytesLength();
public byte[] getBytes();
public ByteWriteParser reset();
public ByteWriteParser reset(int size);
}
public static ByteWriteParser getByteWriteParser(){
return getByteWriteParser((int)k(512));
}
public static ByteWriteParser getByteWriteParser(int size){
FileAdapter fa = new FileAdapter("");
return fa.getByteParserWriter(size);
}
public ByteWriteParser getByteParserWriter(final int size){
return size<=0?null:new ByteWriteParser(){
private int bytesLength=0;
{reset(size);}
public ByteWriteParser writeBytes(byte[] bts){
if(bts!=null&&bts.length>0){
autoBuffer(bts.length);
mbwrite.put(bts);
bytesLength+=bts.length;
}
return this;
}
public ByteWriteParser writeShort(short n){
autoBuffer(ConstBit[1]);
mbwrite.putShort(n);
bytesLength+=ConstBit[1];
return this;
}
public ByteWriteParser writeInt(int n){
autoBuffer(ConstBit[2]);
mbwrite.putInt(n);
bytesLength+=ConstBit[2];
return this;
}
public ByteWriteParser writeDouble(double n){
autoBuffer(ConstBit[3]);
mbwrite.putDouble(n);
bytesLength+=ConstBit[3];
return this;
}
public ByteWriteParser writeLong(long n){
autoBuffer(ConstBit[3]);
mbwrite.putLong(n);
bytesLength+=ConstBit[3];
return this;
}
public ByteWriteParser writeFloat(float n){
autoBuffer(ConstBit[2]);
mbwrite.putFloat(n);
bytesLength+=ConstBit[2];
return this;
}
public ByteWriteParser writeDate(Date time){
return writeLong(time.getTime());
}
public ByteWriteParser writeString(String n){
return writeBytes(n.getBytes());
}
//ObjectBytes objectBytes = new ObjectBytes();
public ByteWriteParser writeCharsBytes(byte[] bts){
return writeBytes(ObjectBytes.getCharSequence(bts));
}
public ByteWriteParser writeChars(String n){
return writeCharsBytes(n.getBytes());
}
public ByteWriteParser writeObject(Object n){
return writeBytes(ObjectBytes.toBytes(n));
}
public int getBytesLength(){
return bytesLength;
}
public byte[] getBytes(){
byte[] btsnew = new byte[bytesLength];
System.arraycopy(mbwrite.array(),0,btsnew,0,bytesLength);
return btsnew;
}
public ByteWriteParser reset(){
//return reset(size);
mbwrite.clear();
bytesLength=0;
return this;
}
public ByteWriteParser reset(int newsize){
mbwrite = ByteBuffer.wrap(new byte[newsize]);
bytesLength=0;
return this;
}
private void autoBuffer(int length){
while(mbwrite.remaining()<length){
byte[] btsnew = new byte[mbwrite.capacity()+size];
System.arraycopy(mbwrite.array(),0,btsnew,0,bytesLength);
mbwrite = ByteBuffer.wrap(btsnew,bytesLength,btsnew.length-bytesLength);
}
}
};
}
//----------------
private void initWrite()
{
try{
if(raf==null)
{
if(!this.exists())//fl
createFile(this.getPath());//fl
raf = new RandomAccessFile(this, "rw");//fl
fc = raf.getChannel();
}
}catch(Exception e){
LogUtil.info("[FileAdapter]", "[WriteAdapter]", e.getMessage());
}
}
public ByteReadAdapter getByteReader(){
return getReader();
}
public IntReadAdapter getIntReader(){
return getReader();
}
public ReadAdapter getReader(){
return getReader(0, this.length());//byte.length
}
public ByteReadAdapter getByteReader(long beginIndex, long bytesNum){
return getReader(beginIndex, bytesNum);
}
public IntReadAdapter getIntReader(long beginIndex, long intNum){
return getReader(beginIndex*4, intNum*4);
}
public ReadAdapter getReader(final long beginIndex, final long bytesNum){
if(!initRead(beginIndex, bytesNum))
return null;
else return new ReadAdapter(){
public void jump(int num){
int jumpnum = Math.min(mbread.remaining(),num);
mbread.position(getReadIndex()+jumpnum);
}
public int getReadIndex(){
return mbread.position();
}
public byte[] readAll(){
return read((int)Math.min(bytesNum, Integer.MAX_VALUE));
}
public byte[] readAllSafety() throws FileException{
byte[] rbts = null;
FileLock fl = null;
try{
fl = fc.lock(beginIndex,bytesNum,true);
rbts = readAll();
fl.release();
}catch(Exception ex){
throw new FileException(ex);
}
return rbts;
}
public Result<byte[]> tryReadAll(){
return tryReadAll(false);
}
public Result<byte[]> tryReadAllSafety(){
return tryReadAll(true);
}
private Result<byte[]> tryReadAll(final boolean locked){
final FileResult<byte[]> fr = new FileResult<byte[]>(false);
PoolExector.tpe().execute(new Runnable(){
public void run(){
try{
byte[] wh = locked?readAllSafety():readAll();
if(wh!=null)
fr.setResult(wh);
fr.setReady(FileResult.READY);
}catch(Throwable e){
LogUtil.info("tryReadAll", "exception", e);
//fr.status = FileResult.EXCEPTION;
fr.setReady(FileResult.EXCEPTION);
}
}
});
return fr;
}
public byte[] read(int totalnum)
{
int readnum = Math.min(mbread.remaining(),totalnum);
byte[] bt = null;
try{
if(readnum>0){
bt = new byte[readnum];
mbread.get(bt);
}
}catch(Exception e){
LogUtil.info("[ReadAdapter]", "[read]", e.getMessage());//
}
return bt;
}
public byte[] readLine()
{
byte[] bts = new byte[]{0xD,0xA};
return read(bts);
}
public byte[] read(byte[] split)
{
if(split==null||mbread.remaining()==0)
return null;
int i=0,p=mbread.position(),n=0;
while(mbread.hasRemaining()&&i<split.length){
byte b = mbread.get();
if(b==split[i]){
if(i++==0)
mbread.mark();
}else{
if(i>0){
mbread.reset();
i=0;
}
n++;
}
}
if(i<split.length){
n+=i;
i=0;
}
mbread.position(p);
byte[] rbts = new byte[n];
mbread.get(rbts);
mbread.position(mbread.position()+i);
return rbts;
}
public byte[] readLast(byte[] split){
byte[] bts = readAll();
if(split==null||bts==null)
return null;
int i=bts.length-1,j=split.length-1,m=-1;
while(i>=0&&j>=0){
if(bts[i--]==split[j]){
if(j--==split.length-1)
m=i;
}else if(m>0){
i=m-1;
j=split.length-1;
m=-1;
}
}
return i>0?Arrays.copyOf(bts, i+1):bts;
}
public int[] readIntAll(){
return readInt((int)(bytesNum/4));
}
public int[] readIntAllSafety() throws FileException{
int[] rits = null;
FileLock fl = null;
try{
fl = fc.lock(beginIndex,bytesNum,true);
rits = readIntAll();
fl.release();
}catch(Exception ex){
throw new FileException(ex);
}
return rits;
}
public Result<int[]> tryIntReadAll(){
return tryIntReadAll(false);
}
public Result<int[]> tryIntReadAllSafety(){
return tryIntReadAll(true);
}
private Result<int[]> tryIntReadAll(final boolean locked){
final FileResult<int[]> fr = new FileResult<int[]>(false);
PoolExector.tpe().execute(new Runnable(){
public void run(){
try{
int[] wh = locked?readIntAllSafety():readIntAll();
if(wh!=null)
fr.setResult(wh);
fr.setReady(FileResult.READY);
}catch(Throwable e){
LogUtil.info("tryIntReadAll", "exception", e);
fr.setReady(FileResult.EXCEPTION);
}
}
});
return fr;
}
public int[] readInt(int totalnum){
int readnum = Math.min(mbread.remaining()/4,totalnum);
int[] its = null;
if(readnum>0){
its = new int[readnum];
for(int i=0;i<its.length;i++)
its[i]=readInt();
}
return its;
}
public List<Integer> readListIntAll(){
return readListInt((int)(bytesNum/4));
}
public List<Integer> readListInt(int totalnum){
int size = Math.min(mbread.remaining()/4,totalnum);
List<Integer> ls = null;
if(size>0){
ls = new ArrayList<Integer>(size);
for(int i=0;i<size;i++)
ls.add(readInt());
}
return ls;
}
public boolean reading(){
return mbread.hasRemaining();
}
public int readInt(){
int n = 0;
try{
n = mbread.getInt();
}catch(Exception e){
LogUtil.info("[ReadAdapter]", "convert int data format error", e.toString());//
}
return n;
}
public short readShort(){
short n = 0;
try{
n = mbread.getShort();
}catch(Exception e){
LogUtil.info("[ReadAdapter]", "convert short data format error", e.toString());
}
return n;
}
public long readLong(){
long n = 0;
try{
n = mbread.getLong();
}catch(Exception e){
LogUtil.info("[ReadAdapter]", "convert long data format error", e.toString());
}
return n;
}
public float readFloat(){
float n = 0;
try{
n = mbread.getFloat();
}catch(Exception e){
LogUtil.info("[ReadAdapter]", "convert float data format error", e.toString());
}
return n;
}
public double readDouble(){
double n = 0;
try{
n = mbread.getDouble();
}catch(Exception e){
LogUtil.info("[ReadAdapter]", "convert double data format error", e.toString());
}
return n;
}
public Date readDate(){
long t = readLong();
return t==0?null:new Date(t);
}
public String readString(int length){
byte[] bts = read(length);
return bts!=null?new String(bts):null;
}
//ObjectBytes objectBytes = new ObjectBytes();
public byte[] readCharsBytes(int length){
return ObjectBytes.getCharSequence(read(length));
}
public String readChars(int length){
byte[] bts=readCharsBytes(length);
return bts!=null?new String(bts):null;
}
public Object readObject(int length){
byte[] bts = read(length);
return bts!=null?ObjectBytes.toObject(bts):null;
}
public ByteReadParser reset(byte[] array){
mbread = ByteBuffer.wrap(array);
return this;
}
};
}
public File createFile()
{
return createFile(this.getPath());
}
public File createDirectory()
{
return createFile(this.getPath(),false);
}
public File createFile(String fileUrl)
{
return createFile(fileUrl,true);
}
public File createFile(String fileUrl, boolean fileflag)
{
File newFile = new File(fileUrl);
try{
if(fileflag){
String parentStr = newFile.getParent();
String fileName = newFile.getName();
File newDir = parentStr!=null?createFile(parentStr, false):new File("");
File theFile = new File(newDir,fileName);
theFile.createNewFile();
/*if(!theFile.createNewFile())
System.out.println(fileUrl+" already existed!");*/
}else{
if(!newFile.exists())
newFile.mkdirs();
}
}catch(Exception e){
LogUtil.info("[FileAdapter]", "[createFile]", e.getMessage()+":"+fileUrl);
}
return newFile;
}
public ByteWriteAdapter getByteWriter(){
return getWriter();
}
public IntWriteAdapter getIntWriter(){
return getWriter();
}
public WriteAdapter getWriter(){
return getWriter(-1, -1);
}
public ByteWriteAdapter getByteWriter(long beginIndex, long bytesNum){
return getWriter(beginIndex, bytesNum);
}
public IntWriteAdapter getIntWriter(long beginIndex, long intNum){
return getWriter(beginIndex*4, intNum*4);
}
public WriteAdapter getWriter(final long beginIndex, final long bytesNum){
initWrite();
final long filesize = this.length();
return new WriteAdapter(){
private long index,num;
private void initIndexNum(long t){
index = beginIndex<0?filesize:beginIndex;
num = bytesNum<0?t:bytesNum;
}
private void initWriteBuffer(int total) throws IOException{
initIndexNum(total);
mbwrite = fc.map(MapMode.READ_WRITE, index, num);
}
public int write(byte[] bytes)
{
int t=0;
try{
initWriteBuffer(bytes.length);
if(bytes.length>num)//mbread.remaining()
bytes = Arrays.copyOf(bytes, (int)num);
mbwrite.put(bytes);
t=bytes.length;
}catch(Exception e){
LogUtil.info("[WriteAdapter]", "[write]", e.getMessage());//
}
return t;
}
/*public int writeSafety(byte[] bytes) throws FileException{
int t = 0;
FileLock fl = null;
try{
initIndexNum(bytes.length);
fl = fc.lock(index,num,false);//
t = write(bytes);//raf.write(1);
fl.release();//
}catch(Exception ex){
throw new FileException(ex);
}
return t;
}*/
public int writeSafety(byte[] bytes) throws FileException{
return writeSafety(bytes, null);
}
private int writeSafety(byte[] bytes, int[] its) throws FileException{
int t = 0;
FileLock fl = null;
try{
if(bytes!=null)
initIndexNum(bytes.length);
else
initIndexNum(its.length*4);
fl = fc.lock(index,num,false);
t = bytes!=null?write(bytes):writeInt(its);
fl.release();
}catch(Exception ex){
throw new FileException(ex);
}
return t;
}
private int write(byte[] bytes, int[] its){
return bytes!=null?write(bytes):writeInt(its);
}
public Result<Integer> tryWrite(byte[] bytes){
return tryWrite(bytes, null, false);
}
public Result<Integer> tryWriteSafety(byte[] bytes){
return tryWrite(bytes, null, true);
}
/*private Result<Integer> tryWrite(final byte[] bytes, final boolean locked)
{
final FileResult<Integer> fr = new FileResult<Integer>(false);
PoolExector.tpe().execute(new Runnable(){
public void run(){
try{
int bl = locked?writeSafety(bytes):write(bytes);
fr.setResult(new Integer(bl));
//fr.setReady(true);
fr.setReady(FileResult.READY);
}catch(Throwable e){
LogUtil.info("tryWrite", "exception", e);
//fr.status = FileResult.EXCEPTION;
fr.setReady(FileResult.EXCEPTION);
}
}
});
return fr;
}*/
private Result<Integer> tryWrite(final byte[] bytes, final int[] its, final boolean locked)
{
final FileResult<Integer> fr = new FileResult<Integer>(false);
PoolExector.tpe().execute(new Runnable(){
public void run(){
try{
int bl = locked?writeSafety(bytes, its):write(bytes, its);
fr.setResult(new Integer(bl));
//fr.setReady(true);
fr.setReady(FileResult.READY);
}catch(Throwable e){
LogUtil.info("tryWrite", "exception", e);
//fr.status = FileResult.EXCEPTION;
fr.setReady(FileResult.EXCEPTION);
}
}
});
return fr;
}
public int writeInt(int[] its)
{
int i=0;
try{
initWriteBuffer(its.length*4);
int wt = Math.min((int)(num/4),its.length);
for(;i<wt;i++)
mbwrite.putInt(its[i]);
}catch(Exception e){
LogUtil.info("[WriteAdapter]", "[writeInt]", e.getMessage());
}
return i;
}
/*public int writeIntSafety(int[] its) throws FileException
{
int t = 0;
FileLock fl = null;
try{
initIndexNum(its.length*4);
fl = fc.lock(index,num,false);
t = writeInt(its);
fl.release();
}catch(Exception ex){
throw new FileException(ex);
}
return t;
}*/
public int writeIntSafety(int[] its) throws FileException{
return writeSafety(null, its);
}
public Result<Integer> tryIntWrite(int[] its){
return tryWrite(null, its, false);
}
public Result<Integer> tryIntWriteSafety(int[] its){
return tryWrite(null, its, true);
}
/*private Result<Integer> tryIntWrite(final int[] its, final boolean locked)
{
final FileResult<Integer> fr = new FileResult<Integer>(false);
PoolExector.tpe().execute(new Runnable(){
public void run(){
try{
int bl = locked?writeIntSafety(its):writeInt(its);
fr.setResult(new Integer(bl));
fr.setReady(FileResult.READY);
}catch(Throwable e){
LogUtil.info("tryIntWrite", "exception", e);
fr.setReady(FileResult.EXCEPTION);
}
}
});
return fr;
}*/
public int writeListInt(List<Integer> ls)
{
int i=0;
try{
initWriteBuffer(ls.size()*4);
int wt = Math.min((int)(num/4),ls.size());
for(;i<wt;i++)
mbwrite.putInt(ls.get(i));
}catch(Exception e){
LogUtil.info("[WriteAdapter]", "[writeListInt]", e.getMessage());
}
return i;
}
};
}
/*public boolean exists()
{
return fl.exists();
}
public boolean isFile()
{
return fl.isFile();
}
public String getPath()
{
return fl.getPath();
}
public boolean delete()
{
close();
boolean b = false;
try{
b = fl.delete();
}catch(Exception e){
System.out.println(e);
}
return b;
}*/
public int copyTo(String toFilePath){
return copyTo(toFilePath, FileAdapter.m(8));
}
public int copyTo(String toFilePath, long every){
int c=0;
FileAdapter fa = new FileAdapter(toFilePath);
fa.createFile();
byte[] bts = null;
long begin=0;
while((bts=this.getReader(begin, every).readAll())!=null){
c+=fa.getWriter().write(bts);
begin+=bts.length;
}
fa.close();
return c;
}
public Result<Integer> tryCopyTo(String toFilePath){
return tryCopyTo(toFilePath, FileAdapter.m(8));
}
public Result<Integer> tryCopyTo(final String toFilePath, final long every)
{
final FileResult<Integer> fr = new FileResult<Integer>(false);
PoolExector.tpe().execute(new Runnable(){
public void run(){
try{
int bl = copyTo(toFilePath, every);
fr.setResult(new Integer(bl));
fr.setReady(FileResult.READY);
}catch(Throwable e){
LogUtil.info("tryCopyFile", "exception", e);
fr.setReady(FileResult.EXCEPTION);
}
}
});
return fr;
}
public final void closeBuffer(final Buffer buffer){
if(null==buffer)
return;
AccessController.doPrivileged(new PrivilegedAction<Object>(){
public Object run() {
try {
Method cleanerMethod = buffer.getClass().getMethod("cleaner");
if (null==cleanerMethod)
return null;
cleanerMethod.setAccessible(true);
Object cleanerObj = cleanerMethod.invoke(buffer);
if(null==cleanerObj)
return null;
Method cleanMethod = cleanerObj.getClass().getMethod("clean");
if (null==cleanMethod)
return null;
cleanMethod.invoke(cleanerObj);
}catch(Throwable e){}
return null;
}
});
}
public void closeExit(){
PoolExector.close();
close();
}
public void close()
{
try{
if(fc!=null)fc.close();
if(raf!=null)raf.close();
closeBuffer(mbread);
closeBuffer(mbwrite);
}catch(Exception e){
LogUtil.info("[FileAdapter]", "[close]", e.getMessage());
}
}
public static void main(String[] args)
{
}
}