CSV to tab delimited java in command line - java

Updated Code. This program should take the CSV file and separate it into TSV files by school,but I am not getting it to work. I am getting it to create the files correctly, but only one has any data in it...
public class Student implements Comparable<Student>{
public int id = 0;
public String name = "";
public String school = "";
public Student(int id, String name, String school){
this.id = id;
this.name = name;
this.school = school;
}
public String toString(){
return id+"\t"+name+"\t"+school;
}
#Override
public int compareTo(Student o) {
return this.school.compareTo(o.school);
}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
public class ReadCSV {
public static String CSV_FILE_PATH = "/Users/eringray/Desktop/csvtotab/input.csv";
public static void main(String[] args){
try {
BufferedReader br = new BufferedReader(new FileReader(CSV_FILE_PATH));
BufferedWriter bw = new BufferedWriter(new FileWriter(CSV_FILE_PATH + ".tsv"));
ArrayList<Student> list = new ArrayList<Student>();
String line = "";
while((line = br.readLine()) != null) {
String[] values = line.split(",");
if(values.length == 3) {
String idAsString = values[0];
String name = values[1];
String school = values[2];
int id = Integer.parseInt(idAsString);
Student s = new Student(id, name, school);
list.add(s);
}
}
Collections.sort(list);
String currentSchool = "";
for(int i = 0; i < list.size(); i++){
Student stu = list.get(i);
if(currentSchool != stu.school){
currentSchool = stu.school;
bw = new BufferedWriter(new FileWriter(CSV_FILE_PATH + stu.school + ".tsv"));
}
String lineText = stu.toString();
bw.write(lineText);
bw.newLine();
}
br.close();
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

The first thing, you have to do is reading the input file.
I think, you need to read it line by line (depends on file structure).
https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html
https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html
Next step is to seperate the data and sort it by school (if i understood your question well).
For this you have to split the data and create a class to store the information:
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String)
public Class Student{
public String name = "";
....
public Student(String name, String school, ...){}
}
When you have created a Student object for each student in the list, you have to sort the students by school:
You could implement compareable and use Collection.sort().
https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html
Last thing is to print the output, for this you have to override the toString method of the student class:
public String toString(){
return this.id+"\t"+this.name+"\t"+this.school;
}
and iterate throug the list of your students and call the toString method:
System.out.println(students.get(i).toString());
EDIT:
If you need the output in a file and not in the console, just use a fileoutputStream and a bufferedwriter to print the output of the toString method in a file.

Related

NumbersFormatException in Array List

I am attempting to put employee details from a CSV file(in the form of FirstName,LastName,DateOfBirth,SSN,Role,Salary,Zip,Phone) with salary being an int. The only problem is, each time I try and implement this code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class Driver {
//Delimiters used in the CSV file
private static final String COMMA_DELIMITER = ",";
public static void main(String args[])
{
BufferedReader br = null;
try
{
//Reading the csv file
br = new BufferedReader(new FileReader("data.csv"));
//Create List for holding Employee objects
List<Employee> empList = new ArrayList<Employee>();
String line = "";
//Read to skip the header
br.readLine();
//Reading from the second line
while ((line = br.readLine()) != null)
{
String[] employeeDetails = line.split(",");
//Save the employee details in Employee object
Employee emp = new Employee(employeeDetails[0],employeeDetails[1],
employeeDetails[2],
employeeDetails[3],
employeeDetails[4],
Integer.parseInt(employeeDetails[5]),
employeeDetails[6],
employeeDetails[7]);
empList.add(emp);
}
for(int i = 0;i<empList.size();i++){
System.out.println(empList);
}
}
catch(Exception ee)
{
ee.printStackTrace();
}
finally{
try{
br.close();
}
catch(IOException ie){
System.out.println("Error occured while closing the BufferedReader");
ie.printStackTrace();
}
}
}
}
I get a NumbersFormatException error. An employee class has been made with constructors setters and getters.
I just scanned the CSV. There is always a salary which is the root of my confusion.
You need to make sure that: Integer.parseInt(employeeDetails[5])
dosen't fail. So employeeDetails[5] must be a String that can be converted to int.
Like: "5", "123", "567"

Create and populate HashMap<Integer, ArrayList<object>>

I have an assignment for school that's all about using files, HashMap and ArrayList. This assignment requires 4 classes.
The first class is called FileReader and reads a txt file which is written line by line and each field that we need is separated by ";", for example ("Columbia University";"USA";78.86;2012). Each line contains 2 strings (university name and country) and 2 numbers (score and year). The FileReader class after reading the txt file returns its content in an arraylist.
The second class of the assignment is called UniversityScores and it has 4 fields (uniname, country, score, year), a constructor, accessor methods for all fields and a toString method.
The third class is the heart of our program. This class is called FileEditor and creates a Hashmap<Integer,ArrayList<UniversityScores>> where the key is the year field of each object and value I guess is the rest of the line. My problem is filling the right way the HashMap.
Also, my final 4th class is called FileWriter which creates a new txt and writes inside of it. All my classes work as supposed to except my FileEditor class. Any help needed. Thank you in advance!
Edit
I am supposed to write some other methods as well. For now my problem is the FileEditor class. I also posted the TestFiles class which contains the main function.
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
class FileReader{
private String fileName;
private Scanner scanner;
private File file;
private ArrayList<String> arrayList;
private String line;
public FileReader(String otherFileName){
this.fileName = otherFileName;
this.file = new File(fileName);
}
public boolean initReader(){
try {
scanner = new Scanner(file);
}
catch (FileNotFoundException e) {
System.out.println("Just caught a FileNotFoundException.");
}
if(file.exists()){
return true;
}
else{
return false;
}
}
public ArrayList<String> readFile(){
this.arrayList = new ArrayList<String>();
while (scanner.hasNextLine()) {
this.line = scanner.nextLine();
arrayList.add(line);
}
arrayList.remove(0);
//System.out.println(arrayList);
return arrayList;
}
public void closeReader(){
scanner.close();
System.out.println("Scanner closed");
}
}
‌
import java.util.ArrayList;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
class FileWriter{
private String path;
private PrintWriter writer;
private File outputFile;
public FileWriter(String otherPath){
this.path = otherPath;
this.outputFile = new File(path);
}
public boolean initWriter(){
try{
writer = new PrintWriter(path);
}
catch (FileNotFoundException e){
System.out.println("just caught an exception");
}
if(outputFile.exists()){
return true;
}
else{
return false;
}
}
public void writeFile(){
writer.println("The first line");
writer.println("The second line");
writer.println("Christos");
}
public void closeWriter(){
writer.close();
System.out.println("Writer closed");
}
}
‌
class UniversityScore{
private String name;
private String country;
private double score;
private int year;
public UniversityScore(String otherName, String otherCountry, double otherScore, int otherYear){
this.name = otherName;
this.country = otherCountry;
this.score = otherScore;
this.year = otherYear;
}
public String getName(){
return name;
}
public String getCountry(){
return country;
}
public double getScore(){
return score;
}
public int getYear(){
return year;
}
public String toString(){
String outputString = name + "\t" + country + "\t" + score + "\t" + year;
return outputString;
}
}
‌
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
class FileEditor{
private HashMap<Integer, ArrayList<UniversityScore>> scores = new HashMap<Integer, ArrayList<UniversityScore>>();
private ArrayList<String> lines;
public FileEditor(ArrayList<String> otherLines){
this.lines = otherLines;
}
public void fillHashMap(){
// that's where I need help
}
}
public class TestFiles {
public static void main(String[] args){
FileReader reader = new FileReader("universities.txt");
if(reader.initReader()){
FileEditor editor = new FileEditor(reader.readFile());
reader.closeReader();
editor.fillHashMap();
FileWriter writer = new FileWriter("universities_2015_output.txt");
if(writer.initWriter()){
writer.writeFile(editor.getScoresOfYear(2015));
writer.closeWriter();
}
else{
System.out.println("Error creating file");
}
System.out.println("Average university score of year 2015: "+editor.getAverageOfYear(2015));
System.out.println("Min university score of year 2015: "+editor.getMinOfYear(2015));
System.out.println("Max university score of year 2015: "+editor.getMaxOfYear(2015));
}
else{
System.out.println("Error opening file");
}
}
}
You will need a way to parse your lines into UniversityScore objects.
Now that you have all the scores, you can add it to your map, according to their year values (may be score but the type doesn't match nor makes practical sense), for example:
for(String line : lines){
String[] vals = line.split(";");
UniversityScore score = new UniversityScore(vals[0],vals[1],Double.parseDouble(vals[2]),Integer.parseInt(vals[3]))
if(scores.containsKey(score.getYear()){ // If the key exists
scores.get(score.getYear()).add(score);
}else{ // If the key doesn't exist, it must be created and added to the map
ArrayList<UniversityScore> newList = new ArrayList<>();
newList.add(score);
scores.put(score.getYear(), newList)
}
}
I noticed your map has an Integer key which corresponds to the year property of a score, so I assumed the map's keys are the years and not the scores as you suggested.
I didn't check if the code works, but it should at least give you an idea on how to fill your map.
It looks like you're being tasked with reading data from a file, and then generating some stats about the data in the file.
Currently, you're simply plopping each line in the ArrayList.
Looks like your next step is to go through each item in that list, and create a UniversityScore object. This is where you will have to parse each string into values that can be assigned to the various fields in the UniversityScore object. When you have done that, put the current line number (as an Integer key) and UniversityScore (as the value) in your HashMap.
Once you have done that, you will have to write the missing methods getScoresOfYear(Integer year), getAverageOfYear(int year), getMinOfYear(int year), and getMaxOfYear(int year) in the editor class.
try this:
public void fillHashMap() {
for(String line : lines) {
String [] fields = line.split(";");
UniversityScores us = new UniversityScores(fields[0], fields[1], fields[2], fields[3]);
if (scores.keySet().contains(us.getScore())) {
scores.get(us.getScore()).add(us);
}
else {
ArrayList<UniversityScores> t = new ArrayList<UniversityScores>();
t.add(us);
scores.put(us.getScore(), t);
}
}
}

How to sort both numbers and name at the same time

Currently, I'm at the point where I have only sorted the names within the file but I want to also make it so that ages can be sort. Another problem would be trying to get names that are the same but have different ages to sort. Right now my code looks something like this:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MultiKey {
public static void main(String[] args) {
File textFile = new File("H:\\Names_ages.txt");
FileReader in;
BufferedReader readFile;
String lineOfText;
try {
in = new FileReader(textFile);
readFile = new BufferedReader(in);
BufferedReader reader = new BufferedReader(new FileReader(textFile));
List<String> results = new ArrayList<String>();
while ((lineOfText = readFile.readLine()) != null) {
results.add(lineOfText);
}
Collections.sort(results);
System.out.println(results);
readFile.close();
in.close();
} catch (FileNotFoundException e){
System.out.println("File does not exist or could not be found");
System.err.println("FileNotFoundException: "+ e.getMessage());
} catch (IOException e){
System.out.println("Problem reading file");
System.err.println("IOException: " + e.getMessage());
}
}
}
Logic:
Create a separate holder for the attributes you want to have the sorting on.
Apply Comparator on that Person object.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MultiKey {
public static void main(String[] args) {
File textFile = new File("H:\\Names_ages.txt");
FileReader in;
BufferedReader readFile;
String lineOfText;
try {
in = new FileReader(textFile);
readFile = new BufferedReader(in);
BufferedReader reader = new BufferedReader(new FileReader(textFile));
List<Person> results = new ArrayList<Person>();
while ((lineOfText = readFile.readLine()) != null) {
//split here the line into name and age separate variables basedon delimiter available between them.
Person p = new Person(name,age);
results.add(p);
}
order(results);
System.out.println(results);
readFile.close();
in.close();
} catch (FileNotFoundException e){
System.out.println("File does not exist or could not be found");
System.err.println("FileNotFoundException: "+ e.getMessage());
} catch (IOException e){
System.out.println("Problem reading file");
System.err.println("IOException: " + e.getMessage());
}
}
}
private static void order(List<Person> persons) {
Collections.sort(persons, new Comparator<Person>() {
public int compare(Object o1, Object o2) {
String x1 = ((Person) o1).getName();
String x2 = ((Person) o2).getName();
int sComp = x1.compareTo(x2);
if (sComp != 0) {
return sComp;
} else {
Integer x1 = ((Person) o1).getAge();
Integer x2 = ((Person) o2).getAge();
return x1.compareTo(x2);
}
}});
}
public class Person{
private String name;
private int age;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return this.age;
}
public vois setAge(int age){
this.age = age;
}
}
Typical Approach would be:
Parse each line and create an encapsulation object for it
(in your example a class "Person" with two fields for "name" and "age")
How you do this parsing depends on the format of the lines in the file
e.g. you can use String.split(",") for this, if the values in the line
are separated by comma.
Add the encapsulation objects to a list and then e.g. sort using
a Comparator. Use java.util.Collections.sort(Comparator).
Of course, with that list of encapsulation objects you can do much more very easily, e.g. find Persons with same Name but different Ages.
You can use the thenComparing to chain Comparators
Comparator<String> byName = Comparator.comparing(s -> s.split(" ")[0]);
Comparator<String> byAge = Comparator.comparingInt(s -> Integer.parseInt(s.split(" ")[1]));
try (BufferedReader br = new BufferedReader(new FileReader("filePath"))) {
List<String> sorted = br.lines().sorted(byName.thenComparing(byAge)).collect(Collectors.toList());
return sorted;
} catch (IOException e) {
e.printStackTrace();
}
If more than one space also expected try pattern \\s+ instead of white space
or we can create a Comparator like below instead of creating two Comparators
Comparator<String> c = Comparator.<String, String> comparing(s -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1]));

Reading integers in .txt file and store in arraylist

I know this question might be answered many times. However, I still cannot solve this specific problem.
Basically I have a .txt file with the following format.
String Integer String
For example,
la 789 ferrari
turbo 560 porsche
veyron 987 bugatti
sls 563 benz
dbs 510 aston
How can I read the file line by line and store the numbers/integers ONLY into arraylist?
Thank you!
Here's a more full Java-esque solution, using Java 7 ... for fun.
Main.java
import java.util.List;
public class Main
{
private static final InputFileParser inputFileParser = new InputFileParser();
private static final EntryNumberExtractor extractor = new EntryNumberExtractor();
private static final String FILENAME = "input-file.txt";
public static void main(String... args)
{
List<Entry> entries = inputFileParser.parse(FILENAME);
List<Integer> extractedIntegers = extractor.extract(entries);
System.out.println("Entries: ");
prettyPrintListItems(entries);
System.out.println();
System.out.println("Entry numbers: ");
prettyPrintListItems(extractedIntegers);
}
private static <T> void prettyPrintListItems(List<T> list)
{
for (T item : list)
{
System.out.println(item);
}
}
}
InputFileParser.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class InputFileParser
{
public List<Entry> parse(String filename)
{
List<Entry> entries = new ArrayList<>();
File f = new File(filename);
try (BufferedReader reader = new BufferedReader(new FileReader(f));)
{
String line = null;
while ((line = reader.readLine()) != null)
{
String[] components = line.split(" ");
entries.add(new Entry(components[0], Integer.parseInt(components[1]), components[2]));
}
}
catch (IOException e)
{
e.printStackTrace();
}
return entries;
}
}
EntryNumberExtractor.java
import java.util.ArrayList;
import java.util.List;
public class EntryNumberExtractor
{
public List<Integer> extract(List<Entry> entries)
{
List<Integer> integers = new ArrayList<>();
for (Entry e : entries)
{
integers.add(e.getNumber());
}
return integers;
}
}
Entry.java
public class Entry
{
private String model;
private int number;
private String company;
public Entry(String model, int number, String company)
{
this.model = model;
this.number = number;
this.company = company;
}
public Integer getNumber()
{
return number;
}
#Override
public String toString()
{
return "model: " + model + ", number: " + number + ", company: " + company;
}
}
ArrayList<int> list = new ArrayList<int>();
try {
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
String line = br.readLine();
while(line != null)
{
String[] tokens = line.Split(" ");
list.Add(Integer.parseInt(tokens[1]));
line = br.readLine()
}
catch(Exception e)
{
//Probably a conversation exception or a index out of bounds exception
}
You can read each line and split the line string by space, retrieve the number and store it in array list

Writing class data to CSV , java

I am trying to write the data that I take in via the JOptionPane to a Csv file. Is there a way that I can just write the whole class to it rather than doing it individually?? Cant seem to get it to work
import javax.swing.*;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class AddStudent implements Serializable
{
public static void main(String[] args) throws IOException
{
Student s1 = new Student();
String id = JOptionPane.showInputDialog(null, "Enter Students ID ");
s1.setStudentName(JOptionPane.showInputDialog(null, "Enter Students name "));
s1.setStudentNumber(JOptionPane.showInputDialog(null, "Enter Students ID "));
s1.setStudentEmail(JOptionPane.showInputDialog(null, "Enter Students Email Address "));
s1.setStudentAdd(JOptionPane.showInputDialog(null, "Enter Students Home Address "));
String ProgID = JOptionPane.showInputDialog(null, "Enter the Programme code the student is taking ") ;
FileWriter fw = new FileWriter("C:\\Users\\Packard Bell\\Desktop\\ProjectOOD\\ProgrammeID.csv", true);
}
FileOutputStream fos = new FileOutputStream("ProgrammeID");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student s1 = new Student();
oos.writeObject( s1);
oos.close();
}
And here is the Student Class
class Student
{
private String _studentNumber;
private String _studentName;
private String _studentAddress;
private String _studentEmail;
public void setStudentName(String studentName)
{
_studentName = studentName;
}
public void setStudentNumber(String studentNumber)
{
_studentNumber = studentNumber;
}
public void setStudentAdd(String studentAddress)
{
_studentAddress = studentAddress;
}
public void setStudentEmail(String studentEmail)
{
_studentEmail = studentEmail;
}
public String getNumber()
{
return _studentNumber;
}
public String getName()
{
return _studentName;
}
public String getAddress()
{
return _studentAddress;
}
public String getEmail()
{
return _studentAddress;
}
}
You need to override the method
toString()
It will be called automatically when handing the object of class Student to a method which requires a String.
You can create a JPanel for entering student information.
Like the following mock-up screen shot: ( Left side are the JLabel components, on right side, they are JTextField and JTextArea components )
Once the informaiton are entered, you can create a class to include these values and then write the value into CSV.
In this way, you can enter student informaiton, like name, ID, Email address etc, on one panel, rather than using JOptionPanel, you need to enter student information individually.

Categories