diff --git a/.gitignore b/.gitignore index e0eb3bf..50d4412 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ target/ !**/src/test/**/out/ *.iml .idea/ - +*.class ### Mac OS ### .DS_Store diff --git a/src/main/java/com/javarush/karpeev/command/CryptText.java b/src/main/java/com/javarush/karpeev/command/CryptText.java new file mode 100644 index 0000000..5a82ed7 --- /dev/null +++ b/src/main/java/com/javarush/karpeev/command/CryptText.java @@ -0,0 +1,84 @@ +package com.javarush.karpeev.command; + +import com.javarush.karpeev.constants.Constants; + +import java.util.Arrays; + +public class CryptText { + public char[] encrypt(char[] arrayInputText, int key) { + char[] arrayOutputText = new char[arrayInputText.length]; + for (int i = 0; i < arrayInputText.length; i++) { + if (arrayInputText[i] == '\n') { + arrayOutputText[i] = arrayInputText[i]; + continue; + } + for (int j = 0; j < Constants.alphabet.length; j++) { + if (arrayInputText[i] == Constants.alphabet[j]) { + if (j + key > Constants.alphabet.length - 1) { + arrayOutputText[i] = Constants.alphabet[(j + key) % Constants.alphabet.length]; + } else { + arrayOutputText[i] = Constants.alphabet[j + key]; + } + } + } + } + return arrayOutputText; + } + + public char[] decrypt(char[] arrayInputText, int key) { + char[] arrayOutputText = new char[arrayInputText.length]; + for (int i = 0; i < arrayInputText.length; i++) { + if (arrayInputText[i] == '\n') { + arrayOutputText[i] = arrayInputText[i]; + continue; + } + for (int j = 0; j < Constants.alphabet.length; j++) { + if (arrayInputText[i] == Constants.alphabet[j]) { + if (j - key < 0) { + arrayOutputText[i] = Constants.alphabet[Constants.alphabet.length + j - key]; + } else { + arrayOutputText[i] = Constants.alphabet[j - key]; + } + } + } + } + return arrayOutputText; + } + + public int bruteForce(char[] arrayDecodeText) { + int correctKey = 0; + int maxAmount = 0; + char[] bufferArrayChar; + arrayDecodeText = Arrays.copyOf(arrayDecodeText, Math.min(arrayDecodeText.length, Constants.LIMIT_SYMBOLS_FOR_FOUND_KEY)); + for (int key = 0; key < Constants.alphabet.length; key++) { + int amountConjunction = 0; + bufferArrayChar = decrypt(arrayDecodeText, key); + for (int i = 0; i < bufferArrayChar.length; i++) { + amountConjunction += isCorrectKey(bufferArrayChar, i); + } + if (amountConjunction > maxAmount) { + maxAmount = amountConjunction; + correctKey = key; + } + } + return correctKey; + } + + public int isCorrectKey(char[] arrayChar, int i) { + int amountConjunction = 0; + if (arrayChar[i] == ' ') { + amountConjunction++; + } + if (i + 2 < arrayChar.length && arrayChar[i] == ',' && arrayChar[i + 1] == ' ' && Character.isLetter(arrayChar[i + 2])) { + amountConjunction += Constants.COEFFICIENT_EFFICIENCY; + } + if (i + 2 < arrayChar.length && arrayChar[i] == ' ' && Character.isLetter(arrayChar[i + 1]) && arrayChar[i + 2] == ' ') { + amountConjunction++; + } + if (i + 2 < arrayChar.length && arrayChar[i] == '.' && arrayChar[i + 1] == ' ' && + Character.isLetter(arrayChar[i + 2]) && Character.isUpperCase(arrayChar[i + 2])) { + amountConjunction += Constants.COEFFICIENT_EFFICIENCY; + } + return amountConjunction; + } +} diff --git a/src/main/java/com/javarush/karpeev/console/Menu.java b/src/main/java/com/javarush/karpeev/console/Menu.java new file mode 100644 index 0000000..9c1695b --- /dev/null +++ b/src/main/java/com/javarush/karpeev/console/Menu.java @@ -0,0 +1,109 @@ +package com.javarush.karpeev.console; + +import com.javarush.karpeev.exceptions.FileForReadNotFoundException; +import com.javarush.karpeev.exceptions.FileForWriteNotFoundException; +import com.javarush.karpeev.fileManager.FileManager; +import com.javarush.karpeev.command.CryptText; +import com.javarush.karpeev.constants.Constants; +import com.javarush.karpeev.constants.Message; + +import java.util.Scanner; + +public class Menu { + private int key; + private int step = Constants.STEP_START; + + Scanner input = new Scanner(System.in); + + public void getMenu() { + System.out.println(Message.WELCOME); + while (step != Constants.STEP_EXIT) { + switch (getStep()) { + case 1 -> coding(); + case 2 -> decoding(); + case 3 -> foundKey(); + default -> System.out.println(Message.BAY); + } + } + } + + private void coding() { + FileManager fileManager = new FileManager(); + CryptText cryptText = new CryptText(); + getKey(); + try { + char[] arrayEncrypt = cryptText.encrypt(fileManager.varyTextInArrayChar(fileManager.getPathReadeFile()), key); + fileManager.writeTextInFile(fileManager.getPathWriteFile(), arrayEncrypt, arrayEncrypt.length); + System.out.println(Message.END_CODE + Message.NEXT_STEP); + } catch (FileForReadNotFoundException e) { + System.out.println(Message.NOT_FOUND_FILE_FOR_READ + Message.NEXT_STEP); + } catch (FileForWriteNotFoundException e) { + System.out.println(Message.NOT_FOUND_FILE_FOR_WRITE + Message.NEXT_STEP); + } + } + + private void decoding() { + FileManager fileManager = new FileManager(); + CryptText cryptText = new CryptText(); + getKey(); + try { + char[] arrayForDecrypt = cryptText.decrypt(fileManager.varyTextInArrayChar(fileManager.getPathReadeFile()), key); + fileManager.writeTextInFile(fileManager.getPathWriteFile(), arrayForDecrypt, arrayForDecrypt.length); + System.out.println(Message.END_DECODE + Message.NEXT_STEP); + } catch (FileForReadNotFoundException e) { + System.out.println(Message.NOT_FOUND_FILE_FOR_READ + Message.NEXT_STEP); + } catch (FileForWriteNotFoundException e) { + System.out.println(Message.NOT_FOUND_FILE_FOR_WRITE + Message.NEXT_STEP); + } + } + + private void foundKey() { + FileManager fileManager = new FileManager(); + CryptText cryptText = new CryptText(); + try { + char[] arrayDecrypt = fileManager.varyTextInArrayChar(fileManager.getPathFoundKey()); + key = cryptText.bruteForce(arrayDecrypt); + fileManager.writeTextInFile(fileManager.getPathWriteFile(), cryptText.decrypt(arrayDecrypt, key), arrayDecrypt.length); + System.out.println(Message.END_DECODE + Message.END_FOUND_KEY + key + Message.NEXT_STEP); + } catch (FileForReadNotFoundException e) { + System.out.println(Message.NOT_FOUND_FILE_FOR_READ + Message.NEXT_STEP); + } catch (FileForWriteNotFoundException e) { + System.out.println(Message.NOT_FOUND_FILE_FOR_WRITE + Message.NEXT_STEP); + } + } + + private int getStep() { + while (true) { + System.out.println(Message.MENU); + try { + step = Integer.parseInt(input.nextLine()); + } catch (NumberFormatException e) { + System.out.println(Message.NOT_NUMBER); + continue; + } + if (step < Constants.INTERVAL_STEP_MENU_START || step > Constants.INTERVAL_STEP_MENU_END) { + System.out.println(Message.NUMBER_NOT_IN_MENU); + } else { + break; + } + } + return step; + } + + public void getKey() { + while (true) { + System.out.print(Message.INPUT_KEY + (Constants.alphabet.length - 1) + ": "); + try { + key = Integer.parseInt(input.nextLine()); + } catch (NumberFormatException e) { + System.out.println(Message.NOT_NUMBER_KEY + (Constants.alphabet.length - 1) + ": "); + continue; + } + if (key < 1 || key > Constants.alphabet.length - 1) { + System.out.println(Message.FALSE_NUMBER + (Constants.alphabet.length - 1) + ": "); + } else { + break; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/karpeev/constants/Constants.java b/src/main/java/com/javarush/karpeev/constants/Constants.java new file mode 100644 index 0000000..e43efd0 --- /dev/null +++ b/src/main/java/com/javarush/karpeev/constants/Constants.java @@ -0,0 +1,26 @@ +package com.javarush.karpeev.constants; +public class Constants { + public static final char[] alphabet = { + 'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', + 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', + 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я', + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', + 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', + 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', + '~', '!', '@', '#', '$', '№', ':', '^', '&', '?', '*', '(', ')', '{', '}', '-', '«', '»', + '_', ',', '/', '.', '…', '|', '<', '>', '+', ';', '%', '"', '`', '=', '\'', '\\', ' ', '—', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' + }; + + public static final int COEFFICIENT_EFFICIENCY = 10; + public static final int LIMIT_SYMBOLS_FOR_FOUND_KEY = 1000; + public static final int STEP_START = -1; + public static final int INTERVAL_STEP_MENU_START = 0; + public static final int INTERVAL_STEP_MENU_END = 3; + public static final int STEP_EXIT = 0; + +} \ No newline at end of file diff --git a/src/main/java/com/javarush/karpeev/constants/Message.java b/src/main/java/com/javarush/karpeev/constants/Message.java new file mode 100644 index 0000000..66c58a8 --- /dev/null +++ b/src/main/java/com/javarush/karpeev/constants/Message.java @@ -0,0 +1,22 @@ +package com.javarush.karpeev.constants; + +public class Message { + public static final String NOT_NUMBER = "Вы ввели текст или нецелое число. Введите число от 0 до 3"; + public static final String NOT_NUMBER_KEY = "Вы ввели текст или нецелое число. Введите целое число от 1 до "; + public static final String INPUT_PATH_READ_FILE = "Введите адрес файла с текстом для шифрования: "; + public static final String INPUT_PATH_FOR_FOUND_KEY = "Введите адрес зашифрованного текстового файла для поиска ключа: "; + public static final String INPUT_PATH_WRITE_FILE = "Введите адрес файла для записи: "; + public static final String FALSE_NUMBER = "Вы ввели число, которое не входит в диапазон от 1 до "; + public static final String NUMBER_NOT_IN_MENU = "\nЧисло не соответствует входному условию. Введите число от 0 до 3"; + public static final String MENU = "1 - Шифрование\n2 - Расшифровка\n3 - Поиск ключа расшифровки\n0 - Выход"; + public static final String WELCOME = "\nДобро пожаловать в шифратор!\n\nВведите действие в соответствии с пунктом в меню:"; + public static final String INPUT_KEY = "Введите ключ - положительное целое число от 1 до "; + public static final String NEXT_STEP = "\nДля дальнейших действий выберите пункт в меню.\n"; + public static final String END_CODE = "Шифрование выполнено!"; + public static final String END_DECODE = "Расшифровка выполнена! "; + public static final String END_FOUND_KEY = "Поиск ключа выполнен! \nКорректный ключ: "; + public static final String NOT_FOUND_FILE_FOR_READ = "\nФайл для чтения текста не найден! Попробуйте ещё раз\n"; + public static final String NOT_FOUND_FILE_FOR_WRITE = "\nФайл для записи не найден! Попробуйте ещё раз\n"; + public static final String BAY = "До скорой встречи!"; +} + diff --git a/src/main/java/com/javarush/karpeev/exceptions/FileForReadNotFoundException.java b/src/main/java/com/javarush/karpeev/exceptions/FileForReadNotFoundException.java new file mode 100644 index 0000000..54c9175 --- /dev/null +++ b/src/main/java/com/javarush/karpeev/exceptions/FileForReadNotFoundException.java @@ -0,0 +1,8 @@ +package com.javarush.karpeev.exceptions; + +import java.io.IOException; + +public class FileForReadNotFoundException extends IOException { + public FileForReadNotFoundException() { + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/karpeev/exceptions/FileForWriteNotFoundException.java b/src/main/java/com/javarush/karpeev/exceptions/FileForWriteNotFoundException.java new file mode 100644 index 0000000..914a105 --- /dev/null +++ b/src/main/java/com/javarush/karpeev/exceptions/FileForWriteNotFoundException.java @@ -0,0 +1,8 @@ +package com.javarush.karpeev.exceptions; + +import java.io.IOException; + +public class FileForWriteNotFoundException extends IOException { + public FileForWriteNotFoundException() { + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/karpeev/fileManager/FileManager.java b/src/main/java/com/javarush/karpeev/fileManager/FileManager.java new file mode 100644 index 0000000..851fae7 --- /dev/null +++ b/src/main/java/com/javarush/karpeev/fileManager/FileManager.java @@ -0,0 +1,54 @@ +package com.javarush.karpeev.fileManager; + +import com.javarush.karpeev.exceptions.FileForReadNotFoundException; +import com.javarush.karpeev.exceptions.FileForWriteNotFoundException; +import com.javarush.karpeev.constants.Message; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Scanner; + +public class FileManager { + Scanner scanner = new Scanner(System.in); + + public char[] varyTextInArrayChar(String addressText) throws FileForReadNotFoundException { + StringBuilder textBuffer = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new FileReader(addressText))) { + while (reader.ready()) { + textBuffer.append(reader.readLine()).append('\n'); + } + } catch (IOException e) { + throw new FileForReadNotFoundException(); + } + textBuffer.deleteCharAt(textBuffer.length() - 1); + return textBuffer.toString().toCharArray(); + } + + public void writeTextInFile(String addressFileForWrite, char[] mas, int len) throws FileForWriteNotFoundException { + File file = new File(addressFileForWrite); + if (!file.exists()) { + throw new FileForWriteNotFoundException(); + } + try (BufferedWriter writer = Files.newBufferedWriter(Path.of(addressFileForWrite))) { + writer.write(mas, 0, len); + } catch (IOException e) { + throw new FileForWriteNotFoundException(); + } + } + + public String getPathReadeFile() { + System.out.print(Message.INPUT_PATH_READ_FILE); + return scanner.nextLine(); + } + + public String getPathFoundKey() { + System.out.print(Message.INPUT_PATH_FOR_FOUND_KEY); + return scanner.nextLine(); + } + + public String getPathWriteFile() throws FileForWriteNotFoundException { + System.out.print(Message.INPUT_PATH_WRITE_FILE); + return scanner.nextLine(); + } +} diff --git a/src/main/java/com/javarush/karpeev/main/Runner.java b/src/main/java/com/javarush/karpeev/main/Runner.java new file mode 100644 index 0000000..93a9ab2 --- /dev/null +++ b/src/main/java/com/javarush/karpeev/main/Runner.java @@ -0,0 +1,10 @@ +package com.javarush.karpeev.main; + +import com.javarush.karpeev.console.Menu; + +public class Runner { + public static void main(String[] args) { + Menu menu = new Menu(); + menu.getMenu(); + } +}