package me.xuzs.db;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class FileDb {
public static final String NEXT_LINE = System.getProperty("line.separator");
private static String FILE_ROOT = "D:/filedb/";
private static String FILE_EXT = ".txt";
private static String CONNECT_CHAR = "_";
private static int PAGE_SIZE = 50;
public static void main(String[] args) {
String field = "user";
// init(field, 2000);
int limit = 2;
int offset = 4;
int totalCount = queryCountByField(field);
System.out.println("记录总数: " + totalCount);
List<String> dataList = queryList(field, limit, offset);
System.out.println("limit: " + limit + ", offset: " + offset);
System.out.println(dataList);
}
/**
* 初始化字段
* @param field
* @param count
*/
public static void init(String field, int count){
List<String> dataList = new ArrayList<String>(PAGE_SIZE);
for (int i = 1; i <= count; i++) {
dataList.add(String.valueOf(i));
}
insertData(field, dataList);
}
/**
* 插入数据到文件
* @param field
* @param dataList
* @return
*/
public static boolean insertData(String field, List<String> dataList) {
File filePath = queryFilePathByFieldName(field, true);
String[] fileNames = filePath.list();
int fileCount = fileNames.length;
String fileNameStr = "";
File toInsert = null;
if (fileCount < 1) {
toInsert = createFile(field);
} else {
sortFile(fileNames);
fileNameStr = fileNames[fileCount - 1];
toInsert = new File(filePath.getAbsolutePath() + File.separator
+ fileNameStr);
}
int recordCount = queryCountInFile(toInsert.getAbsolutePath());
int recorded = 0;
try {
FileWriter fileWriter = new FileWriter(toInsert, true);
for (String data : dataList) {
fileWriter.append(data + NEXT_LINE);
recorded++;
if (recorded + recordCount == PAGE_SIZE) {
toInsert = createFile(field);
fileWriter.flush();
fileWriter = new FileWriter(toInsert, true);
recorded = 0;
recordCount = 0;
}
}
fileWriter.flush();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 返回指定记录的条数
*
* @param field
* @return
*/
public static int queryCountByField(String field) {
int totalRecord = 0;
File filePath = queryFilePathByFieldName(field, false);
String[] fileNames = filePath.list();
int fileCount = fileNames.length;
sortFile(fileNames);
// 最新文件的文件名
String lastFilePath = filePath.getAbsolutePath() + File.separator
+ fileNames[fileCount - 1];
totalRecord += PAGE_SIZE * (fileCount - 1);
totalRecord += queryCountInFile(lastFilePath);
return totalRecord;
}
/**
* 根据字段名查询结果列表
* @param field
* @param limit
* @param offset
* @return
*/
public static List<String> queryList(String field, int limit, int offset) {
List<String> contentList = new ArrayList<String>(PAGE_SIZE);
File filePath = queryFilePathByFieldName(field, false);
// 文件偏移量
int fileIndex = offset / PAGE_SIZE;
// 记录偏移量
int recordOffset = offset % PAGE_SIZE;
String toReadFileStr = "";
// 执行查询
toReadFileStr = field + CONNECT_CHAR + fileIndex + FILE_EXT;
queryListInFile(filePath.getAbsolutePath() + File.separator
+ toReadFileStr, limit, recordOffset, contentList);
return contentList;
}
/**
* 根据字段名查询数据所在路径
*
* @param create
* @return
*/
private static File queryFilePathByFieldName(String field, boolean create) {
String filePathStr = FILE_ROOT + field + File.separator;
File filePath = new File(filePathStr);
if (!filePath.exists() || !filePath.isDirectory()) {
if (!create) {
throw new IllegalArgumentException("记录不存在!");
}
if(!filePath.mkdirs()){
throw new IllegalArgumentException("文件创建失败!");
};
}
return filePath;
}
/**
* 查询当前文件中有几条记录
*
* @param fileName
* @return
*/
private static int queryCountInFile(String fileStr) {
int count = 0;
try {
RandomAccessFile file = new RandomAccessFile(fileStr, "r");
while (file.readLine() != null) {
count++;
}
} catch (IOException e) {
e.printStackTrace();
}
return count;
}
/**
* 查询指定文件中的指定记录
*
* @param fileStr 文件全路径
* @param limit 查询条数
* @param offset 查询偏移量
* @param contentList 查询后结果存入
* @return 查询结果
*/
private static int queryListInFile(String fileStr, int limit, int offset,
List<String> contentList) {
RandomAccessFile file = null;
try {
file = new RandomAccessFile(fileStr, "r");
} catch (FileNotFoundException e) {
System.err.println("没有记录了!");
return -1;
}
if(offset>0){
skipLine(file, offset);
}
int added = 0;
while (limit > 0) {
String content = "";
try {
content = file.readLine();
} catch (IOException e) {
e.printStackTrace();
}
if (content == null) {
System.err.println("超过记录总数,还差" + limit);
break;
}
contentList.add(content);
added++;
limit--;
if((added + offset) == PAGE_SIZE){
String fileIdexStr = fileStr.substring(fileStr.lastIndexOf(CONNECT_CHAR) + 1, fileStr.lastIndexOf(FILE_EXT));
int newFileIdex = Integer.parseInt(fileIdexStr) + 1;
String newFileStr = fileStr.replace(fileIdexStr + FILE_EXT, newFileIdex + FILE_EXT);
return queryListInFile(newFileStr, limit, 0, contentList);
}
}
return 1;
}
/**
* 跳过指定文件的指定行数
* @param file
* @param lineCount
* @return
*/
private static boolean skipLine(RandomAccessFile file, int lineCount) {
boolean success = true;
for (int i = 0; i < lineCount; i++) {
try {
file.readLine();
} catch (IOException e) {
e.printStackTrace();
success = false;
}
}
return success;
}
/**
* 创建文件
* @param filePathStr
* @param fileNameStr
* @return
*/
private static File createFile(String fieldName) {
File filePath = queryFilePathByFieldName(fieldName, false);
String[] fileNames = filePath.list();
int fileCount = fileNames.length;
File toCreate = new File(filePath.getAbsolutePath() + File.separator
+ fieldName + CONNECT_CHAR + fileCount + FILE_EXT);
try {
toCreate.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return toCreate;
}
/**
* 排序文件名
* @param fileNames
*/
private static void sortFile(final String[] fileNames){
Arrays.sort(fileNames, new Comparator<String>(){
@Override
public int compare(final String s1, final String s2) {
if(s1.length() != s2.length()){
if(s1.length()>s2.length()){
return 1;
}
return -1;
}
return s1.compareTo(s2);
}
});
}
}