Как проанализировать файл и использовать данные для расшифровки данных другого файла? - PullRequest
2 голосов
/ 12 марта 2019

Я пытаюсь заменить символы в цикле, и я получил такой код

$my_file = 'encrypted_text.txt';
$handle = fopen($my_file, 'r');
$data = fread($handle,filesize($my_file));
echo "\n".$data."\n";

$file = fopen("encryption_scheme.txt", "r");
$members = array();

while (!feof($file)) 
{
    $code = substr(fgets($file), strrpos(fgets($file), '=> ' )+1); 
    $code = str_replace('>', '', $code);
    $code = str_replace(' ', '', $code);
    $letter = substr(fgets($file), 0, 1);
    $data = str_replace(',', ' ', $data);
    $data = str_replace($code, $letter, $data); 
}
echo $data;

fclose($file);

Но вместо получения расшифрованного текста он повторяет коды, такие как

631005,323151,810236,60916,384244,346538,404479

631005 323151 810236 60916 384244 346538 404479

Обновление

while (!feof($file)) 
{
    $text = fgets($file);
    $code = substr($text, strrpos($text, '=> ' )+1); 
    $code = str_replace('>', '', $code);
    $code = str_replace(' ', '', $code);
    $letter = substr($text, 0, 1);
    $data = str_replace(',', ' ', $data);
    $data = str_replace($code, $letter, $data); 
}

Ответы [ 2 ]

2 голосов
/ 12 марта 2019

Я только что проверил это на своем локальном хосте с вашими примерами данных.

Преимущество использования preg_match_all() здесь (хотя некоторые люди боятся регулярных выражений) заключается в том, что php не требуется 110x батарея замен строк для достижения результата.

  • Прочитать оба файла, разобрать схему шифрования, применить замены к зашифрованному тексту

См. Шаблон Regex на работе: https://regex101.com/r/HAQEuK/2

Код:

$encryption_scheme = file_get_contents('encryption_scheme.txt');
if (!preg_match_all('~(.*?) => (\d+)(?: *\R|$)~s', $encryption_scheme, $matches, PREG_SET_ORDER)) {
    echo 'Failed to extract encryption scheme.';
} else {
    $translator = array_combine(array_column($matches, 2), array_column($matches, 1));
    $translator[','] = ' ';  // replace commas with spaces
    $encrypted_text = file_get_contents('encrypted_text.txt');
    echo strtr($encrypted_text, $translator);
}

Выход:

z C F I L O R

Шаблон регулярного выражения говорит:

  • захватывает подстроку перед [space] => [space], затем захватывает числовую подстроку в той же строке, затем сопоставляет / использует завершающие пробелы и возврат строки (за исключением последней строки, не имеющей строки, возвращаемой для сопоставления).
  • array_combine() позволяет генерировать ассоциативный массив из двух столбцов захваченных данных.

Чтобы быть более точными и предотвратить непреднамеренные замены, вы можете обработать каждое целое число индивидуально и распаковать их после расшифровки.

$encryption_scheme = file_get_contents('encryption_scheme.txt');
if (!preg_match_all('~(.*?) => (\d+)(?: *\R|$)~s', $encryption_scheme, $matches, PREG_SET_ORDER)) {
    echo 'Failed to extract encryption scheme.';
} else {
    $translator = array_combine(array_column($matches, 2), array_column($matches, 1));
    $encrypted_text = file_get_contents('encrypted_text.txt');
    $decrypted = [];
    foreach (explode(',', $encrypted_text) as $integer) {
        $decrypted = $translator[$integer] ?? $integer;
    }
    echo implode(' ', $decrypted);
}
2 голосов
/ 12 марта 2019

Ваша первая проблема заключается в том, что fgets возвращает текст , включая символ новой строки (и в зависимости от возврата каретки системы).

Ваша вторая проблема в том, что некоторые из "букв" не имеют длины "один символ" (а именно символы в кодировке Юникод в конце).

Ваша третья проблема заключается в том, что при изменении схемы шифрования могут возникнуть непредвиденные результаты. скажем, ваша схема шифрования просто так:

a => 1
b => 12
c => 2

текст 12, который явно равен b, вместо этого превратится в ac (из-за порядка).

На мой взгляд, это приводит к выводу, что ответ Микмацкузы - лучший, особенно вторая часть его ответа, проходящая через шифротекстовый код по коду.

мое старое решение

Я бы, наверное, использовал

$data = str_replace(',', ' ', $data); // do this once, not every iteration

while($text = fgets($file) { // fgets returns false on eof
    list($letter, $code) = explode(' => ', $text, 2);
    $code = trim($code); // <-- removes whitespace and new lines and so on
    $data = str_replace($code, $letter, $data);
}

обновление:

// expand the text, if no "=>" is found:
while(...) {
    if(strpos($text, '=>') === FALSE) {
        $text = fgets($text);
    }
    if(!trim($text)) { // completely empty lines, even after expanding (EOF)
        break;
    }
    // rest as before
}
...