ошибка java.util.NoSuchElementException, искал возможные причины, до сих пор не могу исправить

Я получаю ошибку java.util.NoSuchElementException. Мы получаем эту ошибку по следующим причинам.

  1. Если мы не проверяем, есть ли в файле следующая строка перед его чтением, то он выдает исключение после чтения последней строки, поскольку пытается прочитать несуществующую строку.
  2. Формат файла испорчен

Я думаю, что формат файла, который я использую, правильный, и я также проверяю следующую строку, прежде чем читать ее, но я все еще получаю сообщение об ошибке.

Когда я отлаживаю его с помощью оператора печати, он печатает всю строку и выдает ошибку java.util.NoSuchElementException после прочтения последней строки.

Пожалуйста, помогите мне

Вот код:

 public static void InterpretMessageFromFile() throws FileNotFoundException{

    File inputfile = new File("filepath");
    Scanner reader = new Scanner(inputfile);

   try {
        while (reader.hasNextLine()) {              
            String MessageType = reader.next();
            int IsAdd = MessageType.compareToIgnoreCase("A");
            int IsCancel = MessageType.compareToIgnoreCase("X");
            int IsDelete = MessageType.compareToIgnoreCase("D");
            int IsExecute = MessageType.compareToIgnoreCase("E");
            int IsReplace = MessageType.compareToIgnoreCase("U");

            //if the type of order is add order to existing Order Book
            if (IsAdd == 0) {
                String retrieve_ts = reader.next();
                int ts = Integer.parseInt(retrieve_ts);

                String retrieve_id = reader.next();
                int id = Integer.parseInt(retrieve_id);

                String or_side = reader.next();
                String retrieve_share = reader.next();
                int share = Integer.parseInt(retrieve_share);

                String retrieve_price = reader.next();
                int price = Integer.parseInt(retrieve_price);

                System.out.println("Add Order : Id is " + id );
                AddOrderToExistingBook.AddNewOrder(id, ts, or_side, share, price);
            }

            //if it is cancel order
            if (IsCancel == 0){
                String retrieve_ts = reader.next();
                int ts = Integer.parseInt(retrieve_ts);

                String retrieve_id = reader.next();
                int id = Integer.parseInt(retrieve_id);
                System.out.println("Cancel Order : Id is " + id + " time stamp is : " + ts );

                CancelOrder.CancelPartOfOrder(id, ts);
            }
            }
        } 
    }
    finally {
        reader.close();
    }
}

Исключение (скопировано из комментариев):

Исключение в потоке «основной» java.util.NoSuchElementException в java.util.Scanner.throwFor(Scanner.java:907) в java.util.Scanner.next(Scanner.java:1416) в OrderBook.InterpretOrderBookUpdateMessage.InterpretMessageFromFile(InterpretOrde‌​ rBookUpdateMessage.java:20) в OrderBook.MainMethod.main(MainMethod.java:50)


person user2942227    schedule 31.10.2013    source источник
comment
Показанная ошибка: исключение в потоке main java.util.NoSuchElementException в java.util.Scanner.throwFor(Scanner.java:907) в java.util.Scanner.next(Scanner.java:1416) в OrderBook.InterpretOrderBookUpdateMessage.InterpretMessageFromFile(InterpretOrderBookUpdateMessage .java:20) в OrderBook.MainMethod.main(MainMethod.java:50)   -  person user2942227    schedule 31.10.2013
comment
Вы должны отредактировать свой вопрос и процитировать свое исключение внизу в блоке кода, чтобы его было легче читать.   -  person StormeHawke    schedule 31.10.2013
comment
Поскольку вы показываете только часть файла InterpretOrde‌​rBookUpdateMessage.java, что находится в строке 20?   -  person Stefan Freitag    schedule 31.10.2013
comment
Вы должны предварять каждый вызов reader.next() условным вызовом reader.hasNextLine(), чтобы убедиться, что действительно есть еще одна строка для чтения.   -  person spot35    schedule 31.10.2013
comment
Попробуйте поставить println после каждого read.next(), чтобы увидеть, где нет элемента. Вот что означает исключение... что сканеру нечего читать.   -  person Paul Samsotha    schedule 31.10.2013
comment
Убедитесь, что самая последняя строка вашего входного файла имеет конец строки. Возможно, вам придется добавить (или, в редких случаях, удалить) это.   -  person user949300    schedule 31.10.2013
comment
Строка 20: String MessageType = reader.next();   -  person user2942227    schedule 31.10.2013
comment
Когда я помещаю оператор печати, он фактически читает и печатает каждую строку во входном файле. Он выдает это исключение после полного прочтения самой последней строки.   -  person user2942227    schedule 31.10.2013
comment
Таким образом, он в основном входит во время просмотра даже после чтения всего файла и выдает исключение в String MessageType = reader.next();...... Как мне это исправить?   -  person user2942227    schedule 31.10.2013


Ответы (1)


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

то же самое произойдет, если у вас есть пустые строки между блоками в вашем файле.

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

public boolean hasNext(String pattern) 

вместо

next()

это позволит вам смотреть вперед, не потребляя токен.

поэтому вместо:

String MessageType = reader.next();
int IsAdd = MessageType.compareToIgnoreCase("A");
int IsCancel = MessageType.compareToIgnoreCase("X");
// .... left out other classes

//if the type of order is add order to existing Order Book
if (IsAdd == 0){
    // .. do stuff
}

вы можете сделать что-то вроде:

if (reader.hasNext("A") {
    reader.next(); // consume A
    int ts = reader.nextInt(); // get id
    // ... etcetera
} else if (reader.hasNext("X") {

}

Я бы также рекомендовал вам использовать nextInt() вместо nextString, а затем вызывать parseInt.

И еще одно: вы даже можете сделать свой код более читабельным, выполнив:

if (reader.hasNext("A") {
    handleAddition(reader);
}

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

try
{
    while (reader.hasNextLine())
    {
        if (reader.hasNext("A")) {
            handleAdd(reader);
        } else if (reader.hasNext("X")) {
            handleCancel(reader);
        } else if (reader.hasNext("D")) {
            handleDelete(reader);
        } else if (reader.hasNext("E")) {
            handleExecute(reader);
        } else if (reader.hasNext("R")) {
            handleReplace(reader);
        } else {
            // unexpected token. pretty sure this is the case that triggers your exeception. 
            // basically log as info and ignore.
            reader.nextLine();
        }
    } 
}
finally
{
    reader.close();
}

Теперь ваш метод красивый и короткий, и все конкретные действия выполняются в методах с собственными именами.

единственное, в чем я не уверен на 100%, является ли хорошей практикой использование A, X, R и т. д. внутри основного цикла или фактического метода обработчика. Я предпочитаю потреблять внутри метода лично.

Надеюсь, поможет.

person Joeblade    schedule 31.10.2013
comment
Я только что понял, что ошибка исчезла, но теперь цикл while никогда не прерывается. Я думаю, что причина в том, что даже после прочтения последней строки в файле она не достигает конца файла. Он просто продолжает читать пустые символы. Как это исправить? Это просто поместило мою программу в бесконечный цикл - person user2942227; 31.10.2013
comment
хе-хе, вероятно, потому что в else {} вы должны использовать строку. На самом деле это не чтение пустых символов, а сканирование вперед, видя, что есть еще одна строка, но затем фактически не потребляя эту строку. так что следующая итерация, та же самая строка все еще существует, готовая к обработке. что-то вроде else { reader.nextLine(); ) должен заняться этим - person Joeblade; 31.10.2013