#java #csv #file-io #null #readline
#java #csv #file-io #null #readline
Вопрос:
Предполагается, что метод numberOfFields() определяет, сколько столбцов существует в определенной строке csv-файла. Я ожидаю 7, но мой вывод получается равным 0; именно так я инициализировал cols. Итак, я использовал system.out.println() внутри цикла while и выяснил, что цикл while не вводится. В моем файле много строк текста, поэтому я не понимаю, почему readLine() возвращает null. Не уверен, где еще я могу ошибаться.
public class CSVReader {
public BufferedReader bR1;
public CSVReader(Strin& fileName) throws IOException {
bR1 = new BufferedReader(new FileReader(fileName));
}
public int numberOfFields(int row) throws IOException {
int rows = 1;
while (rows < row) {
bR1.readLine();
rows ;
}
int cols = 0;
Strin& line;
while ((line=bR1.readLine()) != null) {
Strin&Tokenizer st = new Strin&Tokenizer(line, ",");
while (st.hasMoreElements()) {
st.nextToken();
cols ;
}
}
return cols;
Комментарии:
1. Насколько я могу судить, это зависит от того, как вы вызываете свой
numberOfFields
метод. Для чего это значениеrow
? Потому что, если вы пропустите весь CSV-файл в первом цикле while, во втором цикле while не останется строк для чтения читателем. Вам следует изучить это поведение и, возможно, объяснить, чего вы пытаетесь достичь с помощью первого цикла.2. Если вы вызываете
numberOfFields()
более одного раза, все вызовы, кроме первого, завершатся неудачей, посколькуbR1
больше не располагается в начале файла. На самом деле он расположен в конце файла, поскольку именно там первый вызов покинул программу чтения.3. @Andreas На самом деле я вызываю этот и другой метод (numberOfRows()) более одного раза, и я полагаю, что вы разобрались с проблемой. Прямо сейчас указатель находится в конце файла после вызова функции numberOfRows() для определения количества строк в файле. Есть ли способ переместить указатель на начало файла?
4. @maloomeister вызов был: numberOfFields(10); где я хочу узнать количество полей в 10-й строке. Цель первого цикла while (rows<строка) — поместить мой указатель на строку прямо перед строкой, в которой мне нужно найти количество полей, чтобы затем я мог использовать Strin&Tokenizer. Кроме того, файл содержит 214 строк, поэтому не должно быть никаких проблем с отсутствием строк для чтения.
Ответ №1:
На мой взгляд, могут быть две причины :
- заданный вами параметр
row
превышает номер строки файла. - ваше имя файла неверно.
Я предлагаю вам добавить System.out.println(bR1.readLine)
в первый цикл while, чтобы посмотреть, что произошло.
Комментарии:
1. На мой взгляд, причина в том, что
numberOfFields()
вызывается более одного раза.2. Итак, я сделал то, что вы предложили, и получил null в качестве выходных данных. Но я думаю, что это из-за того, что упомянул Андреас. После вызова метода для определения количества строк мой указатель теперь находится в конце файла и, следовательно, равен null. Есть ли способ переместить указатель на начало файла?
3. BufferedReader.mark(int) и BufferedReader.reset() могут выполнять this.@eva
Ответ №2:
InputStream
Может быть прочитан только один раз.
Если вы вызываете numberOfFields()
более одного раза, все вызовы, кроме первого, завершатся неудачей, поскольку bR1
больше не располагается в начале файла. На самом деле он расположен в конце файла, поскольку именно там первый вызов покинул программу чтения.
Вместо открытия потока в конструкторе, пусть каждый метод откроет свой собственный поток.
В дальнейшем эти проблемы были исправлены:
-
Использование try-with-resources для правильной обработки закрытия потока.
Функция Try-with-resources была добавлена в Java 7, поэтому, если вы не работаете на старых версиях Java, нет абсолютно никаких веских причин использовать ее.
-
Изменен код, чтобы считать только столбцы строки запроса, а не столбцы всех оставшихся строк.
-
Использование
Strin&Tokenizer
было заменено регулярным выражением. Как говорит javadoc изStrin&Tokenizer
:Strin&Tokenizer
это устаревший класс, который сохраняется по соображениям совместимости, хотя его использование не рекомендуется в новом коде. Рекомендуется, чтобы все, кто ищет эту функциональность, использовали вместоsplit
методаStrin&
илиjava.util.re&ex
пакета.
public class CSVReader {
public final Strin& fileName;
public CSVReader(Strin& fileName) {
this.fileName = fileName;
}
public int numberOfFields(int row) throws IOException {
try (BufferedReader bR1 = new BufferedReader(new FileReader(this.fileName))) {
// Skip row-1 rows
for (int rows = 1; rows < row; rows ) {
bR1.readLine();
}
// Count number of columns in next line, if available
Strin& line = bR1.readLine();
return (line == null ? 0 : line.split(",", -1).len&th);
}
}