Как еще можно оптимизировать этот код для защитного программирования?

Для моего проекта структур данных цель состоит в том, чтобы прочитать в предоставленном файле, содержащем более 10000 песен, с четко обозначенным исполнителем, названием и текстом, и каждая песня отделена строкой с одной двойной кавычкой. Я написал этот код для разбора текстового файла, и он работает со временем выполнения чуть менее 3 секунд, чтобы
прочитайте 422K строк текста
создать объект Song
добавить сказанную песню в ArrayList

Код синтаксического анализа, который я написал:

if (songSource.canRead()) {  //checks to see if file is valid to read
    readIn= new Scanner(songSource);
    while (readIn.hasNextLine()) {
 do {
     readToken= readIn.nextLine();

             if (readToken.startsWith("ARTIST=\"")) {
  artist= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("TITLE=\"")) {
  title= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("LYRICS=\"")) {
  lyrics= readToken.split("\"")[1];
      } else {
  lyrics+= "\n"+readToken;
      }//end individual song if block
 } while (!readToken.startsWith("\"")); //end inner while loop

    songList.add(new Song(artist, title, lyrics));

    }//end while not EOF 
} //end if file can be read 

Я говорил с моим профессором "Введение в алгоритмы" о коде для этого проекта, и он заявил, что я должен стараться быть более осторожным в своем коде, чтобы учесть несоответствия в данных, предоставленных другими людьми. Первоначально я использовал блоки if/else между полями Artist, Title и Lyrics, и по его предложению я изменил на последовательные выражения if. Хотя я могу понять его точку зрения, используя этот пример кода, как я могу быть более осторожным в отношении учета несоответствий ввода?

6 ответов

Решение

Вы предполагаете, что ввод идеален. Если вы посмотрите на то, как ваше приложение в настоящее время настроено, на основании быстрого чтения вашего алгоритма данные будут выглядеть так

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"

Но рассмотрим случай

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"
ARTIST="Peter"
LYRICS="Sing Song All night long"
"

Основываясь на вашем алгоритме, теперь у вас есть 2 песни, которые характеризуются как

songList = { Song("JOHN", "HELLO WORLD", "Sing Song All night long"),
             Song("Peter", "HELLO WORLD", "Sing Song All night long") }

В текущем алгоритме, художник и название выставляются и будут отображаться во 2-й песне, даже если они не были определены. Вам нужно сбросить три переменные.

в другом вы просто добавляете полную строку в тексты песен. Что, если вы уже вытащили тексты песен, теперь вы переопределяете это. Прецедент

 ARTIST="John"
 LYRICS="Sing Song All night long"
 TILET="HELLO WORLD"
 "

Рассмотрите возможность отправки этой записи в состояние ошибки. Поэтому, когда пакетное чтение завершено, отчет об ошибке может быть сгенерирован и исправлен.

Также вы рассматриваете EOF только после того, как художник был прочитан. Что, если EOF происходит во время чтения Artist, а файл не заканчивается на ". Вы собираетесь получить исключение там. В вашем do/while добавьте еще одну проверку для hasNextLine()

Я бы заменил например:

artist= readToken.split("\"")[1];

с

String[] parts = readToken.split("\"");
if(parts.length >= 2) artist = parts[1];
else continue;

Другие модификации будут включать:

  1. сбросить локальные переменные (чтобы случайно не выбрать исполнителя для песни, если для первой песни не указан исполнитель)
  2. решить, что делать, если некоторые данные отсутствуют - вы все еще хотите добавить песню в список песен?

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

Например, когда компилятор кода компилятора или оболочка, выполняющая сценарий, обнаруживают несоответствие, он может остановить и распечатать строку, содержащую несоответствие, со второй строкой под ним, которая использует символ "^" для указания местоположения проблемы.

Итак, вот несколько основных вопросов, которые нужно задать себе:
1. Гарантируется ли каждая строка каждого поля?
2. Гарантирован ли порядок полей?

Если это условия входного контракта и они нарушены, вам следует игнорировать / сообщать о строке. Если они не являются условиями ввода, то вам нужно обработать это.. что вы в настоящее время не делаете.

Я вижу пару вещей, которые здесь отсутствуют, Джейсон.

Я думаю, что если / еще было хорошо, и это не изменит логику. Однако вы должны максимально ограничить область действия ваших переменных. Объявляя Artist, Title и т. Д. Внутри цикла while, они будут инициализированы нулем (или чем-то еще), поэтому, если в записи отсутствует исполнитель, она не получит значение последней записи.

Кроме того, что произойдет, если в названии, исполнителе и т. Д. Есть цитата? Как это обрабатывается? Как насчет Лирики, которая, кажется, состоит из нескольких строк правильно?

Что произойдет, если есть неизвестное поле - возможно, опечатка? Это будет добавлено в конец Лирики, которая кажется неправильной. Только после того, как поле LYRICS было найдено, вы можете добавить к нему. Если лирика нулевая, то она начнется с "нулевой".

Разобраться с исключениями (я полагаю, сканер может вызвать исключение InputMismatchException для недопустимого символа).

Похоже, do { } while (...) может зацикливаться бесконечно, если файл плохо сформирован, и конец файла достигнут.

Ничто не мешает artist или же title от того, чтобы быть пустым.

Вот несколько вопросов, которые можно решить:

  • В вашем коде предполагается, что перед (например) "ARTIST" нет пробелов, нет знака "=" и т. Д.

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

  • Ваш код предполагает, что строка, которая не начинается с keyword=\" является продолжением песни. Но что, если пользователь вошел ARTOST="Sting"? Или что, если пользователь попытался использовать две строки для имени исполнителя?

Наконец, я не уверен, что замена "else if" на "if" в этом случае повлияла на надежность кода.

Другие вопросы по тегам