Demo

package me.xuzs.db; import java.io.BufferedWriter; 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.List; public class FileDb { private static String FILE_ROOT = "D:/filedb/"; private static String FILE_EXT = ".txt"; private static int PAGE_SIZE = 10; public static void main(String[] args) { int limit = 25; int offset = 1; // int totalCount = queryCountByField("user"); // System.out.println("记录总数: " + totalCount); List<String> dataList = queryList("other", limit, offset); // System.out.println("limit: " + limit + ", offset: " + offset); System.out.println(dataList); // insertData("other", dataList); } /** * 根据字段名查询数据所在路径 * * @param create * @return */ public 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("字段不存在!"); } filePath.mkdir(); } return filePath; } /** * 返回指定记录的条数 * * @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; Arrays.sort(fileNames); // 最新文件的文件名 String lastFilePath = filePath.getAbsolutePath() + File.separator + fileNames[fileCount - 1]; totalRecord += PAGE_SIZE * (fileCount - 1); totalRecord += queryCountInFile(lastFilePath); return totalRecord; } /** * 查询当前文件中有几条记录 * * @param fileName * @return */ public 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 查询到的行数 */ public static int queryListInFile(String fileStr, int limit, int offset, List<String> contentList) { int addedCount = 0; try { RandomAccessFile file = new RandomAccessFile(fileStr, "r"); skipLine(file, offset); for (int i = 0; i < limit; i++) { String content = file.readLine(); if (content == null) { System.err.println("超过记录总数!"); break; } contentList.add(content); addedCount++; } } catch (FileNotFoundException e) { e.printStackTrace(); return 1; } catch (IOException e) { e.printStackTrace(); return 1; } return addedCount; } 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; // 记录条数 int recordLimit = 0; if(limit - offset + recordOffset < PAGE_SIZE){ recordLimit = limit; } else recordLimit = PAGE_SIZE - recordOffset; String toReadFileStr = ""; // 首先查询一把 toReadFileStr = field + "_" + fileIndex + FILE_EXT; limit -= queryListInFile(filePath.getAbsolutePath() + File.separator + toReadFileStr, recordLimit, recordOffset, contentList); fileIndex++; // 循环寻找下一个文件 while (limit / PAGE_SIZE > 0) { toReadFileStr = field + "_" + fileIndex + FILE_EXT; limit -= queryListInFile(filePath.getAbsolutePath() + File.separator + toReadFileStr, PAGE_SIZE, 0, contentList); fileIndex++; } toReadFileStr = field + "_" + fileIndex + FILE_EXT; limit -= queryListInFile(filePath.getAbsolutePath() + File.separator + toReadFileStr, limit, 0, contentList); return contentList; } /** * 跳过指定文件的指定行数 * * @param file * @param lineCount * @return */ public 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; } 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 { Arrays.sort(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 + "\n"); 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 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 + "_" + fileCount + FILE_EXT); try { toCreate.createNewFile(); } catch (IOException e) { e.printStackTrace(); } return toCreate; } }

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); } }); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律