Как прочитать файл с несколькими типами данных в ArrayList с помощью Scanner

Я пытаюсь прочитать файл с несколькими типами данных в объект ArrayList, используя Scanner с разделителем «\ s \ s», однако, похоже, он не работает должным образом. Я использую printf для просмотра, будут ли данные храниться правильно, данные, которые я буду использовать для расчетов позже. Данные отображаются правильно, однако я все еще получаю исключение «Неверный формат файла». Также, кажется, есть проблема с циклом. Я всегда застреваю при использовании ArrayList объектов.

Пример текстового файла:

item  item descr  100  1.50
item2  item descr  250  2.50
item2  item descr  250  3.50

Код:

import java.io.*;
import java.util.*;

public class ReadItems
{

    private Scanner input;
    ArrayList<Item> item = new ArrayList<Item>();

    //open text file
    public void openFile()
    {
        try
        {
            FileReader in = new FileReader("Items.txt");
            input = new Scanner(in).useDelimiter("\\s\\s");
        }
        catch( FileNotFoundException fileNotFound)
        {
            System.err.println( "Error opening file.");
            System.exit(1);
        }
    }

    //read file
    public void readFile()
    {
        try
        {
            while ( input.hasNextLine())
            {
                item.add( new Item(input.next(), input.next(), input.nextInt(), input.nextFloat() ));                                       
                for (Item list : item) 
                {
                    System.out.printf("%-10s%-48s$%5.2f\n", list.getCode(), (list.getDecription()+ ", "+ list.getWeight()+ "g"), + list.getPrice());
                    //System.out.println(item);
                }

            }

        }
        catch ( NoSuchElementException elementEx)
        {
            System.err.println( "Incorrect file format.");
            System.exit(1);
        }
        catch ( IllegalStateException stateEx )
        {
            System.err.println( "Error reading from file.");
            System.exit(1);
        }

    }

    public void closeFile()
    {
        if (input != null)
            input.close();      
    }

}

Выход:

item      item descr, 100g                                $ 1.50
item      item descr, 100g                                $ 1.50
item2     item descr, 250g                                $ 2.50
item      item descr, 100g                                $ 1.50
item2     item descr, 250g                                $ 2.50
item2     item descr, 250g                                $ 3.50

Неверный формат файла.

Извините, кажется, я сделал глупость. Я не запускал программу через свой тестовый класс, где находится main.

Тестовый класс:

public class TestReadItems
{

public static void main(String[] args) 
{
ReadItems application = new ReadItems();
application.openFile();
application.readFile();
application.closeFile();
}
}

Программа работает без ошибок, однако я не могу заставить цикл while работать должным образом. Выход увеличивается втрое.


person xiphias    schedule 10.03.2012    source источник


Ответы (2)


Это потому, что ваш цикл for для печати вывода находится внутри цикла while. Итак, он читает каждую строку файла и возвращает результат. Итак, чтобы исправить, замените выходной цикл for внутри оператора while и запишите его после завершения цикла while.

person SDesai    schedule 22.10.2012
comment
Да, я смотрю на этот SSCCE и думаю про себя, я написал это или задал этот вопрос? Удивительно, как многому можно научиться за несколько месяцев :) - person xiphias; 23.10.2012

Цикл также может взорваться мусором в конце файла. Я добавил вызов .nextLine() после вызова item.add(), теперь он у меня работает нормально.

while ( input.hasNextLine()) {
    item.add( new Item(input.next(), input.next(), input.nextInt(), input.nextFloat() ));                                       
    for (Item list : item) {
        System.out.printf("%-10s%-48s$%5.2f\n", list.getCode(), (list.getDecription()+ ", "+ list.getWeight()+ "g"), + list.getPrice());
    }
    input.nextLine(); // added
}
person Adam    schedule 11.03.2012
comment
разве \\s не реализует все пробельные символы (пробелы, табуляции, новые строки)? Поэтому я считаю, что \n не имеет значения. Также я использую input.hasNextLine(). Я пробовал, тот же результат. Есть комментарии по поводу цикла while? - person xiphias; 11.03.2012
comment
Я немного задержался с комментарием. Как это работает для вас? С чего бы это? хм - person xiphias; 11.03.2012
comment
Я уже пытался изменить разделитель на \\s\\s|\n, поскольку это было моей первой мыслью, однако это не имело значения. - person Adam; 11.03.2012
comment
Предложенное мной изменение работает для меня, но не для вас, что предполагает некоторую разницу в пробелах, не отображаемую в данных образца. Не могли бы вы прикрепить свой Sample.txt или загрузить его куда-нибудь, чтобы мы могли его увидеть? - person Adam; 11.03.2012
comment
Для простоты я использую только одну строку в своем тестировании. - person xiphias; 11.03.2012
comment
должно быть два пробела, не знаю, почему так получилось. - person xiphias; 11.03.2012
comment
Та же ошибка, когда в описании предмета есть два или более пробела, таких как item item descr, type 100 1.50, я думаю, что попробую другой подход к этому. Может быть, обрабатывать все типы как строки и потом приводить. - person xiphias; 11.03.2012
comment
Я заставил его работать, используя input.nextLine();, как вы предложили, но у меня все еще есть проблема с циклом. Кажется, последние часы я разговаривал сам с собой :( Является ли мой вопрос базовым? Я озадачен, хотя это должно сработать, не так ли? - person xiphias; 11.03.2012
comment
input.nextLine(); работает, когда в последней строке текста есть символ \n. Я использовал блокнот ++, чтобы просмотреть все символы в других, чтобы понять это. - person xiphias; 11.03.2012
comment
Необходимо удалить оператор печати из внутреннего цикла. - person xiphias; 12.03.2012