All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scudata.dm.BFileReader Maven / Gradle / Ivy

Go to download

SPL(Structured Process Language) A programming language specially for structured data computing.

There is a newer version: 20240823
Show newest version
package com.scudata.dm;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import com.scudata.array.IArray;
import com.scudata.array.IntArray;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.cursor.BFileCursor;
import com.scudata.dm.cursor.ICursor;
import com.scudata.dm.cursor.MemoryCursor;
import com.scudata.dm.cursor.PFileCursor;
import com.scudata.expression.Expression;
import com.scudata.resources.EngineMessage;
import com.scudata.util.Variant;

/**
 * ???ļ???ȡ????
 * @author WangXiaoJun
 *
 */
public class BFileReader {
	private FileObject file; // ???ļ???Ӧ???ļ?????
	private int type; // ???ļ?????
	private long []blocks; // ÿһ??Ľ???λ??
	private int lastBlock; // ???һ???????
	private long totalRecordCount;	// ??¼????
	private long blockRecordCount;	// ????????
	private long firstRecordPos; // ??һ????¼??λ??
	
	private DataStruct ds; // ???ļ????ݽṹ
	private DataStruct readDs; // ѡ???ֶ???ɵ????ݽṹ
	private String []readFields; // ѡ???ֶ?
	private int []readIndex; // ѡ???ֶζ?Ӧ?????
	private boolean isSingleField; // ?Ƿ񷵻ص?????ɵ?????
	private boolean isSequenceMember; // ?Ƿ񷵻???????ɵ?????
	private boolean isExist = true; // ?ֶ??Ƿ????ļ???

	private int segSeq; // ?ֶ???ţ???1??ʼ????
	private int segCount; // ?ֶ???
	private long endPos = -1; // ??ȡ?Ľ???λ?ã????ڶ??̷ֶ߳ζ?ȡ
	
	private ObjectReader importer; // ?????ȡ??
	
	/**
	 * ???ļ????󴴽????ļ???ȡ??
	 * 
	 * @param file	?ļ?????
	 */
	public BFileReader(FileObject file) {
		this(file, null, null);
	}
	
	/**
	 * ???ļ??????????Ͷ?д?ַ??????????????ļ?
	 * @param file ?ļ?????
	 * @param fields ѡ???ֶ?
	 * @param opt ѡ?i???????ֻ??1??ʱ???س????У?e?????ļ??в?????ʱ??????null??ȱʡ????????w????ÿ?ж???????
	 */
	public BFileReader(FileObject file, String []fields, String opt) {
		this(file, fields, 1, 1, opt);
	}

	/**
	 * ???ļ??????????Ͷ?д?ַ??????????????ļ?
	 * @param file ?ļ?????
	 * @param fields ѡ???ֶ?
	 * @param segSeq Ҫ??ȡ?Ķκţ???1??ʼ????
	 * @param segCount ?ֶ???
	 * @param opt ѡ?i???????ֻ??1??ʱ???س????У?e?????ļ??в?????ʱ??????null??ȱʡ????????w????ÿ?ж???????
	 */
	public BFileReader(FileObject file, String []fields, int segSeq, int segCount, String opt) {
		this.file = file;
		this.segSeq = segSeq;
		this.segCount = segCount;
		
		if (fields != null) {
			readFields = new String[fields.length];
			System.arraycopy(fields, 0, readFields, 0, fields.length);
		}
		
		if (opt != null) {
			if (opt.indexOf('i') != -1) isSingleField = true;
			if (opt.indexOf('e') != -1) isExist = false;
			if (opt.indexOf('w') != -1) isSequenceMember = true;
		}
		
		if (segCount > 1) {
			if (segSeq < 0 || segSeq > segCount) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(segSeq + mm.getMessage("function.invalidParam"));
			}
		}
	}
	
	/**
	 * ?????нṹ
	 * @return DataStruct
	 */
	public DataStruct getFileDataStruct() {
		return ds;
	}
	
	/**
	 * ???ļ????зֶ?
	 * 
	 * @throws IOException
	 */
	private void doSegment() throws IOException {
		int segSeq = this.segSeq - 1;
		int avg = (lastBlock + 1) / segCount;
		
		if (avg < 1) {
			// ÿ?β???һ??
			if (segSeq > lastBlock) {
				endPos = 0;
			} else {
				endPos = blocks[segSeq];
				if (segSeq > 0) {
					importer.seek(blocks[segSeq - 1]);
				}
			}
		} else {
			if (segSeq > 0) {
				int s = segSeq * avg - 1;
				int e = s + avg;
				
				// ʣ??Ŀ?????ÿ?ζ?һ??
				int mod = (lastBlock + 1) % segCount;
				int n = mod - (segCount - segSeq - 1);
				if (n > 0) {
					e += n;
					s += n - 1;
				}
				
				endPos = blocks[e];
				importer.seek(blocks[s]);
			} else {
				endPos = blocks[avg - 1];
			}
		}
	}
	
	/**
	 * ??ǰ??????????λ??
	 * @return	???ص?ǰ??????λ??
	 */
	public long position() {
		return importer.position();
	}
	
	/**
	 * ??λ????????λ?á?
	 * ֧?????λ????ǰ??λ?Ļ?????????????????Χ???ͻ????쳣??
	 * @param pos	Ҫ??λ??λ??
	 * @throws IOException
	 */
	public void seek(long pos) throws IOException {
		importer.seek(pos);
	}
	
	/**
	 * ??ǰ??ȡ???Ƿ??
	 * 
	 * @return
	 */
	public boolean isOpen() {
		return importer != null;
	}
	
	/**
	 * 
	 * @throws IOException
	 */
	public void open() throws IOException {
		open(Env.FILE_BUFSIZE);
	}
	
	/**
	 * ???´?
	 * 
	 * @param bufSize	???????Ĵ?С
	 */
	private void reopen(int bufSize) {
		InputStream in = file.getBlockInputStream(bufSize);
		ObjectReader importer = new ObjectReader(in, bufSize);
		this.importer = importer;
	}
	
	/**
	 * ??һ?????????ļ???????bufSize??ʼ???ļ???ȡ??Ļ???????С??
	 * 
	 * @param bufSize	???????Ĵ?С
	 * @throws IOException
	 */
	public void open(int bufSize) throws IOException {
		InputStream in = file.getBlockInputStream(bufSize);
		ObjectReader importer = new ObjectReader(in, bufSize);
		this.importer = importer;
		
		if (importer.read() != 'r' || importer.read() != 'q' || importer.read() != 't' || 
				importer.read() != 'b' || importer.read() != 'x') {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("license.fileFormatError"));
		}
		
		type = importer.read();
		int ver = importer.readInt32();
		
		if (type == BFileWriter.TYPE_NORMAL) {
			if (segCount > 1) {
				//MessageManager mm = EngineMessage.get();
				//throw new RQException(mm.getMessage("engine.needZFile"));
				if (segSeq > 1) {
					endPos = 0;
				}
			}
			
			totalRecordCount = importer.readLong64();
			ds = new DataStruct(importer.readStrings());
			firstRecordPos = position();
		} else if (type == BFileWriter.TYPE_BLOCK) {
			totalRecordCount = importer.readLong64();
			blockRecordCount = importer.readLong64();
			importer.readLong64(); // lastRecordCount
			lastBlock = importer.readInt32();
			
			int count = importer.readInt32();
			long []blocks = new long[count];
			this.blocks = blocks;
			for (int i = 0; i < count; ++i) {
				blocks[i] = importer.readLong64();
			}
			
			ds = new DataStruct(importer.readStrings());
			firstRecordPos = position();
			
			if (segCount > 1) {
				doSegment();
			}
		} else if (type == BFileWriter.TYPE_GROUP) {
			totalRecordCount = importer.readLong64();
			if (ver > 0) {
				blockRecordCount = importer.readLong64();
				importer.readLong64(); // lastRecordCount
			}
			
			lastBlock = importer.readInt32();
			int count = importer.readInt32();
			long []blocks = new long[count];
			this.blocks = blocks;
			for (int i = 0; i < count; ++i) {
				blocks[i] = importer.readLong64();
			}
			
			ds = new DataStruct(importer.readStrings());
			firstRecordPos = position();
			
			if (segCount > 1) {
				doSegment();
			}
		} else {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("license.fileFormatError"));
		}
		
		String []fields = ds.getFieldNames();
		int fcount = fields.length;
		
		if (readFields != null) {
			if (isSingleField) {
				isSingleField = readFields.length == 1;
			}
			
			readIndex = new int[fcount];
			for (int i = 0; i < fcount; ++i) {
				readIndex[i] = -1;
			}

			for (int i = 0, count = readFields.length; i < count; ++i) {
				int q = ds.getFieldIndex(readFields[i]);
				if (q >= 0) {
					if (readIndex[q] != -1) {
						MessageManager mm = EngineMessage.get();
						throw new RQException(readFields[i] + mm.getMessage("ds.colNameRepeat"));
					}

					readIndex[q] = i;
					readFields[i] = fields[q];
				} else if (isExist) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(readFields[i] + mm.getMessage("ds.fieldNotExist"));
				}
			}

			readDs = new DataStruct(readFields);
		} else {
			if (isSingleField) isSingleField = fcount == 1;
		}
	}
	
	/**
	 * ?ر??ļ????ر???
	 * @throws IOException
	 */
	public void close() throws IOException {
		if (importer != null) {
			importer.close();
			importer = null;
		}
	}
	
	/**
	 * ??ȡ?ļ??????еļ?¼??????????з??ء?
	 * 
	 * @return
	 * @throws IOException
	 */
	public Sequence readAll() throws IOException {
		return read(ICursor.MAXSIZE);
	}
	
	/**
	 * ??ȡָ???????ļ?¼
	 * @param n	Ҫ??ȡ?ļ?¼??
	 * @return	?????б???ļ?¼??
	 * @throws IOException
	 */
	public Sequence read(int n) throws IOException {
		long endPos = this.endPos;
		ObjectReader importer = this.importer;
		if (n < 1 || (endPos != -1 && importer.position() >= endPos)) {
			return null;
		}

		int fcount = ds.getFieldCount();
		int initSize;
		if (n <= ICursor.FETCHCOUNT) {
			initSize = n;
		} else if (n >= totalRecordCount && totalRecordCount > 0) {
			// ?ֶζ????Ƽ??˼?¼????;
			initSize = (int)totalRecordCount;
		} else if (n < ICursor.MAXSIZE) {
			initSize = n;
		} else {
			initSize = ICursor.INITSIZE;
		}
		
		if (isSingleField) {
			Sequence seq = new Sequence(initSize);
			if (readFields == null) {
				for (int i = 0; i < n; ++i) {
					if (importer.hasNext() && (endPos == -1 || importer.position() < endPos)) {
						seq.add(importer.readObject());
					} else {
						break;
					}
				}
			} else {
				int []readIndex = this.readIndex;
				for (int i = 0; i < n; ++i) {
					if (importer.hasNext() && (endPos == -1 || importer.position() < endPos)) {
						for (int f = 0; f < fcount; ++f) {
							if (readIndex[f] != -1) {
								seq.add(importer.readObject());
							} else {
								importer.skipObject();
							}
						}
					} else {
						break;
					}
				}
			}

			if (seq.length() != 0) {
				return seq;
			} else {
				return null;
			}
		} else if (isSequenceMember) {
			Sequence seq = new Sequence(initSize);
			if (readFields == null) {
				Sequence tmp = new Sequence(ds.getFieldNames());
				seq.add(tmp);
				Object []values = new Object[fcount];
				for (int i = 0; i < n; ++i) {
					if (importer.hasNext() && (endPos == -1 || importer.position() < endPos)) {
						for (int f = 0; f < fcount; ++f) {
							values[f] = importer.readObject();
						}
						
						seq.add(new Sequence(values));
					} else {
						break;
					}
				}
			} else {
				Sequence tmp = new Sequence(readFields);
				seq.add(tmp);
				Object []values = new Object[readFields.length];
				int []readIndex = this.readIndex;
				for (int i = 0; i < n; ++i) {
					if (importer.hasNext() && (endPos == -1 || importer.position() < endPos)) {
						for (int f = 0; f < fcount; ++f) {
							if (readIndex[f] != -1) {
								values[readIndex[f]] = importer.readObject();
							} else {
								importer.skipObject();
							}
						}
						
						seq.add(new Sequence(values));
					} else {
						break;
					}
				}
			}

			if (seq.length() != 0) {
				//seq.trimToSize();
				return seq;
			} else {
				return null;
			}
		} else {
			Table table;
			if (readFields == null) {
				table = new Table(ds, initSize);
				for (int i = 0; i < n; ++i) {
					if (importer.hasNext() && (endPos == -1 || importer.position() < endPos)) {
						BaseRecord cur = table.newLast();
						for (int f = 0; f < fcount; ++f) {
							cur.setNormalFieldValue(f, importer.readObject());
						}
					} else {
						break;
					}
				}
			} else {
				int []readIndex = this.readIndex;
				table = new Table(readDs, initSize);

				for (int i = 0; i < n; ++i) {
					if (importer.hasNext() && (endPos == -1 || importer.position() < endPos)) {
						BaseRecord cur = table.newLast();
						for (int f = 0; f < fcount; ++f) {
							if (readIndex[f] != -1) {
								cur.setNormalFieldValue(readIndex[f], importer.readObject());
							} else {
								importer.skipObject();
							}
						}
					} else {
						break;
					}
				}
			}

			if (table.length() != 0) {
				//table.trimToSize();
				return table;
			} else {
				return null;
			}
		}
	}
	
	/**
	 * ??????????ָ???ļ?¼??
	 * 
	 * @param n	Ҫ?????ļ?¼??
	 * @return	????ʵ?ʵ??????ļ?¼??
	 * @throws IOException
	 */
	public long skip(long n) throws IOException {
		if (totalRecordCount > 0 && segCount <= 1 && firstRecordPos == position() && endPos == -1) {
			if (totalRecordCount <= n) {
				seek(file.size());
				return totalRecordCount;
			}

			if (type == BFileWriter.TYPE_BLOCK && blockRecordCount < n) {
				int i = (int)(n / blockRecordCount);
				seek(blocks[i - 1]);
				skip(n - blockRecordCount * i);
				return n;
			}
		}
		
		ObjectReader importer = this.importer;
		if (n < 1 || (endPos != -1 && importer.position() >= endPos)) {
			return 0;
		}

		int fcount = ds.getFieldCount();
		for (long i = 0; i < n; ++i) {
			if (importer.hasNext() && (endPos == -1 || importer.position() < endPos)) {
				for (int f = 0; f < fcount; ++f) {
					importer.skipObject();
				}
			} else {
				return i;
			}
		}

		return n;
	}
	
	/**
	 * ȡ??ǰ??¼??ָ???ֶ?
	 * 
	 * @param fields	?ֶα?ǣ?ֵΪ-1?IJ?ȡ????
	 * @param values	???????
	 * @return		true	ȡ???ɹ?
	 * 				false	ȡ??ʧ??
	 * @throws IOException
	 */
	public boolean readRecord(int []fields, Object []values) throws IOException {
		ObjectReader importer = this.importer;
		if (importer.hasNext()) {
			for (int f = 0, fcount = fields.length; f < fcount; ++f) {
				if (fields[f] != -1) {
					values[fields[f]] = importer.readObject();
				} else {
					importer.skipObject();
				}
			}
			
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * ??ȡһ??һ????¼??ij???ֶΡ?
	 * @param field	ָ?????ֶ???????
	 * @return	????ֵ??ȡ?Ľ??
	 * @throws IOException
	 */
	private Object readRecordField(int field) throws IOException {
		ObjectReader importer = this.importer;
		for (int f = 0; f < field; ++f) {
			importer.skipObject();
		}
		
		return importer.readObject();
	}
	
	// ȡ??ǰ??¼???ֶ?
	/**
	 * ??ȡһ????¼
	 * 
	 * @param values	?????¼?Ķ???????
	 * @return			true	ȡ???ɹ?
	 * 					false	ȡ??ʧ??
	 * @throws IOException
	 */
	public boolean readRecord(Object []values) throws IOException {
		ObjectReader importer = this.importer;
		if (importer.hasNext()) {
			for (int f = 0, fcount = values.length; f < fcount; ++f) {
				values[f] = importer.readObject();
			}
			
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * ??????¼????????ļ?β?򷵻?false
	 * @return
	 * @throws IOException
	 */
	public boolean skipRecord() throws IOException {
		ObjectReader importer = this.importer;
		if (importer.hasNext()) {
			for (int f = 0, fcount = ds.getFieldCount(); f < fcount; ++f) {
				importer.skipObject();
			}
			
			return true;
		} else {
			return false;
		}
	}
			
	/**
	 * ?Ӷ?x??????ļ?f????x??????A?еļ?¼?????α?
	 * ?ӵ?ǰ???ݼ??У?ѡ??keyֵ??values?еļ?¼??ѡȡfields?ֶ?ֵ?????±??????????±????αꡣ
	 * @param key		?Ѿ??ź?????ֶε??ֶ?????
	 * @param values	?ο?ֵ????key?ֶ?????Щֵ???Ա?
	 * @param fields	?ֶ????б??????յý??????????Щ?ֶ????
	 * @param ctx		?????ı???
	 * @return			????ɸѡ???????ݼ????α?
	 */
	public ICursor iselect(String key, Sequence values, String []fields, Context ctx) {
		int count = values.length();
		if (count == 0) {
			//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
			return new MemoryCursor(null);
		}
		
		try {
			// ?򿪶??????ļ????????û???????С
			open(1024);
			long []blocks = this.blocks;
			if (blocks == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("license.fileFormatError"));
			}
			
			// ȡ???ֶ?????
			int keyField = ds.getFieldIndex(key);
			if (keyField < 0) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(key + mm.getMessage("ds.fieldNotExist"));
			}
			
			int lastBlock = this.lastBlock;
			int fcount = ds.getFieldCount();
			Object []vals = new Object[fcount];
			
			// ????ֶ?
			LongArray posArray = new LongArray(count > 5 ? count * 2 : 10);
			long prevEnd = position();
			int nextBlock = 0;
			Object nextBlockVal = null;
			if (lastBlock > 0) {
				seek(blocks[0]);
				readRecord(vals);
				nextBlockVal = vals[keyField];
			}
			
			int i = 1;
			while (i <= count && nextBlock < lastBlock) {
				Object val = values.getMem(i);
				int cmp = Variant.compare(val, nextBlockVal);
				
				// ??Ϊ?ļ????????ظ???ֵ????ȵ?ʱ????Ҫ??ǰһ?鿪ʼ??
				if (cmp <= 0) {
					if (position() > prevEnd) {
						close();
						reopen(1024);
						seek(prevEnd);
					}
					
					while (true) {
						readRecord(vals);
						cmp = Variant.compare(val, vals[keyField]);
						if (cmp > 0) {
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(vals);
									nextBlockVal = vals[keyField];
								}
								
								break;
							}
						} else if (cmp == 0) {
							posArray.add(prevEnd);
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(vals);
									nextBlockVal = vals[keyField];
								}
								
								break;
							}

							// ?ļ????????ظ???ֵ??????????û?к͵?ǰֵ?ظ???
							continue;
						} else {
							i++;
							while (i <= count) {
								val = values.getMem(i);
								cmp = Variant.compare(val, vals[keyField]);
								if (cmp > 0) {
									break;
								} else if (cmp == 0) {
									posArray.add(prevEnd);
									break;
								} else {
									i++;
								}
							}
							
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(vals);
									nextBlockVal = vals[keyField];
								}
								
								break;
							}
							
							break;
						}
					}
				} else {
					prevEnd = blocks[nextBlock];					
					nextBlock++;
					if (nextBlock < lastBlock) {
						seek(blocks[nextBlock]);
						readRecord(vals);
						nextBlockVal = vals[keyField];
					}
				}
			}
			
			if (i <= count) {
				if (position() > prevEnd) {
					close();
					reopen(1024);
					seek(prevEnd);
				}
				
				Object val = values.getMem(i);
				while (i <= count && readRecord(vals)) {
					int cmp = Variant.compare(val, vals[keyField]);
					if (cmp > 0) {
						prevEnd = position();
					} else if (cmp == 0) {
						posArray.add(prevEnd);
						prevEnd = position();
					} else {
						i++;
						while (i <= count) {
							val = values.getMem(i);
							cmp = Variant.compare(val, vals[keyField]);
							if (cmp > 0) {
								break;
							} else if (cmp == 0) {
								posArray.add(prevEnd);
								break;
							} else {
								i++;
							}
						}
						
						prevEnd = position();
					}
				}
			}
			
			if (posArray.size() == 0) {
				//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
				return new MemoryCursor(null);
			}
						
			return new PFileCursor(file, posArray.toArray(), 1024, fields, null, ctx);
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
	}
	
	/**
	 * ?Ӷ?x??????ļ?f????x??[a,b]????ļ?¼?????α?
	 * ?ӵ?ǰ???ݼ??У?ѡ??keyֵ??startVal??endVal֮??ļ?¼??ѡȡfields?ֶ?ֵ?????±??????????±????αꡣ
	 * @param key		?Ѿ??ź?????ֶε??ֶ?????
	 * @param startVal	ɸѡ???ݵ???ʼֵ
	 * @param endVal	ɸѡ???ݵĽ???ֵ
	 * @param fields	?ֶ????б??????յý??????????Щ?ֶ????
	 * @param ctx		?????ı???
	 * @return
	 */
	public ICursor iselect(String key, Object startVal, Object endVal, String []fields, Context ctx) {
		int startBlock;
		int endBlock ;
		int keyField;
		long firstPos;
		
		try {
			open(1024);
			firstPos = position();
			long []blocks = this.blocks;
			if (blocks == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("license.fileFormatError"));
			}
			
			keyField = ds.getFieldIndex(key);
			if (keyField < 0) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(key + mm.getMessage("ds.fieldNotExist"));
			}
			
			int lastBlock = this.lastBlock;
			startBlock = lastBlock;
			endBlock = lastBlock;
			
			for (int i = 0; i < lastBlock; ++i) {
				seek(blocks[i]);
				Object val = readRecordField(keyField);
				if (Variant.compare(val, startVal) >= 0) {
					startBlock = i;
					if (endVal != null && Variant.compare(val, endVal) > 0) {
						endBlock = i;
					}
					
					break;
				}
			}
			
			if (endVal != null && endBlock != startBlock) {
				for (int i = startBlock + 1; i < lastBlock; ++i) {
					seek(blocks[i]);
					Object val = readRecordField(keyField);
					if (Variant.compare(val, endVal) > 0) {
						endBlock = i;
						break;
					}
				}
			}
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
		
		try {
			reopen(1024);
			seek(firstPos);
			
			long []blocks = this.blocks;
			long startPos = blocks[startBlock];
			int fcount = ds.getFieldCount();
			Object []vals = new Object[fcount];
			
			if (startBlock > 0) {
				seek(blocks[startBlock - 1]);
			}
			
			long pos = firstPos;
			while (pos < startPos) {
				readRecord(vals);
				if (Variant.compare(vals[keyField], startVal) >= 0) {
					if (endVal != null && Variant.compare(vals[keyField], endVal) > 0) {
						//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
						return new MemoryCursor(null);
					}
					
					startPos = pos;
					break;
				}
				
				pos = position();
			}
			
			long endPos = blocks[endBlock];
			if (endVal != null) {
				if (endBlock > 0 && position() < blocks[endBlock - 1]) {
					seek(blocks[endBlock - 1]);
				}
				
				pos = position();
				while (pos < endPos) {
					readRecord(vals);
					if (Variant.compare(vals[keyField], endVal) > 0) {
						endPos = pos;
						break;
					}
					
					pos = position();
				}
			}
			
			if (startPos < endPos) {
				BFileCursor cursor = new BFileCursor(file, fields, null, ctx);
				cursor.setPosRange(startPos, endPos);
				return cursor;
			} else {
				//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
				return new MemoryCursor(null);
			}
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
	}
	
	/**
	 * ???ö?ȡ?Ľ???λ?ã????ڶ??̷ֶ߳ζ?ȡ
	 * @param pos λ??
	 */
	public void setEndPos(long pos) {
		this.endPos = pos;
	}
	
	/**
	 * ȡ????????ݽṹ
	 * @return
	 */
	public DataStruct getResultSetDataStruct() {
		if (readDs == null) {
			return ds;
		} else {
			return readDs;
		}
	}
	
	/**
	 * ?Աȶ???ֶε?ֵ
	 * 
	 * @param fieldsValue	?ֶ?ֵ
	 * @param refValues		?ο?ֵ
	 * @return	1	fieldsValue??ֵ?Ƚϴ?
	 * 			0	????????һ????
	 * 			-1	refValues??ֵ?Ƚϴ?
	 */
	private int	compareFields(Object[] fieldsValue, Object refValues ) {
		Object refObj = null;
		for (int i = 0; i < fieldsValue.length; i++) {
			if (refValues instanceof Sequence) {
				refObj = ((Sequence)refValues).get(i+1);
			} else
				refObj = refValues;
			
			int res = Variant.compare(fieldsValue[i], refObj);
			if (res > 0)
				return 1;
			else if (res < 0)
				return -1;
		}
		return 0;
	}
	
	/**
	 * ?Աȶ???ֶε?ֵ
	 * 
	 * @param fieldsValue	?ֶ?ֵ
	 * @param refValues		?ο?ֵ
	 * @return	1	refValues??ֵ?Ƚϴ?
	 * 			0	????????һ????
	 * 			-1	fieldsValue??ֵ?Ƚϴ?
	 */	
	private int compareFields(Object refValues, Object[] fieldsValue) {
		Object refObj = null;
		for (int i = 0; i < fieldsValue.length; i++) {
			if (refValues instanceof Sequence) {
				refObj = ((Sequence)refValues).get(i+1);
			} else
				refObj = refValues;
			
			int res = Variant.compare(fieldsValue[i], refObj);
			if (res > 0)
				return -1;
			else if (res < 0)
				return 1;
		}
		return 0;		
	}
	
	/**
	 * ѡ??????ʽ?ļ???????values?еļ?¼
	 * @param exp		????ʽ
	 * @param values	?ԱȽ??
	 * @param fields	??ɽ?????ֶ?
	 * @param ctx		?????ı???
	 * @return			????ɸѡ???ļ?¼
	 */
	public ICursor iselect(Expression exp, Sequence values, String []fields, Context ctx) {
		if (exp == null) {
			//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
			return new MemoryCursor(null);
		}
		
		// ???ֶα???ʽ????????????̣????Դ?????Ч??
		//  ???????ʽ?Ƿ?ʽ???ַ???
		String[] fieldNames = exp.toFields();
		
		try {
			open(1024);
			
			if (blocks == null) {
				// ???ֶμ??ļ?????˳?????
				Sequence result = readAll();
				Sequence fieldValues = result.calc(exp, ctx);
				IArray valueArray = fieldValues.getMems();
				IntArray seqArray = null;
				
				for (int i = 1, len = values.length(); i <= len; ++i) {
					IntArray array = valueArray.indexOfAll(values.getMem(i), 1, true, true);
					if (seqArray == null) {
						seqArray = array;
					} else {
						seqArray.addAll(array);
					}
				}
				
				if (seqArray == null || seqArray.size() == 0) {
					return new MemoryCursor(null);
				}

				result = result.get(new Sequence(seqArray));
				MemoryCursor cs = new MemoryCursor(result);
				if (fields != null) {
					int fcount = fields.length;
					Expression []exps = new Expression[fcount];
					for (int f = 0; f < fcount; ++f) {
						exps[f] = new Expression(fields[f]);
					}
					
					cs.newTable(null, exps, fields, null, ctx);
				}
				
				return cs;
			}
			
			if (fieldNames != null) {
				for (String name : fieldNames) {
					if (ds.getFieldIndex(name) == -1) {
						fieldNames = null;
						break;
					}
				}
			}
		} catch (IOException e) {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("file.fileNotExist", file.getFileName()));
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
		
				
		if (fieldNames != null) {
			return iselectFields(fieldNames, values, fields, ctx);
		} else {
			return iselectExpression(exp, values, fields, ctx);
		}
	}
	
	/**
	 * ???ֶΡ????ֶδӵ?ǰ???ݼ???ѡ???? values?еļ?¼
	 * 
	 * @param	refFields	?ο??ֶ?
	 * @param	values		?ο??ֶεIJο?ֵ
	 * @param	fields      ?????±????ֶΣ????Բ??????ο??ֶ?
	 * @param	ctx			?????ı???
	 * 
	 * @return	????ɸѡ???????ݼ?cursor
	 * 
	*/
	public ICursor iselectFields(String[] refFields, Sequence values, String []fields, Context ctx) {
		// ???Ҷ?Ӧ?е?????
		int fcount = ds.getFieldCount();
		int[] selFields = new int[fcount];
		for (int i = 0; i < fcount; i++) {
			selFields[i] = -1;
		}

		int fcou = 0;
		for (int i = 0; i < refFields.length; i++) {
			int index = ds.getFieldIndex(refFields[i]);
			if (0 > index ) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(refFields[i] + mm.getMessage("ds.fieldNotExist"));
			}
			selFields[index] = fcou;
			fcou++;
		}
		
		// ȡ?ü?¼????
		int count = values.length();
		if (count == 0) {
			//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
			return new MemoryCursor(null);
		}
		
		try {
			// ???ļ?
			open(1024);
			long []blocks = this.blocks;
			if (blocks == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("license.fileFormatError"));
			}
					
			int lastBlock = this.lastBlock;
			Object []vals = new Object[fcou];
			
			LongArray posArray = new LongArray(count > 5 ? count * 2 : 10);
			long prevEnd = position();
			int nextBlock = 0;
			Object[] nextBlockVal = null;
			if (lastBlock > 0) {
				seek(blocks[0]);
				readRecord(selFields, vals);
				nextBlockVal = vals.clone();
			}
			
			int i = 1;
			while (i <= count && nextBlock < lastBlock) {
				// ȡ??һ???ο?ֵ
				Object val = values.getMem(i);
				int cmp = compareFields(val, nextBlockVal);
				if (cmp <= 0) {
					if (position() > prevEnd) {
						close();
						reopen(1024);
						seek(prevEnd);
					}
					
					while (true) {
						readRecord(selFields, vals);
						cmp = compareFields(val, vals);
						if (cmp > 0) {
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(selFields, vals);
									nextBlockVal = vals.clone();
								}
								
								break;
							}
						} else if (cmp == 0) {
							posArray.add(prevEnd);
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(selFields, vals);
									nextBlockVal = vals.clone();
								}
								
								break;
							}

							continue;
						} else {
							i++;
							while (i <= count) {
								// ȡ??һ???ο?ֵ
								val = values.getMem(i);
								cmp = compareFields(val, vals);
								if (cmp > 0) {
									break;
								} else if (cmp == 0) {
									posArray.add(prevEnd);
									break;
								} else {
									i++;
								}
							}
							
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(selFields, vals);
									nextBlockVal = vals.clone();
								}
								
								break;
							}
							
							break;
						}
					}
				} else {
					prevEnd = blocks[nextBlock];					
					nextBlock++;
					if (nextBlock < lastBlock) {
						seek(blocks[nextBlock]);
						readRecord(selFields, vals);
						nextBlockVal = vals.clone();
					}
				}
			}
			
			if (i <= count) {
				if (position() > prevEnd) {
					close();
					reopen(1024);
					seek(prevEnd);
				}
				
				Object val = values.getMem(i);
				while (i <= count && readRecord(selFields, vals)) {
					int cmp = compareFields(val, vals);
					if (cmp > 0) {
						prevEnd = position();
					} else if (cmp == 0) {
						posArray.add(prevEnd);
						prevEnd = position();
					} else {
						i++;
						while (i <= count) {
							val = values.getMem(i);
							cmp = compareFields(val, vals);
							if (cmp > 0) {
								break;
							} else if (cmp == 0) {
								posArray.add(prevEnd);
								break;
							} else {
								i++;
							}
						}
						
						prevEnd = position();
					}
				}
			}
			
			if (posArray.size() == 0) {
				//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
				return new MemoryCursor(null);
			}
						
			return new PFileCursor(file, posArray.toArray(), 1024, fields, null, ctx);
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
	}
	
	private ICursor iselectExpression(Expression exp, Sequence values, String []fields, Context ctx) {
		int count = values.length();
		if (count == 0) {
			//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
			return new MemoryCursor(null);
		}
		
		try {
			open(1024);
			long []blocks = this.blocks;
			if (blocks == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("license.fileFormatError"));
			}
			
			int lastBlock = this.lastBlock;
			int fcount = ds.getFieldCount();
			Object []vals = new Object[fcount];
			Record rec = new Record(ds);
			
			LongArray posArray = new LongArray(count > 5 ? count * 2 : 10);
			long prevEnd = position();
			int nextBlock = 0;
			Object nextBlockVal = null;
			if (lastBlock > 0) {
				seek(blocks[0]);
				readRecord(vals);
				rec.values = vals;
				nextBlockVal = rec.calc(exp, ctx);
			}
			
			int i = 1;
			while (i <= count && nextBlock < lastBlock) {
				Object val = values.getMem(i);
				int cmp = Variant.compare(val, nextBlockVal);
				if (cmp <= 0) {
					if (position() > prevEnd) {
						close();
						reopen(1024);
						seek(prevEnd);
					}
					
					while (true) {
						readRecord(vals);
						rec.values = vals;
						Object reCal = rec.calc(exp, ctx);
						cmp = Variant.compare(val, reCal);
						if (cmp > 0) {
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(vals);
									rec.values = vals;
									nextBlockVal = rec.calc(exp, ctx);
								}
								
								break;
							}
						} else if (cmp == 0) {
							posArray.add(prevEnd);
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(vals);
									rec.values = vals;
									nextBlockVal = rec.calc(exp, ctx);
								}
								
								break;
							}

							continue;
						} else {
							i++;
							while (i <= count) {
								val = values.getMem(i);
								cmp = Variant.compare(val, rec.calc(exp, ctx));
								if (cmp > 0) {
									break;
								} else if (cmp == 0) {
									posArray.add(prevEnd);
									break;
								} else {
									i++;
								}
							}
							
							prevEnd = position();
							if (prevEnd == blocks[nextBlock]) {
								nextBlock++;
								if (nextBlock < lastBlock) {
									seek(blocks[nextBlock]);
									readRecord(vals);
									rec.values = vals;
									nextBlockVal = rec.calc(exp, ctx);
								}
								
								break;
							}
							
							break;
						}
					}
				} else {
					prevEnd = blocks[nextBlock];					
					nextBlock++;
					if (nextBlock < lastBlock) {
						seek(blocks[nextBlock]);
						readRecord(vals);
						rec.values = vals;
						nextBlockVal = rec.calc(exp, ctx);
					}
				}
			}
			
			if (i <= count) {
				if (position() > prevEnd) {
					close();
					reopen(1024);
					seek(prevEnd);
				}
				
				Object val = values.getMem(i);
				while (i <= count && readRecord(vals)) {
					rec.values = vals;
					int cmp = Variant.compare(val, rec.calc(exp, ctx));
					if (cmp > 0) {
						prevEnd = position();
					} else if (cmp == 0) {
						posArray.add(prevEnd);
						prevEnd = position();
					} else {
						i++;
						while (i <= count) {
							val = values.getMem(i);
							cmp = Variant.compare(val, rec.calc(exp, ctx));
							if (cmp > 0) {
								break;
							} else if (cmp == 0) {
								posArray.add(prevEnd);
								break;
							} else {
								i++;
							}
						}
						
						prevEnd = position();
					}
				}
			}
			
			if (posArray.size() == 0) {
				//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
				return new MemoryCursor(null);
			}
			
			return new PFileCursor(file, posArray.toArray(), 1024, fields, null, ctx);
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
	}
	
	/**
	 * ????ʽ??ֵ????startVal??endVal֮??ļ?¼
	 * @param	exp			????ʽ????eΪnull, ????ҲΪnull
	 * @param	startVal	??ʼֵ
	 * @param	endVal		????ֵ
	 * @param	fields      ?????±????ֶΣ????Բ??????ο??ֶ?
	 * @param	ctx			?????ı???
	 * 
	 * @return	???ض?Ӧ???α?
	*/
	public ICursor iselect(Expression exp, Object startVal,
			Object endVal, String []fields, Context ctx) {
		if (exp == null) {
			//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
			return new MemoryCursor(null);
		}
		
		try {
			open(1024);

			if (blocks == null) {
				// ???ֶμ??ļ?????˳?????
				Sequence result = readAll();
				Sequence values = result.calc(exp, ctx);
				int len = values.length();
				int start = -1;
				for (int i = 1; i <= len; ++i) {
					if (Variant.compare(values.getMem(i), startVal) >= 0) {
						start = i;
						break;
					}
				}
				
				if (start == -1) {
					return new MemoryCursor(null);
				}
				
				int end = -1;
				for (int i = len; i >= 1; --i) {
					if (Variant.compare(values.getMem(i), endVal) <= 0) {
						end = i;
						break;
					}
				}
				
				if (end < start) {
					return new MemoryCursor(null);
				}

				MemoryCursor cs = new MemoryCursor(result, start, end + 1);
				if (fields != null) {
					int fcount = fields.length;
					Expression []exps = new Expression[fcount];
					for (int f = 0; f < fcount; ++f) {
						exps[f] = new Expression(fields[f]);
					}
					
					cs.newTable(null, exps, fields, null, ctx);
				}
				
				return cs;
			}
		} catch (IOException e) {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("file.fileNoExist", file.getFileName()));
		}

		// ???ֶα???ʽ????????????̣????Դ?????Ч??
		//  ???????ʽ?Ƿ?ʽ???ַ???
		String[] fieldNames = exp.toFields();
		if (null != fieldNames) {
			boolean multi = true;
			// ?ж??Ƿ?ʽ???ֶ?
			loop:for (int i = 0; i < fieldNames.length; i++) {
				for (int j = 0; j < ds.getFieldCount(); j ++) {
					if (fieldNames[i].equals(ds.getFieldName(j)))
						continue loop;
				}
				
				multi = false;
				break;
			}
			
			if (multi) {
				return iselectFields(fieldNames, startVal, endVal, fields, ctx);
			}
		}
		
		// ????ͨ??????
		
		return iselectExpression(exp, startVal, endVal, fields, ctx);
	}
	/**
	 * ???ֶΡ????ֶ?ֵ????startVal??endVal֮??ļ?¼
	 * 
	 * @param	refFields	?ο??ֶ?
	 * @param	startVal	??ʼֵ
	 * @param	endVal		????ֵ
	 * @param	fields      ?????±????ֶΣ????Բ??????ο??ֶ?
	 * @param	ctx			?????ı???
	 * 
	 * @return	???ض?Ӧ???α?
	*/
	private ICursor iselectFields(String[] refFields, Object startVal, Object endVal, String []fields, Context ctx) {
		int startBlock;
		int endBlock ;
		long firstPos;
		Object[] vals = null; // ??ȡ?ļ?¼????,?????ǵ??ֶλ???ֶ?
		int fcount = ds.getFieldCount();
		int[] selFields = new int[fcount]; // Ҫ??ȡ???ֶ?
		
		// ???Ҷ?Ӧ?е?????
		for (int i = 0; i < fcount; i++) {
			selFields[i] = -1;
		}

		int fcou = 0;
		for (int i = 0; i < refFields.length; i++) {
			int index = ds.getFieldIndex(refFields[i]);
			if (0 > index ) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(refFields[i] + mm.getMessage("ds.fieldNotExist"));
			}
			selFields[index] = fcou;
			fcou++;
		}
				
		try {
			open(1024);
			firstPos = position();
			long []blocks = this.blocks;
			if (blocks == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("license.fileFormatError"));
			}
			
			int lastBlock = this.lastBlock;
			startBlock = lastBlock;
			endBlock = lastBlock;
			vals = new Object[fcou];
			
			for (int i = 0; i < lastBlock; ++i) {
				seek(blocks[i]);
				readRecord(selFields, vals);
				if (compareFields(vals, startVal) >= 0) {
					startBlock = i;
					if (endVal != null && compareFields(vals, endVal) > 0) {
						endBlock = i;
					}
					
					break;
				}
			}
			
			if (endVal != null && endBlock != startBlock) {
				for (int i = startBlock + 1; i < lastBlock; ++i) {
					seek(blocks[i]);
					readRecord(selFields, vals);
					if (compareFields(vals, endVal) > 0) {
						endBlock = i;
						break;
					}
				}
			}
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
		
		try {
			reopen(1024);
			seek(firstPos);
			
			long []blocks = this.blocks;
			long startPos = blocks[startBlock];
			
			if (startBlock > 0) {
				seek(blocks[startBlock - 1]);
			}
			
			long pos = firstPos;
			while (pos < startPos) {
				readRecord(selFields, vals);
				if (compareFields(vals, startVal) >= 0) {
					if (endVal != null && compareFields(vals, endVal) > 0) {
						//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
						return new MemoryCursor(null);
					}
					
					startPos = pos;
					break;
				}
				
				pos = position();
			}
			
			long endPos = blocks[endBlock];
			if (endVal != null) {
				if (endBlock > 0 && position() < blocks[endBlock - 1]) {
					seek(blocks[endBlock - 1]);
				}
				
				pos = position();
				while (pos < endPos) {
					readRecord(selFields, vals);
					if (compareFields(vals, endVal) > 0) {
						endPos = pos;
						break;
					}
					
					pos = position();
				}
			}
			
			if (startPos < endPos) {
				BFileCursor cursor = new BFileCursor(file, fields, null, ctx);
				cursor.setPosRange(startPos, endPos);
				return cursor;
			} else {
				//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
				return new MemoryCursor(null);
			}
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
	}
	
	/**
	 * ????ʽ????startVal??endVal֮??ļ?¼
	 * 
	 * @param	e			???????ʽ
	 * @param	startVal	??ʼֵ
	 * @param	endVal		????ֵ
	 * @param	fields      ?????±????ֶΣ????Բ??????ο??ֶ?
	 * @param	ctx			?????ı???
	 * 
	 * @return	???ض?Ӧ???α?
	*/
	private ICursor iselectExpression(Expression exp, Object startVal, Object endVal, String []fields, Context ctx) {
		int startBlock;
		int endBlock ;
		long firstPos;
		Object[] vals = null; // ??ȡ?ļ?¼????,?????ǵ??ֶλ???ֶ?
		Record rec = new Record(ds);
		
		// ????ʼֵ???Ƚ?
		try {
			open(1024);
			firstPos = position();
			long []blocks = this.blocks;
			if (blocks == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("license.fileFormatError"));
			}
			
			int lastBlock = this.lastBlock;
			startBlock = lastBlock;
			endBlock = lastBlock;
			vals = new Object[ds.getFieldCount()];
			
			for (int i = 0; i < lastBlock; ++i) {
				seek(blocks[i]);
				readRecord(vals);
				rec.values = vals;
				if (Variant.compare(rec.calc(exp, ctx), startVal) >= 0) {
					startBlock = i;
					if (endVal != null && Variant.compare(rec.calc(exp, ctx), endVal) > 0) {
						endBlock = i;
					}
					
					break;
				}
			}
			
			if (endVal != null && endBlock != startBlock) {
				for (int i = startBlock + 1; i < lastBlock; ++i) {
					seek(blocks[i]);
					readRecord(vals);
					rec.values = vals;
					if (Variant.compare(rec.calc(exp, ctx), endVal) > 0) {
						endBlock = i;
						break;
					}
				}
			}
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
		
		// ?????ֵ???Ƚ?
		try {
			reopen(1024);
			seek(firstPos);
			
			long []blocks = this.blocks;
			long startPos = blocks[startBlock];
			
			if (startBlock > 0) {
				seek(blocks[startBlock - 1]);
			}
			
			long pos = firstPos;
			while (pos < startPos) {
				readRecord(vals);
				rec.values = vals;
				if (Variant.compare(rec.calc(exp, ctx), startVal) >= 0) {
					if (endVal != null && Variant.compare(rec.calc(exp, ctx), endVal) > 0) {
						//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
						return new MemoryCursor(null);
					}
					
					startPos = pos;
					break;
				}
				
				pos = position();
			}
			
			long endPos = blocks[endBlock];
			if (endVal != null) {
				if (endBlock > 0 && position() < blocks[endBlock - 1]) {
					seek(blocks[endBlock - 1]);
				}
				
				pos = position();
				while (pos < endPos) {
					readRecord(vals);
					rec.values = vals;
					if (Variant.compare(rec.calc(exp, ctx), endVal) > 0) {
						endPos = pos;
						break;
					}
					
					pos = position();
				}
			}
			
			if (startPos < endPos) {
				BFileCursor cursor = new BFileCursor(file, fields, null, ctx);
				cursor.setPosRange(startPos, endPos);
				return cursor;
			} else {
				//return null; ?ijɷ??ؿ??α꣬????cs.groups@t?᷵?ؿ????
				return new MemoryCursor(null);
			}
		} catch (IOException e) {
			throw new RQException(e);
		} finally {
			try {
				close();
			} catch (IOException e) {
			}
		}
	}
	
	/**
	 * ????n???طֶε?ֵ??ÿ??????
	 * @param list ???ص?ÿ??????
	 * @param values ???طֶε?ֵ
	 * @param n ??????ÿ??????
	 * @throws IOException 
	 */
	public void getSegmentInfo(ArrayList list, Sequence values, int n) throws IOException {
		open();
		long []blocks = this.blocks;
		if (blocks == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("license.fileFormatError"));
		}
		
		int blockCount = lastBlock + 1;
		long blockRecordCount = this.blockRecordCount;
		int sum = (int) blockRecordCount;
		int colCount = readFields.length;
		
		for (int i = 1; i < blockCount; ++i) {
			if (sum + blockRecordCount > n) {
				list.add(sum);
				sum = (int) blockRecordCount;
				seek(blocks[i - 1]);
				Object []vals = new Object[colCount];
				readRecord(readIndex, vals);
				values.add(vals);
			} else {
				sum += blockRecordCount;
			}
		}
		
		list.add(sum);//???һ???ֶ????????п???ֻ????һ??
		close();
	}
	
	public int[] getReadIndex() {
		return readIndex;
	}
	
	public ObjectReader getImporter() {
		return importer;
	}
	
	public long getFirstRecordPos() {
		return firstRecordPos;
	}
	
	public long[] getBlocks() {
		return blocks;
	}

	public int getLastBlock() {
		return lastBlock;
	}
	
	public long getTotalRecordCount() {
		return totalRecordCount;
	}
	
	public DataStruct getDataStruct() {
		return ds;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy