diff --git a/pom.xml b/pom.xml index 7dcd370..a0b4b4c 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ UTF-8 21 21 - udk-pdf-scanner + udk-searcher diff --git a/src/main/java/ru/mcs/udk/DJVUScanner.java b/src/main/java/ru/mcs/udk/DJVUScanner.java deleted file mode 100644 index 3a3148d..0000000 --- a/src/main/java/ru/mcs/udk/DJVUScanner.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.mcs.udk; - -import net.sourceforge.tess4j.TesseractException; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; - -import static ru.mcs.udk.DocumentUtils.findUDK; - -public class DJVUScanner implements DocumentScanner { - @Override - public DocumentInfo getUDK(File djvuFile) { - DocumentInfo documentInfo = new DocumentInfo(); - for (int pageIndex = 0; pageIndex < 6; pageIndex++) { - String outputFile = String.format("temp/page_%d.tiff", pageIndex); - Process process; - try { - process = new ProcessBuilder("ddjvu", - "-format=tiff", - "-quality=90", - "-page=" + pageIndex, - djvuFile.getAbsolutePath(), - outputFile).start(); - int exitCode = process.waitFor(); - if (exitCode == 0) { - BufferedImage image = ImageIO.read(new File(outputFile)); - String text = DocumentUtils.getText(image); - documentInfo.setUdk(findUDK(text)); - } - } catch (InterruptedException | IOException | TesseractException e) { - documentInfo.setError(e.getMessage()); - } - } - return documentInfo; - } -} diff --git a/src/main/java/ru/mcs/udk/DocumentInfo.java b/src/main/java/ru/mcs/udk/DocumentInfo.java deleted file mode 100644 index 19d1beb..0000000 --- a/src/main/java/ru/mcs/udk/DocumentInfo.java +++ /dev/null @@ -1,49 +0,0 @@ -package ru.mcs.udk; - -public class DocumentInfo { - String language; - String udk; - long time; - String error; - String fileSize; - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getUdk() { - return udk; - } - - public void setUdk(String udk) { - this.udk = udk; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public String getError() { - return error; - } - - public void setError(String error) { - this.error = error; - } - - public String getFileSize() { - return fileSize; - } - - public void setFileSize(String fileSize) { - this.fileSize = fileSize; - } -} diff --git a/src/main/java/ru/mcs/udk/DocumentScanner.java b/src/main/java/ru/mcs/udk/DocumentScanner.java deleted file mode 100644 index 3ce3016..0000000 --- a/src/main/java/ru/mcs/udk/DocumentScanner.java +++ /dev/null @@ -1,9 +0,0 @@ -package ru.mcs.udk; - -import java.io.File; -import java.io.IOException; - -public interface DocumentScanner { - - DocumentInfo getUDK(File file); -} diff --git a/src/main/java/ru/mcs/udk/DocumentScannerFactory.java b/src/main/java/ru/mcs/udk/DocumentScannerFactory.java deleted file mode 100644 index 1d185f8..0000000 --- a/src/main/java/ru/mcs/udk/DocumentScannerFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.mcs.udk; - -public class DocumentScannerFactory { - public static DocumentScanner getScanner(String filePath) { - if (filePath.toLowerCase().endsWith(".pdf")) { - return new PDFScanner(); - } else if (filePath.toLowerCase().endsWith(".djvu")) { - return new DJVUScanner(); - } else { - throw new IllegalArgumentException("Неподдерживаемый формат файла: " + filePath); - } - } -} diff --git a/src/main/java/ru/mcs/udk/DocumentUtils.java b/src/main/java/ru/mcs/udk/DocumentUtils.java deleted file mode 100644 index 585dc39..0000000 --- a/src/main/java/ru/mcs/udk/DocumentUtils.java +++ /dev/null @@ -1,56 +0,0 @@ -package ru.mcs.udk; - -import net.sourceforge.tess4j.Tesseract; -import net.sourceforge.tess4j.TesseractException; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class DocumentUtils { - public static void main(String[] args) { - Tesseract tesseract = new Tesseract(); - tesseract.setDatapath("d:\\program\\Tesseract-OCR\\tessdata\\"); - tesseract.setLanguage("rus"); - - try { - String text = tesseract.doOCR(new File("book3.PNG")); - System.out.println(text); - String udk = findUDK(text); - System.out.println("UDK " + udk); - } catch (TesseractException e) { - e.printStackTrace(); - } - } - - public static String getText(BufferedImage image) throws TesseractException { - Tesseract tesseract = new Tesseract(); - tesseract.setDatapath("d:\\program\\Tesseract-OCR\\tessdata\\"); - tesseract.setLanguage("rus"); - tesseract.setVariable("user_defined_dpi", "300"); - // Настройки для маленьких изображений -// tesseract.setPageSegMode(7); // PSM_SINGLE_LINE (распознавание одной строки) -// tesseract.setVariable("tessedit_min_characters", "1"); // Минимальное количество символов - - return tesseract.doOCR(image); - } - - public static String findUDK(String text) { - // Регулярное выражение для поиска УДК - Pattern pattern = Pattern.compile("[Уу]\\s*[Дд]\\s*[Кк]\\s*([0-9.]+)"); - Matcher matcher = pattern.matcher(text); - - if (matcher.find()) { - return matcher.group(1); - } - return null; - } - - public static boolean isCyrillic(String fileName) { - String regex = ".*[\\p{IsCyrillic}]{3,}.*"; - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(fileName); - return matcher.matches(); - } -} diff --git a/src/main/java/ru/mcs/udk/PDFScanner.java b/src/main/java/ru/mcs/udk/PDFScanner.java deleted file mode 100644 index 6182db6..0000000 --- a/src/main/java/ru/mcs/udk/PDFScanner.java +++ /dev/null @@ -1,68 +0,0 @@ -package ru.mcs.udk; - -import net.sourceforge.tess4j.TesseractException; -import org.apache.pdfbox.Loader; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.rendering.PDFRenderer; -import org.apache.pdfbox.text.PDFTextStripper; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.text.DecimalFormat; - -import static ru.mcs.udk.DocumentUtils.findUDK; -import static ru.mcs.udk.DocumentUtils.isCyrillic; - -public class PDFScanner implements DocumentScanner { - - @Override - public DocumentInfo getUDK(File file) { - // Засекаем время начала поиска - long startTime = System.currentTimeMillis(); - DocumentInfo documentInfo = new DocumentInfo(); - documentInfo.setError(""); - documentInfo.setUdk(""); - documentInfo.setFileSize(getSizeFile(file)); - try (PDDocument document = Loader.loadPDF(file)) { - PDFTextStripper stripper = new PDFTextStripper(); - // Устанавливаем диапазон страниц для анализа (первые три страницы) - stripper.setStartPage(1); - stripper.setEndPage(Math.min(3, document.getNumberOfPages())); - String text = stripper.getText(document); - documentInfo.setUdk(findUDK(text)); - - documentInfo.setLanguage(isCyrillic(file.getName()) ? "ru" : "en"); - - if ((documentInfo.getUdk() == null || documentInfo.getUdk().isBlank()) && documentInfo.getLanguage().equals("ru")) { - documentInfo.setUdk(getUdkByImage(document)); - } - } catch (IOException | TesseractException e) { - documentInfo.setError(e.getMessage()); - } - long endTime = System.currentTimeMillis(); - documentInfo.setTime(endTime - startTime); - return documentInfo; - } - - private String getSizeFile(File file) { - double sizeInMB = (double) file.length() / (1024 * 1024); // Размер в мегабайтах - DecimalFormat df = new DecimalFormat("#.##"); // Форматирование до двух знаков после запятой - - return df.format(sizeInMB) + " Mb"; - } - - private static String getUdkByImage(PDDocument document) throws IOException, TesseractException { - PDFRenderer renderer = new PDFRenderer(document); - - for (int pageIndex = 0; pageIndex < 6; pageIndex++) { - BufferedImage image = renderer.renderImageWithDPI(pageIndex, 300); - String text = DocumentUtils.getText(image); - String udk = findUDK(text); - if (udk != null) { - return udk; - } - } - return ""; - } -} diff --git a/src/main/java/ru/mcs/udk/UDKSearcher.java b/src/main/java/ru/mcs/udk/UDKSearcher.java index 1903d73..8a563f0 100644 --- a/src/main/java/ru/mcs/udk/UDKSearcher.java +++ b/src/main/java/ru/mcs/udk/UDKSearcher.java @@ -6,6 +6,9 @@ import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; +import ru.mcs.udk.document.DocumentScanner; +import ru.mcs.udk.factory.DocumentScannerFactory; +import ru.mcs.udk.wrapper.DocumentInfo; import java.io.File; import java.io.FileNotFoundException; @@ -61,8 +64,6 @@ // проходимся по всем найденым файлам и ищем УДК findUdk(outputFile); - - } catch (ParseException e) { System.out.println("Ошибка при разборе аргументов: " + e.getMessage()); printHelp(options); diff --git a/src/main/java/ru/mcs/udk/UdkScannerExecutor.java b/src/main/java/ru/mcs/udk/UdkScannerExecutor.java deleted file mode 100644 index 5f291e1..0000000 --- a/src/main/java/ru/mcs/udk/UdkScannerExecutor.java +++ /dev/null @@ -1,54 +0,0 @@ -package ru.mcs.udk; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; - - -public class UdkScannerExecutor { - public static void main(String[] args) throws FileNotFoundException { - if (args.length == 0) { - System.out.println("Пожалуйста, укажите путь к папке."); - return; - } - - String directoryPath = args[0]; - Path startDir = Paths.get(directoryPath); - - if (!Files.exists(startDir) || !Files.isDirectory(startDir)) { - System.out.println("Указанный путь не существует или не является папкой."); - return; - } - - System.setOut(new PrintStream(new FileOutputStream("book-list.csv"), true, StandardCharsets.UTF_8)); - try { - Files.walkFileTree(startDir, new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - if (file.toAbsolutePath().toString().matches(".*\\.pdf$")) { - // Выводим путь и имя файла - PDFScanner pdfScanner = new PDFScanner(); - pdfScanner.getUDK(file.toFile()); - } else if (file.toAbsolutePath().toString().matches(".*\\.djvu$")) { - DJVUScanner djvuScanner = new DJVUScanner(); - djvuScanner.getUDK(file.toFile()); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) { - // Обрабатываем ошибки доступа к файлам - System.err.println("Ошибка доступа к файлу: " + file.toAbsolutePath() + " - " + exc.getMessage()); - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/ru/mcs/udk/document/DocumentScanner.java b/src/main/java/ru/mcs/udk/document/DocumentScanner.java new file mode 100644 index 0000000..567f5c9 --- /dev/null +++ b/src/main/java/ru/mcs/udk/document/DocumentScanner.java @@ -0,0 +1,10 @@ +package ru.mcs.udk.document; + +import ru.mcs.udk.wrapper.DocumentInfo; + +import java.io.File; + +public interface DocumentScanner { + + DocumentInfo getUDK(File file); +} diff --git a/src/main/java/ru/mcs/udk/document/impl/DJVUScanner.java b/src/main/java/ru/mcs/udk/document/impl/DJVUScanner.java new file mode 100644 index 0000000..827a80a --- /dev/null +++ b/src/main/java/ru/mcs/udk/document/impl/DJVUScanner.java @@ -0,0 +1,51 @@ +package ru.mcs.udk.document.impl; + +import net.sourceforge.tess4j.TesseractException; +import ru.mcs.udk.wrapper.DocumentInfo; +import ru.mcs.udk.document.DocumentScanner; +import ru.mcs.udk.utils.DocumentUtils; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import static ru.mcs.udk.utils.DocumentUtils.findUDK; + +public class DJVUScanner implements DocumentScanner { + @Override + public DocumentInfo getUDK(File djvuFile) { + // Засекаем время начала поиска + long startTime = System.currentTimeMillis(); + DocumentInfo documentInfo = new DocumentInfo(); + documentInfo.setError(""); + documentInfo.setUdk(""); + for (int pageIndex = 0; pageIndex < 6; pageIndex++) { + String outputFile = String.format("temp/page_%d.tiff", pageIndex); + Process process; + try { + process = new ProcessBuilder("ddjvu", + "-format=tiff", + "-quality=90", + "-page=" + pageIndex, + djvuFile.getAbsolutePath(), + outputFile).start(); + int exitCode = process.waitFor(); + if (exitCode == 0) { + BufferedImage image = ImageIO.read(new File(outputFile)); + String text = DocumentUtils.getText(image); + String udk = findUDK(text); + documentInfo.setUdk(udk); + if (udk != null && !udk.isEmpty()) { + break; + } + } + } catch (InterruptedException | IOException | TesseractException e) { + documentInfo.setError(e.getMessage()); + } + } + long endTime = System.currentTimeMillis(); + documentInfo.setTime(endTime - startTime); + return documentInfo; + } +} diff --git a/src/main/java/ru/mcs/udk/document/impl/PDFScanner.java b/src/main/java/ru/mcs/udk/document/impl/PDFScanner.java new file mode 100644 index 0000000..d4ac5d8 --- /dev/null +++ b/src/main/java/ru/mcs/udk/document/impl/PDFScanner.java @@ -0,0 +1,71 @@ +package ru.mcs.udk.document.impl; + +import net.sourceforge.tess4j.TesseractException; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.apache.pdfbox.text.PDFTextStripper; +import ru.mcs.udk.wrapper.DocumentInfo; +import ru.mcs.udk.document.DocumentScanner; +import ru.mcs.udk.utils.DocumentUtils; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; + +import static ru.mcs.udk.utils.DocumentUtils.findUDK; +import static ru.mcs.udk.utils.DocumentUtils.isCyrillic; + +public class PDFScanner implements DocumentScanner { + + @Override + public DocumentInfo getUDK(File file) { + // Засекаем время начала поиска + long startTime = System.currentTimeMillis(); + DocumentInfo documentInfo = new DocumentInfo(); + documentInfo.setError(""); + documentInfo.setUdk(""); + documentInfo.setFileSize(getSizeFile(file)); + try (PDDocument document = Loader.loadPDF(file)) { + PDFTextStripper stripper = new PDFTextStripper(); + // Устанавливаем диапазон страниц для анализа (первые три страницы) + stripper.setStartPage(1); + stripper.setEndPage(Math.min(3, document.getNumberOfPages())); + String text = stripper.getText(document); + documentInfo.setUdk(findUDK(text)); + + documentInfo.setLanguage(isCyrillic(file.getName()) ? "ru" : "en"); + + if ((documentInfo.getUdk() == null || documentInfo.getUdk().isBlank()) && documentInfo.getLanguage().equals("ru")) { + documentInfo.setUdk(getUdkByImage(document)); + } + } catch (IOException | TesseractException e) { + documentInfo.setError(e.getMessage()); + } + long endTime = System.currentTimeMillis(); + documentInfo.setTime(endTime - startTime); + return documentInfo; + } + + private String getSizeFile(File file) { + double sizeInMB = (double) file.length() / (1024 * 1024); // Размер в мегабайтах + DecimalFormat df = new DecimalFormat("#.##"); // Форматирование до двух знаков после запятой + + return df.format(sizeInMB) + " Mb"; + } + + private static String getUdkByImage(PDDocument document) throws IOException, TesseractException { + PDFRenderer renderer = new PDFRenderer(document); + + for (int pageIndex = 0; pageIndex < 6; pageIndex++) { + BufferedImage image = renderer.renderImageWithDPI(pageIndex, 300); + String text = DocumentUtils.getText(image); + String udk = findUDK(text); + if (udk != null) { + return udk; + } + } + return ""; + } +} diff --git a/src/main/java/ru/mcs/udk/factory/DocumentScannerFactory.java b/src/main/java/ru/mcs/udk/factory/DocumentScannerFactory.java new file mode 100644 index 0000000..9389a34 --- /dev/null +++ b/src/main/java/ru/mcs/udk/factory/DocumentScannerFactory.java @@ -0,0 +1,17 @@ +package ru.mcs.udk.factory; + +import ru.mcs.udk.document.DocumentScanner; +import ru.mcs.udk.document.impl.DJVUScanner; +import ru.mcs.udk.document.impl.PDFScanner; + +public class DocumentScannerFactory { + public static DocumentScanner getScanner(String filePath) { + if (filePath.toLowerCase().endsWith(".pdf")) { + return new PDFScanner(); + } else if (filePath.toLowerCase().endsWith(".djvu")) { + return new DJVUScanner(); + } else { + throw new IllegalArgumentException("Неподдерживаемый формат файла: " + filePath); + } + } +} diff --git a/src/main/java/ru/mcs/udk/utils/DocumentUtils.java b/src/main/java/ru/mcs/udk/utils/DocumentUtils.java new file mode 100644 index 0000000..1782ece --- /dev/null +++ b/src/main/java/ru/mcs/udk/utils/DocumentUtils.java @@ -0,0 +1,56 @@ +package ru.mcs.udk.utils; + +import net.sourceforge.tess4j.Tesseract; +import net.sourceforge.tess4j.TesseractException; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DocumentUtils { + public static void main(String[] args) { + Tesseract tesseract = new Tesseract(); + tesseract.setDatapath("d:\\program\\Tesseract-OCR\\tessdata\\"); + tesseract.setLanguage("rus"); + + try { + String text = tesseract.doOCR(new File("book3.PNG")); + System.out.println(text); + String udk = findUDK(text); + System.out.println("UDK " + udk); + } catch (TesseractException e) { + e.printStackTrace(); + } + } + + public static String getText(BufferedImage image) throws TesseractException { + Tesseract tesseract = new Tesseract(); + tesseract.setDatapath("d:\\program\\Tesseract-OCR\\tessdata\\"); + tesseract.setLanguage("rus"); + tesseract.setVariable("user_defined_dpi", "300"); + // Настройки для маленьких изображений +// tesseract.setPageSegMode(7); // PSM_SINGLE_LINE (распознавание одной строки) +// tesseract.setVariable("tessedit_min_characters", "1"); // Минимальное количество символов + + return tesseract.doOCR(image); + } + + public static String findUDK(String text) { + // Регулярное выражение для поиска УДК + Pattern pattern = Pattern.compile("[Уу]\\s*[Дд]\\s*[Кк]\\s*([0-9.]+)"); + Matcher matcher = pattern.matcher(text); + + if (matcher.find()) { + return matcher.group(1); + } + return null; + } + + public static boolean isCyrillic(String fileName) { + String regex = ".*[\\p{IsCyrillic}]{3,}.*"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(fileName); + return matcher.matches(); + } +} diff --git a/src/main/java/ru/mcs/udk/wrapper/DocumentInfo.java b/src/main/java/ru/mcs/udk/wrapper/DocumentInfo.java new file mode 100644 index 0000000..c2298ef --- /dev/null +++ b/src/main/java/ru/mcs/udk/wrapper/DocumentInfo.java @@ -0,0 +1,49 @@ +package ru.mcs.udk.wrapper; + +public class DocumentInfo { + String language; + String udk; + long time; + String error; + String fileSize; + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getUdk() { + return udk; + } + + public void setUdk(String udk) { + this.udk = udk; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public String getFileSize() { + return fileSize; + } + + public void setFileSize(String fileSize) { + this.fileSize = fileSize; + } +} diff --git a/temp/page_3.tiff b/temp/page_3.tiff new file mode 100644 index 0000000..85c95e1 --- /dev/null +++ b/temp/page_3.tiff Binary files differ