2010-09-21 2 views
0

Для моего проекта структур данных цель состоит в том, чтобы читать в предоставленном файле, содержащем более 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. Хотя я могу видеть его точку зрения, используя этот пример кода, как я могу быть более защищенным, чтобы допускать несоответствия ввода?

+0

Это открытый вопрос для того, чтобы сделать ваш код «лучше». Подумайте о том, чтобы сделать его Wiki сообщества? – pascal

ответ

2

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

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, и файл не заканчивается на «. Там вы получите исключение. еще один чек на hasNextLine()

+0

Я выбрал ваш ответ как ответ, так как, хотя я не использовал его в текущем проекте, вы дали мне конкретный пример для работы с ошибками ввода пользователя без сбоя программы. – Jason

4

Я хотел бы заменить, например:

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

с

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

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

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

Может ли регулярное выражение быть оптимизировано или оно построено для каждой итерации? –

+0

@Thorborn - это не влияет на надежность кода ... только его производительность. И даже тогда, не так много. (IIRC, метод Pattern.compile использует простой кег с одним регулярным выражением, чтобы избежать повторной компиляции одного и того же регулярного выражения. В этом случае это было бы эффективно.) –

+0

Спасибо, например, вы мне задумались. – Jason

2

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

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

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

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

+0

Это именно то, почему мне нравится этот сайт. Я думаю, что я сталкиваюсь с некоторыми недостатками в том, как эта программа CS разработана. Кажется, что больше заинтересованы в получении общих понятий в первую очередь, а затем в деталях, но помимо раздаточного материала по синтаксису кода и пробелам, очень мало внимания уделяется надлежащим процедурам, таким как защитное кодирование. – Jason

0

Вот некоторые вопросы, которые могут быть рассмотрены:

  • Ваш код предполагает, что не существует никаких пробелов до (например) «ХУДОЖНИК», ни один вокруг знака «=» и так далее.

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

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

Наконец, я не уверен, что замена «еще, если» с «если» в этом случае имеет сделал никакой разницы в надежности этого кода.

1

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

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

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

Что произойдет, если есть неизвестное поле - возможно, орфографическая ошибка? Он будет добавлен в конец Текстов, что кажется неправильным. Только после того, как поле LYRICS будет найдено, добавьте его. Если лирика имеет значение null, она начинается с «null».

0

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

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

Ничего не мешает artist или title от пустого.

Смежные вопросы