From 81223ec95520fcaf4ffcd7d1cff7c307b2c6c32b Mon Sep 17 00:00:00 2001 From: me Date: Sat, 17 Jan 2026 19:41:41 +0300 Subject: [PATCH] upd --- README.md | 1 - file-filter/.gitignore | 39 +++ file-filter/.idea/.gitignore | 10 + file-filter/.idea/encodings.xml | 7 + file-filter/.idea/misc.xml | 14 + file-filter/.idea/vcs.xml | 6 + file-filter/dependency-reduced-pom.xml | 48 ++++ file-filter/pom.xml | 70 +++++ .../java/com/filefilter/FileFilterApp.java | 240 ++++++++++++++++++ .../com/filefilter/FileWriterManager.java | 135 ++++++++++ .../main/java/com/filefilter/Statistics.java | 112 ++++++++ 11 files changed, 681 insertions(+), 1 deletion(-) create mode 100644 file-filter/.gitignore create mode 100644 file-filter/.idea/.gitignore create mode 100644 file-filter/.idea/encodings.xml create mode 100644 file-filter/.idea/misc.xml create mode 100644 file-filter/.idea/vcs.xml create mode 100644 file-filter/dependency-reduced-pom.xml create mode 100644 file-filter/pom.xml create mode 100644 file-filter/src/main/java/com/filefilter/FileFilterApp.java create mode 100644 file-filter/src/main/java/com/filefilter/FileWriterManager.java create mode 100644 file-filter/src/main/java/com/filefilter/Statistics.java diff --git a/README.md b/README.md index bd04703..b47dd0a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ ``` file-filter-utility/ ├── pom.xml -├── README.md └── src/ └── main/ └── java/ diff --git a/file-filter/.gitignore b/file-filter/.gitignore new file mode 100644 index 0000000..480bdf5 --- /dev/null +++ b/file-filter/.gitignore @@ -0,0 +1,39 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/file-filter/.idea/.gitignore b/file-filter/.idea/.gitignore new file mode 100644 index 0000000..ab1f416 --- /dev/null +++ b/file-filter/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/file-filter/.idea/encodings.xml b/file-filter/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/file-filter/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/file-filter/.idea/misc.xml b/file-filter/.idea/misc.xml new file mode 100644 index 0000000..d2b5d0f --- /dev/null +++ b/file-filter/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/file-filter/.idea/vcs.xml b/file-filter/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/file-filter/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/file-filter/dependency-reduced-pom.xml b/file-filter/dependency-reduced-pom.xml new file mode 100644 index 0000000..16dbc8d --- /dev/null +++ b/file-filter/dependency-reduced-pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + com.filefilter + file-filter-utility + File Filter Utility + 1.0.0 + Утилита для фильтрации содержимого файлов по типам данных + + + + maven-compiler-plugin + 3.11.0 + + 11 + 11 + UTF-8 + + + + maven-shade-plugin + 3.5.1 + + + package + + shade + + + + + com.filefilter.FileFilterApp + + + file-filter + + + + + + + + UTF-8 + 11 + 4.7.5 + 11 + + diff --git a/file-filter/pom.xml b/file-filter/pom.xml new file mode 100644 index 0000000..9174e6d --- /dev/null +++ b/file-filter/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + com.filefilter + file-filter-utility + 1.0.0 + jar + + File Filter Utility + Утилита для фильтрации содержимого файлов по типам данных + + + UTF-8 + 11 + 11 + 4.7.5 + + + + + + info.picocli + picocli + ${picocli.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 11 + 11 + UTF-8 + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.1 + + + package + + shade + + + + + com.filefilter.FileFilterApp + + + file-filter + + + + + + + \ No newline at end of file diff --git a/file-filter/src/main/java/com/filefilter/FileFilterApp.java b/file-filter/src/main/java/com/filefilter/FileFilterApp.java new file mode 100644 index 0000000..ff6d11f --- /dev/null +++ b/file-filter/src/main/java/com/filefilter/FileFilterApp.java @@ -0,0 +1,240 @@ +package com.filefilter; + +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; + +@Command(name = "file-filter", + mixinStandardHelpOptions = true, + version = "1.0", + description = "Утилита фильтрации содержимого файлов по типам данных") +public class FileFilterApp implements Runnable { + + @Parameters(description = "Входные файлы для обработки") + private List inputFiles = new ArrayList<>(); + + @Option(names = {"-o", "--output"}, + description = "Путь для выходных файлов (по умолчанию: текущая директория)") + private String outputPath = "."; + + @Option(names = {"-p", "--prefix"}, + description = "Префикс имен выходных файлов") + private String prefix = ""; + + @Option(names = {"-a", "--append"}, + description = "Режим добавления в существующие файлы") + private boolean appendMode = false; + + @Option(names = {"-s", "--short-stats"}, + description = "Краткая статистика") + private boolean shortStats = false; + + @Option(names = {"-f", "--full-stats"}, + description = "Полная статистика") + private boolean fullStats = false; + + private Statistics statistics; + private FileWriterManager writerManager; + + public static void main(String[] args) { + int exitCode = new CommandLine(new FileFilterApp()).execute(args); + System.exit(exitCode); + } + + @Override + public void run() { + if (inputFiles == null || inputFiles.isEmpty()) { + System.err.println("Ошибка: не указаны входные файлы"); + return; + } + + statistics = new Statistics(); + writerManager = new FileWriterManager(outputPath, prefix, appendMode); + + // Обработка файлов + for (String inputFile : inputFiles) { + processFile(inputFile); + } + + // Закрытие всех выходных файлов + writerManager.closeAll(); + + // Вывод статистики + printStatistics(); + } + + private void processFile(String filename) { + Path filePath = Paths.get(filename); + + if (!Files.exists(filePath)) { + System.err.println("Предупреждение: файл не найден: " + filename); + return; + } + + if (!Files.isReadable(filePath)) { + System.err.println("Предупреждение: файл недоступен для чтения: " + filename); + return; + } + + try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) { + String line; + int lineNumber = 0; + + while ((line = reader.readLine()) != null) { + lineNumber++; + processLine(line, filename, lineNumber); + } + } catch (IOException e) { + System.err.println("Ошибка при чтении файла " + filename + ": " + e.getMessage()); + } + } + + private void processLine(String line, String filename, int lineNumber) { + if (line.trim().isEmpty()) { + return; // Пропускаем пустые строки + } + + DataType type = detectType(line); + + try { + switch (type) { + case INTEGER: + long intValue = Long.parseLong(line.trim()); + writerManager.writeInteger(intValue); + statistics.addInteger(intValue); + break; + + case FLOAT: + double floatValue = Double.parseDouble(line.trim()); + writerManager.writeFloat(floatValue); + statistics.addFloat(floatValue); + break; + + case STRING: + writerManager.writeString(line); + statistics.addString(line); + break; + } + } catch (IOException e) { + System.err.println("Ошибка при записи данных из файла " + filename + + ", строка " + lineNumber + ": " + e.getMessage()); + } catch (NumberFormatException e) { + // Если парсинг не удался, считаем строкой + try { + writerManager.writeString(line); + statistics.addString(line); + } catch (IOException ioException) { + System.err.println("Ошибка при записи строки из файла " + filename + + ", строка " + lineNumber + ": " + ioException.getMessage()); + } + } + } + + private DataType detectType(String line) { + String trimmed = line.trim(); + + // Проверяем на целое число + try { + Long.parseLong(trimmed); + return DataType.INTEGER; + } catch (NumberFormatException e) { + // Не целое число + } + + // Проверяем на вещественное число + try { + Double.parseDouble(trimmed); + return DataType.FLOAT; + } catch (NumberFormatException e) { + // Не число + } + + // Иначе это строка + return DataType.STRING; + } + + private void printStatistics() { + System.out.println(); + + if (!shortStats && !fullStats) { + return; // Статистика не запрошена + } + + if (shortStats) { + printShortStatistics(); + } else if (fullStats) { + printFullStatistics(); + } + } + + private void printShortStatistics() { + System.out.println("=== Краткая статистика ==="); + + if (statistics.getIntegerCount() > 0) { + System.out.println("Целые числа: " + statistics.getIntegerCount() + " элементов"); + } + + if (statistics.getFloatCount() > 0) { + System.out.println("Вещественные числа: " + statistics.getFloatCount() + " элементов"); + } + + if (statistics.getStringCount() > 0) { + System.out.println("Строки: " + statistics.getStringCount() + " элементов"); + } + + if (statistics.getIntegerCount() == 0 && + statistics.getFloatCount() == 0 && + statistics.getStringCount() == 0) { + System.out.println("Данные не обработаны"); + } + } + + private void printFullStatistics() { + System.out.println("=== Полная статистика ==="); + + if (statistics.getIntegerCount() > 0) { + System.out.println("\nЦелые числа:"); + System.out.println(" Количество: " + statistics.getIntegerCount()); + System.out.println(" Минимум: " + statistics.getIntegerMin()); + System.out.println(" Максимум: " + statistics.getIntegerMax()); + System.out.println(" Сумма: " + statistics.getIntegerSum()); + System.out.println(" Среднее: " + statistics.getIntegerAverage()); + } + + if (statistics.getFloatCount() > 0) { + System.out.println("\nВещественные числа:"); + System.out.println(" Количество: " + statistics.getFloatCount()); + System.out.println(" Минимум: " + statistics.getFloatMin()); + System.out.println(" Максимум: " + statistics.getFloatMax()); + System.out.println(" Сумма: " + statistics.getFloatSum()); + System.out.println(" Среднее: " + statistics.getFloatAverage()); + } + + if (statistics.getStringCount() > 0) { + System.out.println("\nСтроки:"); + System.out.println(" Количество: " + statistics.getStringCount()); + System.out.println(" Длина самой короткой: " + statistics.getStringMinLength()); + System.out.println(" Длина самой длинной: " + statistics.getStringMaxLength()); + } + + if (statistics.getIntegerCount() == 0 && + statistics.getFloatCount() == 0 && + statistics.getStringCount() == 0) { + System.out.println("Данные не обработаны"); + } + } + + private enum DataType { + INTEGER, FLOAT, STRING + } +} \ No newline at end of file diff --git a/file-filter/src/main/java/com/filefilter/FileWriterManager.java b/file-filter/src/main/java/com/filefilter/FileWriterManager.java new file mode 100644 index 0000000..fd76a1f --- /dev/null +++ b/file-filter/src/main/java/com/filefilter/FileWriterManager.java @@ -0,0 +1,135 @@ +package com.filefilter; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +/** + * Менеджер для управления записью данных в выходные файлы + */ +public class FileWriterManager { + + private static final String INTEGERS_FILE = "integers.txt"; + private static final String FLOATS_FILE = "floats.txt"; + private static final String STRINGS_FILE = "strings.txt"; + + private final String outputPath; + private final String prefix; + private final boolean appendMode; + + private BufferedWriter integerWriter; + private BufferedWriter floatWriter; + private BufferedWriter stringWriter; + + /** + * Конструктор менеджера файлов + * + * @param outputPath путь для выходных файлов + * @param prefix префикс имен файлов + * @param appendMode режим добавления в файлы + */ + public FileWriterManager(String outputPath, String prefix, boolean appendMode) { + this.outputPath = outputPath != null ? outputPath : "."; + this.prefix = prefix != null ? prefix : ""; + this.appendMode = appendMode; + } + + /** + * Записать целое число в файл + */ + public void writeInteger(long value) throws IOException { + if (integerWriter == null) { + integerWriter = createWriter(INTEGERS_FILE); + } + integerWriter.write(String.valueOf(value)); + integerWriter.newLine(); + } + + /** + * Записать вещественное число в файл + */ + public void writeFloat(double value) throws IOException { + if (floatWriter == null) { + floatWriter = createWriter(FLOATS_FILE); + } + floatWriter.write(String.valueOf(value)); + floatWriter.newLine(); + } + + /** + * Записать строку в файл + */ + public void writeString(String value) throws IOException { + if (stringWriter == null) { + stringWriter = createWriter(STRINGS_FILE); + } + stringWriter.write(value); + stringWriter.newLine(); + } + + /** + * Создать writer для указанного файла + */ + private BufferedWriter createWriter(String filename) throws IOException { + Path dirPath = Paths.get(outputPath); + + // Создаем директорию если не существует + if (!Files.exists(dirPath)) { + try { + Files.createDirectories(dirPath); + } catch (IOException e) { + throw new IOException("Не удалось создать директорию: " + outputPath + + ". Причина: " + e.getMessage(), e); + } + } + + Path filePath = dirPath.resolve(prefix + filename); + + StandardOpenOption[] options; + if (appendMode) { + options = new StandardOpenOption[]{ + StandardOpenOption.CREATE, + StandardOpenOption.APPEND + }; + } else { + options = new StandardOpenOption[]{ + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING + }; + } + + try { + return Files.newBufferedWriter(filePath, StandardCharsets.UTF_8, options); + } catch (IOException e) { + throw new IOException("Не удалось создать файл: " + filePath + + ". Причина: " + e.getMessage(), e); + } + } + + /** + * Закрыть все открытые файлы + */ + public void closeAll() { + closeWriter(integerWriter, "integers"); + closeWriter(floatWriter, "floats"); + closeWriter(stringWriter, "strings"); + } + + /** + * Безопасно закрыть writer + */ + private void closeWriter(BufferedWriter writer, String type) { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + System.err.println("Предупреждение: ошибка при закрытии файла " + + type + ": " + e.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/file-filter/src/main/java/com/filefilter/Statistics.java b/file-filter/src/main/java/com/filefilter/Statistics.java new file mode 100644 index 0000000..ba95920 --- /dev/null +++ b/file-filter/src/main/java/com/filefilter/Statistics.java @@ -0,0 +1,112 @@ +package com.filefilter; + +/** + * Класс для сбора статистики по обработанным данным + */ +public class Statistics { + + // Статистика для целых чисел + private long integerCount = 0; + private long integerMin = Long.MAX_VALUE; + private long integerMax = Long.MIN_VALUE; + private long integerSum = 0; + + // Статистика для вещественных чисел + private long floatCount = 0; + private double floatMin = Double.MAX_VALUE; + private double floatMax = Double.MIN_VALUE; + private double floatSum = 0.0; + + // Статистика для строк + private long stringCount = 0; + private int stringMinLength = Integer.MAX_VALUE; + private int stringMaxLength = Integer.MIN_VALUE; + + /** + * Добавить целое число в статистику + */ + public void addInteger(long value) { + integerCount++; + integerMin = Math.min(integerMin, value); + integerMax = Math.max(integerMax, value); + integerSum += value; + } + + /** + * Добавить вещественное число в статистику + */ + public void addFloat(double value) { + floatCount++; + floatMin = Math.min(floatMin, value); + floatMax = Math.max(floatMax, value); + floatSum += value; + } + + /** + * Добавить строку в статистику + */ + public void addString(String value) { + stringCount++; + int length = value.length(); + stringMinLength = Math.min(stringMinLength, length); + stringMaxLength = Math.max(stringMaxLength, length); + } + + // Геттеры для целых чисел + + public long getIntegerCount() { + return integerCount; + } + + public long getIntegerMin() { + return integerCount > 0 ? integerMin : 0; + } + + public long getIntegerMax() { + return integerCount > 0 ? integerMax : 0; + } + + public long getIntegerSum() { + return integerSum; + } + + public double getIntegerAverage() { + return integerCount > 0 ? (double) integerSum / integerCount : 0.0; + } + + // Геттеры для вещественных чисел + + public long getFloatCount() { + return floatCount; + } + + public double getFloatMin() { + return floatCount > 0 ? floatMin : 0.0; + } + + public double getFloatMax() { + return floatCount > 0 ? floatMax : 0.0; + } + + public double getFloatSum() { + return floatSum; + } + + public double getFloatAverage() { + return floatCount > 0 ? floatSum / floatCount : 0.0; + } + + // Геттеры для строк + + public long getStringCount() { + return stringCount; + } + + public int getStringMinLength() { + return stringCount > 0 ? stringMinLength : 0; + } + + public int getStringMaxLength() { + return stringCount > 0 ? stringMaxLength : 0; + } +} \ No newline at end of file