是需要在代码中输入的版本下面还有JFrame的窗口工具版本import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.regex.Pattern; import java.util.regex.Matcher; public class TxtUtils { // 章节正则表达式匹配 第1章、第100章 等格式 private static final String CHAPTER_REGEX 第[0-9]章; private static final Pattern CHAPTER_PATTERN Pattern.compile(CHAPTER_REGEX); /** * 分割小说文件 * param inputFile 输入文件路径 * param outputDir 输出目录 * param chapterRanges 章节范围列表如 1-10, 35-45 * param charset 文件编码 */ public static void splitNovel(String inputFile, String outputDir, ListString chapterRanges, Charset charset) { try { // 创建输出目录 File outputDirectory new File(outputDir); if (!outputDirectory.exists()) { outputDirectory.mkdirs(); } // 读取整个文件 ListString allLines readFile(inputFile, charset); // 解析所有章节的位置 MapInteger, ChapterInfo chapters findChapters(allLines); if (chapters.isEmpty()) { System.out.println(未找到任何章节请确认文件格式是否正确。); return; } System.out.println(总共找到 chapters.size() 个章节); // 处理每个章节范围 for (String range : chapterRanges) { processChapterRange(range.trim(), chapters, allLines, outputDir); } System.out.println(分割完成); } catch (IOException e) { System.err.println(处理文件时出错: e.getMessage()); e.printStackTrace(); } } /** * 读取文件内容 */ private static ListString readFile(String filePath, Charset charset) throws IOException { ListString lines new ArrayList(); try (BufferedReader reader new BufferedReader( new InputStreamReader(new FileInputStream(filePath), charset))) { String line; while ((line reader.readLine()) ! null) { lines.add(line); } } return lines; } /** * 查找所有章节的位置 */ private static MapInteger, ChapterInfo findChapters(ListString lines) { MapInteger, ChapterInfo chapters new TreeMap(); for (int i 0; i lines.size(); i) { String line lines.get(i); Matcher matcher CHAPTER_PATTERN.matcher(line); if (matcher.find()) { String chapterStr matcher.group(); int chapterNum extractChapterNumber(chapterStr); if (chapterNum 0) { ChapterInfo info new ChapterInfo(); info.chapterNum chapterNum; info.chapterTitle line.trim(); info.startLine i; chapters.put(chapterNum, info); } } } return chapters; } /** * 从章节字符串中提取数字 */ private static int extractChapterNumber(String chapterStr) { try { String numStr chapterStr.replaceAll([^0-9], ); return Integer.parseInt(numStr); } catch (NumberFormatException e) { return -1; } } /** * 处理单个章节范围 */ private static void processChapterRange(String range, MapInteger, ChapterInfo chapters, ListString allLines, String outputDir) throws IOException { String[] parts range.split(-); if (parts.length ! 2) { System.out.println(无效的章节范围: range); return; } try { int startChapter Integer.parseInt(parts[0].trim()); int endChapter Integer.parseInt(parts[1].trim()); if (startChapter endChapter) { System.out.println(起始章节不能大于结束章节: range); return; } // 获取章节信息 ChapterInfo startInfo chapters.get(startChapter); ChapterInfo endInfo chapters.get(endChapter); if (startInfo null) { System.out.println(未找到第 startChapter 章); return; } if (endInfo null) { System.out.println(未找到第 endChapter 章); return; } // 确定结束位置下一章的开始或文件末尾 int endLine; Integer nextChapter getNextChapter(chapters, endChapter); if (nextChapter ! null) { endLine chapters.get(nextChapter).startLine - 1; } else { endLine allLines.size() - 1; } // 提取章节内容 ListString content allLines.subList(startInfo.startLine, endLine 1); // 生成输出文件名 String outputFileName String.format(%s-%s.txt, formatChapterNumber(startChapter), formatChapterNumber(endChapter)); String outputPath outputDir File.separator outputFileName; // 写入文件 writeToFile(content, outputPath, StandardCharsets.UTF_8); System.out.println(已生成: outputFileName (第 startChapter 章 - 第 endChapter 章)); } catch (NumberFormatException e) { System.out.println(章节范围格式错误: range 正确格式如1-10); } } /** * 格式化章节号保持两位数显示 */ private static String formatChapterNumber(int chapterNum) { return String.format(%02d, chapterNum); } /** * 获取指定章节的下一个章节号 */ private static Integer getNextChapter(MapInteger, ChapterInfo chapters, int currentChapter) { TreeMapInteger, ChapterInfo sortedChapters new TreeMap(chapters); Integer next null; for (Integer chapter : sortedChapters.keySet()) { if (chapter currentChapter) { next chapter; break; } } return next; } /** * 写入文件 */ private static void writeToFile(ListString content, String filePath, Charset charset) throws IOException { try (BufferedWriter writer new BufferedWriter( new OutputStreamWriter(new FileOutputStream(filePath), charset))) { for (String line : content) { writer.write(line); writer.newLine(); } } } /** * 章节信息类 */ private static class ChapterInfo { int chapterNum; String chapterTitle; int startLine; } /** * 主方法 - 使用示例 */ public static void main(String[] args) { // 使用示例 String inputFile F:\\360极速浏览器下载\\111\\2621302.txt; // 修改为你的文件路径 String outputDir F:\\360极速浏览器下载\\111\\output; // 修改为输出目录 // 指定要分割的章节范围 ListString chapterRanges Arrays.asList( 1-10, // 第1章到第10章 35-45, // 第35章到第45章 50-55 // 第50章到第55章 ); // 执行分割使用UTF-8编码 splitNovel(inputFile, outputDir, chapterRanges, StandardCharsets.UTF_8); // 如果文件是GBK编码可以使用 // splitNovel(inputFile, outputDir, chapterRanges, Charset.forName(GBK)); } }效果如图如果章节标题格式有所不同修改正则表达式以匹配即可。然后我直接改了一个窗口化工具版本的用起来更方便效果如图package com.qs; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; public class TxtSplitterGUI extends JFrame { private JTextField txtFilePathField; private JTextField outputDirField; private JTextArea chapterRangesArea; private JComboBoxString charsetComboBox; private JTextArea logArea; private JButton selectFileBtn; private JButton selectOutputDirBtn; private JButton splitBtn; private JButton addRangeBtn; private JButton clearRangesBtn; private JListString rangesList; private DefaultListModelString rangesListModel; // 新增每份章节数输入框 private JTextField chaptersPerFileField; private JCheckBox enableChaptersPerFileCheckBox; // 章节正则表达式匹配 第1章、第100章 等格式 private static final String CHAPTER_REGEX 第[0-9]章; private static final Pattern CHAPTER_PATTERN Pattern.compile(CHAPTER_REGEX); public TxtSplitterGUI() { initUI(); setTitle(TXT小说分割工具); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(850, 650); setLocationRelativeTo(null); } private void initUI() { // 创建主面板 JPanel mainPanel new JPanel(new BorderLayout(10, 10)); mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // 创建输入面板 JPanel inputPanel createInputPanel(); // 创建分割选项面板新增 JPanel splitOptionPanel createSplitOptionPanel(); // 创建章节范围面板 JPanel rangePanel createRangePanel(); // 创建日志面板 JPanel logPanel createLogPanel(); // 创建按钮面板 JPanel buttonPanel createButtonPanel(); // 组装面板 JPanel topPanel new JPanel(new BorderLayout(5, 5)); JPanel inputAndOptionPanel new JPanel(new BorderLayout(5, 5)); inputAndOptionPanel.add(inputPanel, BorderLayout.NORTH); inputAndOptionPanel.add(splitOptionPanel, BorderLayout.CENTER); topPanel.add(inputAndOptionPanel, BorderLayout.NORTH); topPanel.add(rangePanel, BorderLayout.CENTER); mainPanel.add(topPanel, BorderLayout.NORTH); mainPanel.add(logPanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.SOUTH); add(mainPanel); } private JPanel createInputPanel() { JPanel panel new JPanel(new GridBagLayout()); panel.setBorder(BorderFactory.createTitledBorder(文件设置)); GridBagConstraints gbc new GridBagConstraints(); gbc.fill GridBagConstraints.HORIZONTAL; gbc.insets new Insets(5, 5, 5, 5); // 文件选择行 gbc.gridx 0; gbc.gridy 0; gbc.weightx 0; panel.add(new JLabel(TXT文件:), gbc); txtFilePathField new JTextField(); txtFilePathField.setEditable(false); gbc.gridx 1; gbc.weightx 1; panel.add(txtFilePathField, gbc); selectFileBtn new JButton(选择文件); gbc.gridx 2; gbc.weightx 0; panel.add(selectFileBtn, gbc); // 输出目录行 gbc.gridx 0; gbc.gridy 1; gbc.weightx 0; panel.add(new JLabel(输出目录:), gbc); outputDirField new JTextField(); outputDirField.setEditable(false); gbc.gridx 1; gbc.weightx 1; panel.add(outputDirField, gbc); selectOutputDirBtn new JButton(选择目录); gbc.gridx 2; gbc.weightx 0; panel.add(selectOutputDirBtn, gbc); // 编码选择行 gbc.gridx 0; gbc.gridy 2; gbc.weightx 0; panel.add(new JLabel(文件编码:), gbc); String[] charsets {UTF-8, GBK, GB2312, ISO-8859-1}; charsetComboBox new JComboBox(charsets); charsetComboBox.setSelectedIndex(0); gbc.gridx 1; gbc.weightx 1; panel.add(charsetComboBox, gbc); return panel; } /** * 新增创建分割选项面板 */ private JPanel createSplitOptionPanel() { JPanel panel new JPanel(new FlowLayout(FlowLayout.LEFT)); panel.setBorder(BorderFactory.createTitledBorder(分割选项)); enableChaptersPerFileCheckBox new JCheckBox(按指定章节数分割); enableChaptersPerFileCheckBox.addActionListener(e - { chaptersPerFileField.setEnabled(enableChaptersPerFileCheckBox.isSelected()); }); panel.add(enableChaptersPerFileCheckBox); panel.add(new JLabel(每份章节数:)); chaptersPerFileField new JTextField(5); chaptersPerFileField.setEnabled(false); chaptersPerFileField.setToolTipText(输入正整数例如10表示每10章一个文件); panel.add(chaptersPerFileField); JLabel exampleLabel new JLabel((示例: 100-150每10章一个文件)); exampleLabel.setForeground(Color.GRAY); exampleLabel.setFont(exampleLabel.getFont().deriveFont(Font.PLAIN, 11f)); panel.add(exampleLabel); return panel; } private JPanel createRangePanel() { JPanel panel new JPanel(new BorderLayout(5, 5)); panel.setBorder(BorderFactory.createTitledBorder(章节范围设置)); // 左侧范围输入区域 JPanel leftPanel new JPanel(new BorderLayout(5, 5)); JPanel inputRangePanel new JPanel(new FlowLayout(FlowLayout.LEFT)); inputRangePanel.add(new JLabel(章节范围:)); chapterRangesArea new JTextArea(3, 20); chapterRangesArea.setLineWrap(true); JScrollPane rangeScroll new JScrollPane(chapterRangesArea); rangeScroll.setPreferredSize(new Dimension(200, 60)); inputRangePanel.add(rangeScroll); JPanel rangeButtonPanel new JPanel(new GridLayout(2, 1, 5, 5)); addRangeBtn new JButton(添加范围); clearRangesBtn new JButton(清空); rangeButtonPanel.add(addRangeBtn); rangeButtonPanel.add(clearRangesBtn); inputRangePanel.add(rangeButtonPanel); leftPanel.add(inputRangePanel, BorderLayout.NORTH); // 右侧已添加范围列表 JPanel rightPanel new JPanel(new BorderLayout(5, 5)); rightPanel.add(new JLabel(已添加的范围:), BorderLayout.NORTH); rangesListModel new DefaultListModel(); rangesList new JList(rangesListModel); JScrollPane listScroll new JScrollPane(rangesList); listScroll.setPreferredSize(new Dimension(150, 100)); rightPanel.add(listScroll, BorderLayout.CENTER); JButton removeSelectedBtn new JButton(删除选中); rightPanel.add(removeSelectedBtn, BorderLayout.SOUTH); // 添加示例提示 JLabel exampleLabel new JLabel(示例: 1-10, 35-45, 50-55 (每行一个范围)); exampleLabel.setForeground(Color.GRAY); exampleLabel.setFont(exampleLabel.getFont().deriveFont(Font.PLAIN, 11f)); panel.add(leftPanel, BorderLayout.CENTER); panel.add(rightPanel, BorderLayout.EAST); panel.add(exampleLabel, BorderLayout.SOUTH); // 添加按钮事件 addRangeBtn.addActionListener(e - addRange()); clearRangesBtn.addActionListener(e - clearRanges()); removeSelectedBtn.addActionListener(e - removeSelectedRange()); return panel; } private JPanel createLogPanel() { JPanel panel new JPanel(new BorderLayout(5, 5)); panel.setBorder(BorderFactory.createTitledBorder(运行日志)); logArea new JTextArea(); logArea.setEditable(false); logArea.setFont(new Font(Monospaced, Font.PLAIN, 12)); JScrollPane scrollPane new JScrollPane(logArea); panel.add(scrollPane, BorderLayout.CENTER); return panel; } private JPanel createButtonPanel() { JPanel panel new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5)); splitBtn new JButton(开始分割); splitBtn.setPreferredSize(new Dimension(120, 35)); splitBtn.setBackground(new Color(70, 130, 180)); splitBtn.setForeground(Color.WHITE); splitBtn.setFont(splitBtn.getFont().deriveFont(Font.BOLD, 14f)); JButton exitBtn new JButton(退出); exitBtn.setPreferredSize(new Dimension(80, 30)); panel.add(splitBtn); panel.add(exitBtn); // 添加事件监听 selectFileBtn.addActionListener(e - selectFile()); selectOutputDirBtn.addActionListener(e - selectOutputDir()); splitBtn.addActionListener(e - startSplit()); exitBtn.addActionListener(e - System.exit(0)); return panel; } private void selectFile() { JFileChooser fileChooser new JFileChooser(); fileChooser.setFileFilter(new FileNameExtensionFilter(文本文件 (*.txt), txt)); if (fileChooser.showOpenDialog(this) JFileChooser.APPROVE_OPTION) { File selectedFile fileChooser.getSelectedFile(); txtFilePathField.setText(selectedFile.getAbsolutePath()); // 默认输出目录设为文件同级目录下的output文件夹 String defaultOutputDir selectedFile.getParent() File.separator output; outputDirField.setText(defaultOutputDir); log(已选择文件: selectedFile.getName()); log(默认输出目录: defaultOutputDir); } } private void selectOutputDir() { JFileChooser fileChooser new JFileChooser(); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); if (fileChooser.showOpenDialog(this) JFileChooser.APPROVE_OPTION) { File selectedDir fileChooser.getSelectedFile(); outputDirField.setText(selectedDir.getAbsolutePath()); log(已选择输出目录: selectedDir.getAbsolutePath()); } } private void addRange() { String range chapterRangesArea.getText().trim(); if (!range.isEmpty()) { String[] ranges range.split(\n); for (String r : ranges) { r r.trim(); if (isValidRange(r)) { rangesListModel.addElement(r); log(添加范围: r); } else { log(警告: 无效的范围格式 - r 应为如: 1-10); } } chapterRangesArea.setText(); } } private boolean isValidRange(String range) { if (range null || range.isEmpty()) return false; String[] parts range.split(-); if (parts.length ! 2) return false; try { int start Integer.parseInt(parts[0].trim()); int end Integer.parseInt(parts[1].trim()); return start 0 end 0 start end; } catch (NumberFormatException e) { return false; } } private void clearRanges() { chapterRangesArea.setText(); } private void removeSelectedRange() { int selectedIndex rangesList.getSelectedIndex(); if (selectedIndex ! -1) { String removed rangesListModel.remove(selectedIndex); log(删除范围: removed); } } private void log(String message) { SwingUtilities.invokeLater(() - { logArea.append(message \n); // 自动滚动到底部 logArea.setCaretPosition(logArea.getDocument().getLength()); }); } private void startSplit() { String inputFile txtFilePathField.getText(); String outputDir outputDirField.getText(); if (inputFile.isEmpty()) { JOptionPane.showMessageDialog(this, 请选择TXT文件, 提示, JOptionPane.WARNING_MESSAGE); return; } if (outputDir.isEmpty()) { JOptionPane.showMessageDialog(this, 请设置输出目录, 提示, JOptionPane.WARNING_MESSAGE); return; } if (rangesListModel.isEmpty()) { JOptionPane.showMessageDialog(this, 请添加至少一个章节范围, 提示, JOptionPane.WARNING_MESSAGE); return; } // 检查按章节数分割选项 Integer chaptersPerFile null; if (enableChaptersPerFileCheckBox.isSelected()) { try { chaptersPerFile Integer.parseInt(chaptersPerFileField.getText().trim()); if (chaptersPerFile 0) { JOptionPane.showMessageDialog(this, 每份章节数必须为正整数, 提示, JOptionPane.WARNING_MESSAGE); return; } } catch (NumberFormatException e) { JOptionPane.showMessageDialog(this, 请输入有效的每份章节数, 提示, JOptionPane.WARNING_MESSAGE); return; } } // 收集所有范围 ListString chapterRanges new ArrayList(); for (int i 0; i rangesListModel.size(); i) { chapterRanges.add(rangesListModel.get(i)); } // 获取编码 String charsetName (String) charsetComboBox.getSelectedItem(); Charset charset; if (GBK.equals(charsetName) || GB2312.equals(charsetName)) { charset Charset.forName(charsetName); } else { charset StandardCharsets.UTF_8; } // 在后台线程执行分割任务 log( 开始分割 ); log(输入文件: inputFile); log(输出目录: outputDir); log(编码: charsetName); if (chaptersPerFile ! null) { log(分割模式: 每 chaptersPerFile 章一个文件); } else { log(分割模式: 按原范围整体分割); } log(章节范围: chapterRanges); splitBtn.setEnabled(false); final Integer finalChaptersPerFile chaptersPerFile; SwingWorkerVoid, String worker new SwingWorker() { Override protected Void doInBackground() throws Exception { try { splitNovel(inputFile, outputDir, chapterRanges, charset, finalChaptersPerFile); } catch (Exception e) { publish(错误: e.getMessage()); e.printStackTrace(); } return null; } Override protected void process(ListString chunks) { for (String message : chunks) { log(message); } } Override protected void done() { log( 分割完成 \n); splitBtn.setEnabled(true); } }; worker.execute(); } /** * 分割小说文件修改后的方法 */ private void splitNovel(String inputFile, String outputDir, ListString chapterRanges, Charset charset, Integer chaptersPerFile) throws IOException { // 创建输出目录 File outputDirectory new File(outputDir); if (!outputDirectory.exists()) { outputDirectory.mkdirs(); } // 读取整个文件 ListString allLines readFile(inputFile, charset); // 解析所有章节的位置 MapInteger, ChapterInfo chapters findChapters(allLines); if (chapters.isEmpty()) { publish(未找到任何章节请确认文件格式是否正确。); return; } publish(总共找到 chapters.size() 个章节); // 处理每个章节范围 for (String range : chapterRanges) { if (chaptersPerFile ! null chaptersPerFile 0) { // 按指定章节数分割 processChapterRangeWithSplit(range.trim(), chapters, allLines, outputDir, chaptersPerFile); } else { // 原逻辑整体分割 processChapterRange(range.trim(), chapters, allLines, outputDir); } } } /** * 读取文件内容 */ private ListString readFile(String filePath, Charset charset) throws IOException { ListString lines new ArrayList(); try (BufferedReader reader new BufferedReader( new InputStreamReader(new FileInputStream(filePath), charset))) { String line; while ((line reader.readLine()) ! null) { lines.add(line); } } return lines; } /** * 查找所有章节的位置 */ private MapInteger, ChapterInfo findChapters(ListString lines) { MapInteger, ChapterInfo chapters new TreeMap(); for (int i 0; i lines.size(); i) { String line lines.get(i); Matcher matcher CHAPTER_PATTERN.matcher(line); if (matcher.find()) { String chapterStr matcher.group(); int chapterNum extractChapterNumber(chapterStr); if (chapterNum 0) { ChapterInfo info new ChapterInfo(); info.chapterNum chapterNum; info.chapterTitle line.trim(); info.startLine i; chapters.put(chapterNum, info); } } } return chapters; } /** * 从章节字符串中提取数字 */ private int extractChapterNumber(String chapterStr) { try { String numStr chapterStr.replaceAll([^0-9], ); return Integer.parseInt(numStr); } catch (NumberFormatException e) { return -1; } } /** * 处理单个章节范围原逻辑 */ private void processChapterRange(String range, MapInteger, ChapterInfo chapters, ListString allLines, String outputDir) throws IOException { String[] parts range.split(-); if (parts.length ! 2) { publish(无效的章节范围: range); return; } try { int startChapter Integer.parseInt(parts[0].trim()); int endChapter Integer.parseInt(parts[1].trim()); if (startChapter endChapter) { publish(起始章节不能大于结束章节: range); return; } // 获取章节信息 ChapterInfo startInfo chapters.get(startChapter); ChapterInfo endInfo chapters.get(endChapter); if (startInfo null) { publish(未找到第 startChapter 章); return; } if (endInfo null) { publish(未找到第 endChapter 章); return; } // 确定结束位置下一章的开始或文件末尾 int endLine; Integer nextChapter getNextChapter(chapters, endChapter); if (nextChapter ! null) { endLine chapters.get(nextChapter).startLine - 1; } else { endLine allLines.size() - 1; } // 提取章节内容 ListString content allLines.subList(startInfo.startLine, endLine 1); // 生成输出文件名 String outputFileName String.format(%s-%s.txt, formatChapterNumber(startChapter), formatChapterNumber(endChapter)); String outputPath outputDir File.separator outputFileName; // 写入文件 writeToFile(content, outputPath, StandardCharsets.UTF_8); publish(已生成: outputFileName (第 startChapter 章 - 第 endChapter 章)); } catch (NumberFormatException e) { publish(章节范围格式错误: range 正确格式如1-10); } } /** * 新增按指定章节数分割范围 */ private void processChapterRangeWithSplit(String range, MapInteger, ChapterInfo chapters, ListString allLines, String outputDir, int chaptersPerFile) throws IOException { String[] parts range.split(-); if (parts.length ! 2) { publish(无效的章节范围: range); return; } try { int startChapter Integer.parseInt(parts[0].trim()); int endChapter Integer.parseInt(parts[1].trim()); if (startChapter endChapter) { publish(起始章节不能大于结束章节: range); return; } // 验证起始和结束章节是否存在 ChapterInfo startInfo chapters.get(startChapter); ChapterInfo endInfo chapters.get(endChapter); if (startInfo null) { publish(未找到第 startChapter 章); return; } if (endInfo null) { publish(未找到第 endChapter 章); return; } publish(开始处理范围 range 每 chaptersPerFile 章分割为一个文件); // 计算需要分割成多少份 int totalChapters endChapter - startChapter 1; int fileCount (int) Math.ceil((double) totalChapters / chaptersPerFile); for (int i 0; i fileCount; i) { int fileStartChapter startChapter i * chaptersPerFile; int fileEndChapter Math.min(fileStartChapter chaptersPerFile - 1, endChapter); // 获取起始和结束章节信息 ChapterInfo fileStartInfo chapters.get(fileStartChapter); ChapterInfo fileEndInfo chapters.get(fileEndChapter); if (fileStartInfo null || fileEndInfo null) { publish(警告: 跳过不完整的章节范围 fileStartChapter - fileEndChapter); continue; } // 确定结束位置 int fileEndLine; Integer nextChapter getNextChapter(chapters, fileEndChapter); if (nextChapter ! null) { fileEndLine chapters.get(nextChapter).startLine - 1; } else { fileEndLine allLines.size() - 1; } // 提取章节内容 ListString content allLines.subList(fileStartInfo.startLine, fileEndLine 1); // 生成输出文件名 String outputFileName String.format(%s-%s.txt, formatChapterNumber(fileStartChapter), formatChapterNumber(fileEndChapter)); String outputPath outputDir File.separator outputFileName; // 写入文件 writeToFile(content, outputPath, StandardCharsets.UTF_8); publish(已生成: outputFileName (第 fileStartChapter 章 - 第 fileEndChapter 章)); } } catch (NumberFormatException e) { publish(章节范围格式错误: range 正确格式如1-10); } } /** * 格式化章节号保持两位数显示 */ private String formatChapterNumber(int chapterNum) { return String.format(%02d, chapterNum); } /** * 获取指定章节的下一个章节号 */ private Integer getNextChapter(MapInteger, ChapterInfo chapters, int currentChapter) { TreeMapInteger, ChapterInfo sortedChapters new TreeMap(chapters); Integer next null; for (Integer chapter : sortedChapters.keySet()) { if (chapter currentChapter) { next chapter; break; } } return next; } /** * 写入文件 */ private void writeToFile(ListString content, String filePath, Charset charset) throws IOException { try (BufferedWriter writer new BufferedWriter( new OutputStreamWriter(new FileOutputStream(filePath), charset))) { for (String line : content) { writer.write(line); writer.newLine(); } } } /** * 章节信息类 */ private static class ChapterInfo { int chapterNum; String chapterTitle; int startLine; } private void publish(String message) { SwingUtilities.invokeLater(() - log(message)); } public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); } SwingUtilities.invokeLater(() - { new TxtSplitterGUI().setVisible(true); }); } }