Введение
В этом практическом занятии (лабораторной работе) мы научимся считывать CSV (Comma-Separated Values, значения, разделенные запятыми) файлы на Java. CSV - это распространенный формат файлов, используемый для хранения табличных данных, таких как электронные таблицы или экспорт из базы данных. Каждая строка в CSV файле представляет строку данных, а столбцы разделены запятыми.
Мы рассмотрим три различных подхода к считыванию CSV файлов на Java:
- Использование класса
BufferedReaderиз пакетаjava.io - Использование класса
Scannerиз пакетаjava.util - Использование библиотеки OpenCSV, популярной сторонней библиотеки для обработки CSV файлов
К концу этого практического занятия (лабораторной работы) вы сможете выбрать наиболее подходящий метод для считывания CSV файлов в своих Java-приложениях, основываясь на своих конкретных требованиях.
Создание примерного CSV-файла и структуры проекта
Перед тем, как мы начнем считывать CSV-файлы, убедимся, что наш проект настроен правильно. На этом этапе мы рассмотрим структуру нашего CSV-файла и создадим наш основный Java-класс.
Понимание CSV-файлов
CSV (Comma-Separated Values, значения, разделенные запятыми) файл хранит табличные данные в простом текстовом формате. Каждая строка представляет строку таблицы, а столбцы разделены запятыми. CSV-файлы широко используются для обмена данными из-за их простоты и совместимости с множеством приложений, таких как Excel, Google Sheets и системы управления базами данных.
Просмотр нашего примерного CSV-файла
В нашей лабораторной среде уже есть примерный CSV-файл по пути ~/project/sample.csv. Давайте сначала посмотрим на его содержимое:
cat ~/project/sample.csv
Вы должны увидеть следующий вывод:
name,age,city
John,25,New York
Alice,30,Los Angeles
Bob,28,Chicago
Eve,22,Boston
Этот CSV-файл содержит четыре строки данных (включая строку заголовка) с информацией о людях, их возрасте и городах проживания.
Создание нашего Java-класса
Теперь давайте создадим новый Java-класс с именем CSVReaderDemo.java в директории src, который мы будем использовать на протяжении всего практического занятия (лабораторной работы).
В VSCode нажмите на значок проводника в боковой панели, перейдите в директорию ~/project/src, щелкните правой кнопкой мыши по ней и выберите "New File" (Новый файл). Назовите файл CSVReaderDemo.java.
Добавьте в файл следующую базовую структуру:
public class CSVReaderDemo {
public static void main(String[] args) {
System.out.println("CSV Reader Demo");
// Мы добавим код для чтения CSV-файла на следующих этапах
}
}

Давайте скомпилируем и запустим наш Java-класс, чтобы убедиться, что все настроено правильно:
cd ~/project
javac -d . src/CSVReaderDemo.java
java CSVReaderDemo
Вы должны увидеть вывод:
CSV Reader Demo
Отлично! Теперь наша структура проекта готова. На следующих этапах мы реализуем различные методы для чтения нашего CSV-файла.
Чтение CSV-файлов с использованием BufferedReader
На этом этапе мы реализуем наш первый подход к чтению CSV-файлов с использованием класса BufferedReader из пакета java.io. Это распространенный и простой метод для чтения текстовых файлов на Java.
Понимание BufferedReader
BufferedReader - это класс, который читает текст из символьного входного потока, буферизируя символы для эффективного чтения символов, массивов и строк. Размер буфера можно указать или использовать размер по умолчанию.
Реализация чтения CSV с использованием BufferedReader
Давайте обновим файл CSVReaderDemo.java, чтобы прочитать CSV-файл с использованием BufferedReader. Замените весь контент файла следующим кодом:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CSVReaderDemo {
public static void main(String[] args) {
System.out.println("Reading CSV using BufferedReader");
// Path to our CSV file
String csvFile = "sample.csv";
// Lists to store our data
List<List<String>> data = new ArrayList<>();
// Try-with-resources to ensure the reader gets closed automatically
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
String line;
// Read each line from the file
while ((line = br.readLine()) != null) {
// Split the line by comma and convert to a List
String[] values = line.split(",");
List<String> lineData = Arrays.asList(values);
// Add the line data to our main list
data.add(lineData);
}
// Print the data we read
System.out.println("\nData read from CSV file:");
for (int i = 0; i < data.size(); i++) {
List<String> row = data.get(i);
System.out.println("Row " + i + ": " + String.join(", ", row));
}
} catch (IOException e) {
System.err.println("Error reading the CSV file: " + e.getMessage());
e.printStackTrace();
}
}
}

Давайте скомпилируем и запустим наш обновленный код:
cd ~/project
javac -d . src/CSVReaderDemo.java
java CSVReaderDemo
Вы должны увидеть вывод, похожий на следующий:
Reading CSV using BufferedReader
Data read from CSV file:
Row 0: name, age, city
Row 1: John, 25, New York
Row 2: Alice, 30, Los Angeles
Row 3: Bob, 28, Chicago
Row 4: Eve, 22, Boston
Пояснение к коду
- Мы импортируем необходимые Java-классы для операций ввода-вывода файлов и структур данных.
- Мы определяем путь к нашему CSV-файлу (
sample.csv). - Мы создаем
List<List<String>>для хранения наших CSV-данных в виде двумерного списка. - Мы используем блок try-with-resources для автоматического закрытия
BufferedReaderпосле использования. - Мы читаем каждую строку из файла с помощью
br.readLine(). - Для каждой строки мы разделяем ее по запятым с использованием
line.split(",")и преобразуем вList. - Мы добавляем каждую строку в наш основной список данных.
- Наконец, мы выводим данные, чтобы убедиться, что мы прочитали их правильно.
Подход с использованием BufferedReader прост и эффективен для чтения текстовых файлов, в том числе CSV-файлов. Однако он имеет ограничения при работе с более сложным форматированием CSV, например, когда поля содержат запятые или переносы строк, заключенные в кавычки.
На следующем этапе мы рассмотрим другой подход с использованием класса Scanner.
Чтение CSV-файлов с использованием Scanner
На этом этапе мы реализуем второй подход к чтению CSV-файлов с использованием класса Scanner из пакета java.util. Класс Scanner предоставляет удобный способ чтения форматированного ввода из различных источников.
Понимание Scanner
Класс Scanner разбивает входные данные на токены с использованием шаблона-разделителя, который по умолчанию соответствует пробельным символам. Затем полученные токены могут быть преобразованы в значения различных типов с помощью различных методов next.
Реализация чтения CSV с использованием Scanner
Давайте обновим файл CSVReaderDemo.java, чтобы прочитать CSV-файл с использованием Scanner. Замените весь контент файла следующим кодом:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class CSVReaderDemo {
public static void main(String[] args) {
System.out.println("Reading CSV using Scanner");
// Path to our CSV file
String csvFile = "sample.csv";
// Lists to store our data
List<List<String>> data = new ArrayList<>();
try (Scanner scanner = new Scanner(new File(csvFile))) {
// Read each line from the file
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
// Split the line by comma and convert to a List
String[] values = line.split(",");
List<String> lineData = Arrays.asList(values);
// Add the line data to our main list
data.add(lineData);
}
// Print the data we read
System.out.println("\nData read from CSV file:");
for (int i = 0; i < data.size(); i++) {
List<String> row = data.get(i);
System.out.println("Row " + i + ": " + String.join(", ", row));
}
} catch (FileNotFoundException e) {
System.err.println("CSV file not found: " + e.getMessage());
e.printStackTrace();
}
}
}
Давайте скомпилируем и запустим наш обновленный код:
cd ~/project
javac -d . src/CSVReaderDemo.java
java CSVReaderDemo
Вы должны увидеть вывод, похожий на следующий:
Reading CSV using Scanner
Data read from CSV file:
Row 0: name, age, city
Row 1: John, 25, New York
Row 2: Alice, 30, Los Angeles
Row 3: Bob, 28, Chicago
Row 4: Eve, 22, Boston
Пояснение к коду
- Мы импортируем необходимые Java-классы для операций с файлами,
Scannerи структур данных. - Мы определяем путь к нашему CSV-файлу (
sample.csv). - Мы создаем
List<List<String>>для хранения наших CSV-данных в виде двумерного списка. - Мы используем блок try-with-resources для автоматического закрытия
Scannerпосле использования. - Мы читаем каждую строку из файла с помощью
scanner.nextLine(), покаscanner.hasNextLine()возвращаетtrue. - Для каждой строки мы разделяем ее по запятым с использованием
line.split(",")и преобразуем вList. - Мы добавляем каждую строку в наш основной список данных.
- Наконец, мы выводим данные, чтобы убедиться, что мы прочитали их правильно.
Подход с использованием Scanner похож на подход с BufferedReader, но предоставляет более удобные методы для разбора различных типов данных. Однако, как и BufferedReader, он имеет ограничения при работе с сложным форматированием CSV.
На следующем этапе мы рассмотрим более надежный подход с использованием библиотеки OpenCSV, которая более эффективно обрабатывает сложное форматирование CSV.
Чтение CSV-файлов с использованием библиотеки OpenCSV
На этом этапе мы реализуем третий подход к чтению CSV-файлов с использованием библиотеки OpenCSV. OpenCSV - это сторонняя библиотека, которая предоставляет надежные возможности парсинга CSV, обрабатывая сложные сценарии, такие как поля, содержащие запятые или переносы строк, заключенные в кавычки.
Понимание OpenCSV
OpenCSV - это библиотека для парсинга CSV на Java, которая поддерживает все основные вариации формата CSV. В отличие от предыдущих подходов, OpenCSV правильно обрабатывает поля в кавычках, содержащие запятые, разрывы строк и другие специальные символы, которые иначе могут нарушить простое разделение по запятым.
Настройка OpenCSV
Сначала давайте скачаем библиотеку OpenCSV и ее зависимости:
cd ~/project
mkdir -p lib
curl -L -o lib/opencsv-5.7.1.jar https://repo1.maven.org/maven2/com/opencsv/opencsv/5.7.1/opencsv-5.7.1.jar
curl -L -o lib/commons-lang3-3.12.0.jar https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar
curl -L -o lib/commons-text-1.10.0.jar https://repo1.maven.org/maven2/org/apache/commons/commons-text/1.10.0/commons-text-1.10.0.jar
curl -L -o lib/commons-beanutils-1.9.4.jar https://repo1.maven.org/maven2/commons-beanutils/commons-beanutils/1.9.4/commons-beanutils-1.9.4.jar
curl -L -o lib/commons-collections-3.2.2.jar https://repo1.maven.org/maven2/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar
curl -L -o lib/commons-logging-1.2.jar https://repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar
Создание более сложного CSV-файла
Давайте создадим более сложный CSV-файл, который включает поля в кавычках с запятыми:
echo 'name,description,price
"Laptop","High-performance laptop, with SSD",999.99
"Smartphone","Latest model, with dual camera",499.99
"Headphones","Noise-canceling, wireless",149.99' > ~/project/products.csv
Реализация чтения CSV с использованием OpenCSV
Теперь давайте обновим файл CSVReaderDemo.java, чтобы прочитать CSV-файл с использованием OpenCSV. Замените весь контент файла следующим кодом:
import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;
import java.io.FileReader;
import java.io.IOException;
public class CSVReaderDemo {
public static void main(String[] args) {
System.out.println("Reading CSV using OpenCSV");
// Path to our CSV file with complex data
String csvFile = "products.csv";
try (CSVReader reader = new CSVReader(new FileReader(csvFile))) {
// Read and print the header
String[] header = reader.readNext();
if (header != null) {
System.out.println("\nHeader: " + String.join(", ", header));
}
// Read and print each line
String[] nextLine;
int rowNumber = 1;
System.out.println("\nData read from CSV file:");
while ((nextLine = reader.readNext()) != null) {
System.out.println("Row " + rowNumber + ":");
for (int i = 0; i < nextLine.length; i++) {
System.out.println(" " + header[i] + ": " + nextLine[i]);
}
rowNumber++;
System.out.println();
}
} catch (IOException | CsvValidationException e) {
System.err.println("Error reading the CSV file: " + e.getMessage());
e.printStackTrace();
}
}
}
Давайте скомпилируем и запустим наш обновленный код:
cd ~/project
javac -cp ".:lib/*" -d . src/CSVReaderDemo.java
java -cp ".:lib/*" CSVReaderDemo
Вы должны увидеть вывод, похожий на следующий:
Reading CSV using OpenCSV
Header: name, description, price
Data read from CSV file:
Row 1:
name: Laptop
description: High-performance laptop, with SSD
price: 999.99
Row 2:
name: Smartphone
description: Latest model, with dual camera
price: 499.99
Row 3:
name: Headphones
description: Noise-canceling, wireless
price: 149.99
Пояснение к коду
- Мы импортируем необходимые классы из библиотеки OpenCSV и пакета Java I/O.
- Мы определяем путь к нашему CSV-файлу (
products.csv). - Мы создаем объект
CSVReaderдля чтения CSV-файла. - Мы читаем строку заголовка с помощью
reader.readNext()и сохраняем ее для дальнейшего использования. - Затем мы читаем каждую последующую строку с помощью
reader.readNext()в цикле, пока не закончатся строки. - Для каждой строки мы выводим каждое поле вместе с соответствующим заголовком.
Библиотека OpenCSV автоматически обрабатывает сложное форматирование CSV, правильно парся поля с запятыми, заключенными в кавычки. Это делает ее идеальным выбором для реальных CSV-файлов, которые могут содержать сложные данные.
Преимущества OpenCSV
OpenCSV имеет несколько преимуществ по сравнению с базовыми подходами:
- Она правильно обрабатывает поля в кавычках, содержащие запятые, переносы строк и другие специальные символы.
- Она предоставляет встроенную поддержку для чтения в объекты (Java-объекты).
- Она поддерживает расширенные функции, такие как пользовательские разделители, символы кавычек и символы экранирования.
- Она эффективно обрабатывает большие CSV-файлы.
Для большинства реальных приложений, работающих с CSV-файлами, использование специальной библиотеки, такой как OpenCSV, является рекомендуемым подходом.
Резюме
В этом практическом занятии (лабораторной работе) мы рассмотрели три различных подхода к чтению CSV-файлов на Java:
- Использование BufferedReader: Простой подход с использованием стандартной библиотеки ввода-вывода Java. Он хорошо работает для простых CSV-файлов, но имеет ограничения при работе с сложным форматированием CSV.
- Использование Scanner: Другой подход с использованием стандартной утилитарной библиотеки Java. Как и
BufferedReader, он подходит для простых CSV-файлов, но не поддерживает сложное форматирование CSV. - Использование OpenCSV: Надежный подход с использованием сторонней библиотеки, специально разработанной для обработки CSV. Она обрабатывает сложное форматирование CSV, включая поля в кавычках, содержащие запятые, переносы строк и другие специальные символы.
Каждый подход имеет свои преимущества и области применения:
- BufferedReader и Scanner - хорошие выборы для простых CSV-файлов, если вы хотите избежать внешних зависимостей.
- OpenCSV - лучший выбор для реальных приложений, работающих с потенциально сложными CSV-файлами.
Понимая эти различные подходы, вы можете выбрать наиболее подходящий метод на основе своих конкретных требований и сложности ваших CSV-данных.
CSV-файлы широко используются в сценариях обработки данных, обмена данными и интеграции данных. Возможность читать и обрабатывать CSV-файлы является ценным навыком для Java-разработчиков, особенно в приложениях, ориентированных на обработку данных, и при интеграции с другими системами.



