bufferedreader не перейдет на следующую строку

Добрый вечер,

Мне нужно прочитать несколько строк из файла, файл - csv, и файл имеет такую ​​структуру:

4,
Mo Farah,30,
Jessica Ennis,27,

мне нужно прочитать эти значения и поместить их в переменные, вот как я пытался это сделать:

  while(nextline != null){
           StringTokenizer st = new StringTokenizer(nextline,",");
           int size = Integer.parseInt(st.nextToken());
           System.out.println(size);

           nextline = reader.readLine();

           StringTokenizer st2 = new StringTokenizer(nextline, ","); //why???


           String name = st2.nextToken();
           System.out.println(name);
           int age = Integer.parseInt(st2.nextToken());

           System.out.println(age);

первый int (4) читается нормально, однако, если я хочу перейти к следующей строке, возникает исключение noSuchElementException, поэтому мне пришлось написать строку рядом с «// почему ???» Чтобы перейти к следующей строке, действительно ли мне нужно создавать экземпляр нового токенизатора каждый раз, когда я хочу перейти к следующей строке? или есть лучший способ сделать это?

Большое тебе спасибо


person user2209644    schedule 23.11.2013    source источник
comment
Да, вам нужно создать новый токенизатор для каждой строки (или сбросить существующий, чтобы использовать новую строку), потому что токенизатор содержит состояние, которое связано с обрабатываемой строкой.   -  person Emily L.    schedule 24.11.2013
comment
вау, это похоже на такую ​​трату, могу я попросить вас показать мне, как сбросить токен? и добавить это как ответ? Благодарность   -  person user2209644    schedule 24.11.2013
comment
Не используйте StringTokenizer - вместо этого используйте String#split, как рекомендует @Mark (хотя в его коде есть некоторые проблемы с этим).   -  person Hovercraft Full Of Eels    schedule 24.11.2013
comment
На самом деле создание объектов в Java ДЕЙСТВИТЕЛЬНО быстро. Это может показаться пустой тратой, если вы переходите с C ++, но на самом деле это совсем не бесполезно. Язык разработан для такого использования. Я только что посмотрел java-документ, функции сброса нет, просто создайте новый токенизатор.   -  person Emily L.    schedule 24.11.2013


Ответы (2)


Давайте посмотрим, что происходит

nextline = reader.readLine(); // I'm assuming you have this here
while(nextline != null){

Следующий код проанализирует строку "4," и разделит ее на токены, разделенные ,, и будет содержать 1 токен: "4":

       StringTokenizer st = new StringTokenizer(nextline,",");

Следующее будет выполнено успешно, но вы действительно должны проверить, что st.hasMoreTokens() возвращает true, прежде чем делать это. Он будет использовать токен "4" из st, который теперь не содержит токенов:

       int size = Integer.parseInt(st.nextToken());
       System.out.println(size);

       // We read the next line into "nextline", this is okay but not pretty.
       // Also you need to check that nextline is not `null` here.
       nextline = reader.readLine();

       StringTokenizer st2 = new StringTokenizer(nextline, ","); //why???

Почему?

Потому что st был сделан для синтаксического анализа строки "4,". Назначение nextline после того, как строка была проанализирована, не обновляет внутреннее состояние st (этого невозможно достичь). Это просто так не работает. Так что, если вы позвоните st.nextToken() сюда, вы получите NoSuchElementException, как вы сказали. Потому что вы уже прочитали "4" от st, а жетонов не осталось.

Если вы хотите использовать StringTokenizer, нужно сделать следующее: это приведет к синтаксическому анализу строки "Mo Farah,30," на токены: "Mo Farah" и "30":

       st = new StringTokenizer(nextline, ","); // Just parse the new line.
       // You can reuse the old st variable as it is now depleted.

Следующее теперь вернет первый токен из следующей строки, которая равна "Mo Farah". Хотя, опять же, вам действительно следует сначала проверить st.hasMoreTokens() и дать разумное сообщение об ошибке:

       String name = st.nextToken(); // Change from st2 to st
       System.out.println(name);
       int age = Integer.parseInt(st.nextToken()); // Ditto

       System.out.println(age);

Итак, краткий ответ: да, если вы хотите использовать StringTokenizer, вам нужно создать новый StringTokenizer для каждой строки. Если вас не интересуют окончания строк, вы можете просто прочитать все строки и объединить их, прежде чем передавать все в StringTokenizer.

Но проще всего использовать String tokens [] = newline.split (","); как это сделал Марк в своем ответе.

person Emily L.    schedule 23.11.2013

Если я предполагаю, что шаблон в csv всегда один и тот же ...:

  while(nextline != null){ 

      String[] lecture = reader.readLine().split(",");

       if(lecture.lenght()>0){
                  System.out.println("Name: " + lecture[0]);
               int age = Integer.parseInt(lecture[1]);//you need to int?

                  System.out.println(lecture[1]);
        }
              else
                  System.out.println("Name: " + lecture[0]);
    }

надеюсь это поможет...

person Black.Jack    schedule 23.11.2013