CSV Reader empty values java - java

I have this CSV:
0,102000082,,2,125,'Battery location','Left-hand drive',2,2
0,300000029,102000082,3,895,'Behind the cab','Left',2,-7
0,102000082,,4,127,'Battery location','Right-hand drive',4,4
^-----
I use csvReader to map to a bean
public static List<BatteryBean> loadAndRead{
File csvFilename = new File("C:\\my.csv");
CSVReader csvReader = new CSVReader(new FileReader(csvFilename));
ColumnPositionMappingStrategy strat = new ColumnPositionMappingStrategy();
strat.setType(BatteryBean.class);
String[] columns = new String[] { "ktypnr","sentenceId","parentId","sortOrder", "adjItemNoteId","sentText","itemNoteText","parentSortOrder1","parentSortOrder10" };
strat.setColumnMapping(columns);
CsvToBean csv = new CsvToBean();
List<BatteryBean> list = csv.parse(strat, csvReader);
return list;
}
public static void main(String[] args) {
try {
List<BatteryBean> list = loadAndRead("C:\\work\\battery_report_raw.csv");
for (Object object : list) {
BatteryBean bb = (BatteryBean) object;
System.out.println(bb.getKtypnr());
}
}
So the problem is that the file contains empty strings between ,, and I get an exeption at parsing :
Caused by: java.lang.NumberFormatException: For input string: ""
I resolved. I have another question
Csv file
ktypnr sentence_id parent_id sort_order adj_item_note_id sent_text iem_note_text
0 102000082 2 125 Battery location' Left-hand drive'
0 300000029 102000082 3 895 Behind the cab' Left'
0 102000082 4 127 Battery location' Right-hand drive'
0 300000029 102000082 5 898 Behind the cab' Right'
So if one sentence_id = one parent_id i should combine those two so that looks like this(example first line and second line) but I should consider also the sort_order:
0, Battery location, Left-hand drive, Behind the cab, Left
I don't know how to proceed

Change parentId to String data type in BatteryBean. It seems it is integer.

Related

How to read from a .txt file into an array of objects

I have the following sample data in a .txt file
111, Sybil, 21
112, Edith, 22
113, Mathew, 30
114, Mary, 25
the required output is
[{"number":"111","name":"Sybil","age":"21" },
{"number":"112","name":"Edith","age":"22"},
{"number":"113","name":"Mathew","age":"30"},
"number":"114","name":"Mary","age":"25"]
Sadly, I have not gone far because I cant seem to get the values out of each line. instead, this is what is displayed
[one, two, three]
private void loadFile() throws FileNotFoundException, IOException {
File txt = new File("Users.txt");
try (Scanner scan = new Scanner(txt)) {
ArrayList data = new ArrayList<>() ;
while (scan.hasNextLine()) {
data.add(scan.nextLine());
System.out.print(scan.nextLine());
}
System.out.print(data);
}
I would appreciate any help. thank you
Not too sure about the requirements. If you just need to know how to get the values out, then use String.split() combined with Scanner.nextLine().
Codes below:
private void loadFile() throws FileNotFoundException, IOException {
File txt = new File("Users.txt");
try (Scanner scan = new Scanner(txt)) {
ArrayList data = new ArrayList<>();
while (scan.hasNextLine()) {
// split the data by ", " and split at most (3-1) times
String[] input = scan.nextLine().split(", ", 3);
data.add(input[0]);
data.add(input[1]);
data.add(input[2]);
System.out.print(scan.nextLine());
}
System.out.print(data);
}
}
The output would be as below and you can further modify it yourself:
[111, Sybil, 21, 112, Edith, 22, 113, Mathew, 30, 114, Mary, 25]
However, if you need the required format as well, the closest I can get is by using a HaspMap and put it into the ArrayList.
Codes below:
private void loadFile() throws FileNotFoundException, IOException {
File txt = new File("Users.txt");
try (Scanner scan = new Scanner(txt)) {
ArrayList data = new ArrayList<>();
while (scan.hasNextLine()) {
// Create a hashmap to store data in correct format,
HashMap<String, String> info = new HashMap();
String[] input = scan.nextLine().split(", ", 3);
info.put("number", input[0]);
info.put("name", input[1]);
info.put("age", input[2]);
// Put it inside the ArrayList
data.add(info);
}
System.out.print(data);
}
}
And the output would be:
[{number=111, name=Sybil, age=21}, {number=112, name=Edith, age=22}, {number=113, name=Mathew, age=30}, {number=114, name=Mary, age=25}]
Hope this answer helps you well.
Currently, you're skipping lines. A quote from the Scanner::nextLine documentation:
This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line.
So you're adding one line to your list, and writing the next one to the console.
To get the data from each line, you can use the String::split method, which supports RegEx.
Example:
"line of my file".split(" ")
We can use streams to write some compact code.
First we define a record to hold our data.
Files.lines reads your file into memory, producing a stream of strings, one per line.
We call Stream#map to produce another stream, a series of string arrays. Each array has three elements, the three fields within each line.
We call map again, this time to produce a stream of Person objects. We construct each person object by parsing and passing to the constructor each of line’s three fields.
We call Stream#toList to collect those person objects into a list.
We call List#toString to generate text representing the contents of the list of person objects.
record Person ( int id , String name , int age ) {}
String output =
Files
.lines( Paths.of("/path/to/Users.txt" ) )
.map( line -> line.split( ", " ) )
.map( parts -> new Person(
Integer.parseInt( parts[ 0 ] ) ,
parts[ 1 ] ,
Integer.parseInt( parts[ 2 ] )
) )
.toList()
.toString()
;
If the format of the default Person#toString method does not suit you, add an override of that method to produce your desired output.

Join csv files ased on common column in java

I want to join two csv files based on a common column in. My two csv files and final csv file looks like this.
Here are the example files - 1st file looks like:
sno,first name,last name
--------------------------
1,xx,yy
2,aa,bb
2nd file looks like:
sno,place
-----------
1,pp
2,qq
Output:
sno,first name,last name,place
------------------------------
1,xx,yy,pp
2,aa,bb,qq
Code:
CSVReader r1 = new CSVReader(new FileReader("c:/csv/file1.csv"));;
CSVReader r2 = new CSVReader(new FileReader("c:/csv/file2.csv"));;
HashMap<String,String[]> dic = new HashMap<String,String[]>();
int commonCol = 1;
r1.readNext(); // skip header
String[] line = null;
while ((line = r1.readNext()) != null)
{
dic.put(line[commonCol],line)
}
commonCol = 1;
r2.readNext();
String[] line2 = null;
while ((line2 = r2.readNext()) != null)
{
if (dic.keySet().contains(line2[commonCol])
{
// append line to existing entry
}
else
{
// create a new entry and pre-pend it with default values
// for the columns of file1
}
}
foreach (String[] line : dic.valueSet())
{
// write line to the output file.
}
I don't know how to proceed further to get desired output. Any help will be appreciated.
Thanks
First, you need to use zero as your commonCol value as the first column has index zero rather than one.
if (dic.keySet().contains(line2[commonCol])
{
//Get the whole line from the first file.
String firstPart = dic.get(line2[commonCol]);
//Gets the line from the second file, without the common column.
String secondPart = String.join (Arrays.copyOfRange(line2, 1, line2.length -1), ",");
// Join together and put in Hashmap.
dic.put(line2[commonCol], String.join (firstPart, secondPart));
}
else
{
// create a new entry and pre-pend it with default values
// for the columns of file1
String firstPart = String.join(",","some", "default", "values")
String secondPart = String.join (Arrays.copyOfRange(line2, 1, line2.length -1), ",");
dic.put(line2[commonCol], String.join (firstPart, secondPart));
}

How to create Strings from a JTable txt file?

I need to read from a txt file and sort everything in different arrays or strings, allowing me to set text for my JLabels. One array/string for ID, Item Name, Price and Stock.
This is a preview of my txt file:
Here is my code to read the txt file to import it to my JTable:
String filePath = "C:\\Users\\zagad\\IdeaProjects\\DATABYTES\\stock\\consoles\\consoles.txt";
File file = new File(filePath);
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String firstLine = br.readLine().trim();
String[] columnsName = firstLine.split(", ");
DefaultTableModel model3 = (DefaultTableModel) productTable.getModel();
model3.setColumnIdentifiers(columnsName);
Object[] tableLines = br.lines().toArray();
for (int i = 0; i < tableLines.length; i++) {
String line = tableLines[i].toString().trim();
String[] dataRow = line.split("/");
model3.addRow(dataRow);
}
} catch (IOException ex) {
ex.printStackTrace();
}
How do I separate them? Any help would be appreciated.
TXT FILE:
ID , Item Name ,Price , Stock
00016 / Apple Airpods / 8999 / 20
00017 / Samsung Galaxy Buds / 6999 / 13
00018 / Apple Airpods Pro / 14999 / 5
00019 / Beats Powerbeats Pro / 13490 / 8
00020 / Sony WF-1000XM3 / 10799 / 10
It appears that the format separates each of the columns by \ so you can split the String by that. What we can do is read all lines from a given Path object which is the Path to the file. We can then skip the first line which we know is the table column names. We can then map each of these lines which are individual String objects to a String array by removing all whitespace with the replaceAll reference and then use the String#split method to split the line by \ which will give us each of the columns for each row. We can then collect all of these String arrays to a List using the Stream#collect method.
List<String> lines = Files.readAllLines(Paths.get("first.txt"));
String[] columnNames = lines.stream().findFirst().orElseThrow(IOException::new).split(",");
List<MyRow> rows = lines
.stream()
.skip(1)
.map(line -> line.replaceAll(" ", "").split("/"))
.map(MyRow::valueOf)
.collect(Collectors.toList());
DefaultTableModel model3 = new DefaultTableModel();
model3.setColumnIdentifiers(columnNames);
rows.forEach(row -> model3.addRow(new Object[] { row.getId(), row.getItemName(), row.getPrice(), row.getStock() }));
List<Integer> ids = rows.stream().map(MyRow::getId).collect(Collectors.toList());
Output:
[00016, AppleAirpods, 8999, 20]
[00017, SamsungGalaxyBuds, 6999, 13]
[00018, AppleAirpodsPro, 14999, 5]
[00019, BeatsPowerbeatsPro, 13490, 8]
[00020, SonyWF-1000XM3, 10799, 10]

Reading txt file, then re organizing it to an array

So basically what I need to do is:
Read a text file like this:
[Student ID], [Student Name], Asg 1, 10, Asg 2, 10, Midterm, 40, Final, 40
01234567, Timture Choi, 99.5, 97, 100.0, 99.0
02345678, Elaine Tam, 89.5, 88.5, 99.0, 100
and present it like this (with calculations of rank and average):
ID Name Asg 1 Asg 2 Midterm Final Overall Rank
01234567 Timture Choi 99.5 97.0 100.0 99.0 99.3 1
02345678
Elaine Tam 89.5 88.5 99.0 100.0 97.4 2
Average: 94.5 92.75 99.5 99.5 98.3
Using printf() function
now this is what I have done so far:
import java.io.*;
import java.util.Scanner;
class AssignmentGrades {
public static void main(String args[]) throws Exception {
Scanner filename = new Scanner(System.in);
String fn = filename.nextLine(); //scannig the file name
System.out.println("Enter your name of file : ");
FileReader fr = new FileReader(fn+".txt");
BufferedReader br = new BufferedReader (fr);
String list;
while((list = br.readLine()) !=null) {
System.out.println(list);
}
fr.close();
}
}
So I can ask the user for the name of the file, then read it and print.
Now.. I'm stuck. I think I need to probably put it in to array and split?
String firstrow = br.readLine();
String[] firstrow = firstrow.split(", ");
something like that?.. ugh ive been stuck here for more than an hour
I really need help!! I appreciate your attention!! ( I started to learn java this week)
There are two ways for splitting the input line just read from the file
Using String object's split() method which would return an array. Read more about the split here.
StringTokenizer Class - This class can be used to divide the input string into separate tokens based on a set of delimeter. Here is a good tutorial to get started.
You should be able to get more examples using google :)
In case you want to parse integers from String. Check this.
Here I store the columns as an array of Strings and I store the record set as an ArrayList of String arrays. In the while loop if the column set is not initialized yet (first iteration) I initialize it with the split. Otherwise I add the split to the ArrayList. Import java.util.ArrayList.
String[] columns = null;
ArrayList<String[]> values = new ArrayList<String[]>();
String list;
while((list = br.readLine()) !=null) {
if (columns != null) {
columns = list.split(", ");
} else {
values.add(list.split(", "));
}
}
fr.close();

ArrayIndexOutOfBoundsException in Java when using split

I am trying to read file and split its line to get some context(Computer Name and Date), the code gives few lines of outputs then gives the following exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at FILE_MAIN.getComputerName(FILE_MAIN.java:34)
at FILE_MAIN.readFiles(FILE_MAIN.java:24)
at FILE_MAIN.main(FILE_MAIN.java:12)
Code:
import java.util.*;
import java.io.*;
import java.util.Scanner;
public class FILE_MAIN
{
public static void main(String[] args) throws FileNotFoundException
{
File folder = new File("folderName/");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++)
{
readFiles(listOfFiles[i].getName());
}
}
public static void readFiles(String fileName) throws FileNotFoundException
{
FileReader dataFile = new FileReader("yukt/"+fileName);
try (Scanner FileRead = new Scanner(dataFile))
{
while (FileRead.hasNextLine() && FileRead.nextLine().isEmpty()==false)
{
String[] split;
String line = FileRead.nextLine();
split = line.split("\\|",-1);
String computerName=getComputerName(split[0]);
System.out.println(computerName);
}
}
}
public static String getComputerName(String splited)
{
String[] split1;
String[] split2;
split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1);
return("a");
}
public static String getDate(String splited)
{
String[] split1=splited.split("\\(",-1);
String[] split2=split1[1].split("\\ ",-1);
return(split2[0]);
}
}
The main function gets names of the files in a folder, and passes each file to the readFiles function where each line is split into 3 parts by a delimeter(|) and parts are send to getComputerName and getDate function which returns its values after further splitting the strings.
Here is an example of a line of the file, all the lines are similar to this:
[CD8C] ComputerName:NITIN UserID:GO ankurjain Station 9900 LanId: | (11/24 19:50:30) | Client is disconnected from agent.
There is no protection for split1 containing a single element:
split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1); // Accesses second element of split1
Add protection and decide if it is an error for there to be no : in the input string or just use whole string if no ::
split1=splited.split("\\:",-1);
if (split1.length > 1)
{
split2=split1[1].split("\\ ",-1);
}
split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1);
split1 must not be doing what you think.
i.e. it is not splitting, cos split1[1] is not valid.
You should really check the result of the first split before trying to use it's results.
I had similar issue where I had to check weather string sub part contains given string or not. But String in question had many variation. Instead of using if loop I used ternary operator -
StringUtils.containsIgnoreCase("Test String",
("split me".split(":").length > 1)
? "split me".split(":")[1] : "Can't split")
split2=split1[1] gives you java.lang.ArrayIndexOutOfBoundsException: 1 the error. The Array does not have 2 elements so index on 1 will throw an error.
You could add a check to make sure it has atleast 2 elements by putting the assignement in a if statement
if (split1.lenght > 1){
split2=split1[1].split("\\ ",-1);
}

Categories