How to get list of variable names from Java file? - java

How can I get the list of variables from a Java file? So far, I've started by reading the file and splitting each word using spaces. unfortunately, this returns all import statements, comments..etc
public ArrayList<String> getVariables(String javaFilePath) {
ArrayList<String> variableList = new ArrayList<String>();
BufferedReader br;
try {
// creating a buffer reader from the file path
br = new BufferedReader(new FileReader(new File(javaFilePath)));
String line;
while ((line = br.readLine()) != null) {
String[] variables = line.split("\\s+");
for (String variable : variables) {
variableList.add(variable);
}
}
br.close();
} catch (FileNotFoundException e) {
logger.error("This is FileNotFoundException error : " + e.getMessage());
} catch (IOException e) {
logger.error("This is IOException error : " + e.getMessage());
}
return variableList;
}
For example: I've java file saved on C:\Sample.java. And it's code looks like this:
package com.test;
import java.io.File;
import java.io.FileInputStream;
public class Sample {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And the output using the above method returns the following:
package
com.test;
import
java.io.File;
import
java.io.FileInputStream;
public
class
Sample
{
String
name;
public
String
getName()
{
return
name;
}
public
void
setName(String
name)
{
this.name
=
name;
}
}
Question: how do I modify my method shown above in order to get only variables. For example: I want only "name" & "Sample" for the above class.

Related

How can I use Java to create a list of all the values from csv file that have the same row name

Excel file I'm using
I want to parse a csv file and extract the name, like 'chair' and then a list of each possible colour, so ['Blue','Green','Yellow']. How can I do this?
I have created a class Object, that has a 'String name' and a 'Listcolours'.
CSVReader reader = new CSVReader(new FileReader(new File(url.toURI()).getAbsolutePath()));
Object<API> listings = new ArrayList<Object>();
String [] line;
List<String> colourList = new ArrayList<>();
reader.readNext();
while ((line = reader.readNext()) != null) {
String name = line[0];
String colour = line[1];
colourList.add(operation);
Object object = new Object(name,colourList);
listings.add(object);
}
You can create a Hashmap with key as name of the item and value as list of colors available.
I hope below snippet will solve your problem. Good Luck!!
HashMap<String,List<String>> data = new HashMap<>();
String [] line;
reader.readNext();
while ((line = reader.readNext()) != null) {
String name = line[0];
String colour = line[1];
if(data.containsKey(name.toLowerCase())){
data.get(name.toLowerCase()).add(colour.toLowerCase());
}
else{
List<String> colorList = new ArrayList<>();
colorList.add(colour.toLowerCase());
data.put(name.toLowerCase(),colorList);
}
}
#g00se what do you mean by a 'stream grouping operation'
I'll show you. Actually, in your case, since you're using a proper csv API, you can leverage that to create beans first, then do the grouping. Here's what I mean by stream grouping: we create a Map<String, HouseholdObject>> (yes that's my name for your entities - pity it's got the word 'object' in it, but never mind). That collects them into groups having the same name:
package com.technojeeves.opencsvbeans;
import com.opencsv.bean.CsvToBeanBuilder;
import java.util.List;
import java.util.Map;
import static java.util.stream.Collectors.*;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class HouseholdParser {
public static void main(String[] args) {
try {
List<HouseholdObject> objects = new HouseholdParser().read(new File(args[0]));
Map<String, List<HouseholdObject>> objectsGroupedByName =
objects.stream()
.skip(1)
.collect(groupingBy(HouseholdObject::getName));
System.out.println("The following groups of household objects were found:");
objectsGroupedByName.entrySet()
.stream()
.forEach(e -> {
System.out.println(e.getKey());
e.getValue()
.stream()
.forEach(v -> System.out.printf("\t%s%n", v.getColour()));
});
} catch (Throwable t) {
t.printStackTrace();
}
}
public List<HouseholdObject> read(File file) {
try (FileReader reader = new FileReader(file)) {
return new CsvToBeanBuilder(reader).withType(HouseholdObject.class).build().parse();
} catch (IOException e) {
throw new RuntimeException("Cannot read file: " + file.getName() + e);
}
}
}
Here's the bean I made for it:
package com.technojeeves.opencsvbeans;
import com.opencsv.bean.CsvBindByPosition;
import com.opencsv.bean.CsvCustomBindByPosition;
import com.opencsv.bean.AbstractBeanField;
import com.opencsv.bean.CsvRecurse;
public class HouseholdObject {
#CsvBindByPosition(position = 0)
private String name;
#CsvBindByPosition(position = 1)
private String colour;
public HouseholdObject() {
}
public HouseholdObject(String name, String colour) {
this.name = name;
this.colour = colour;
}
public String getName() {
return this.name;
}
public String getColour() {
return this.colour;
}
public void setName(String name) {
this.name = name;
}
public void setColour(String colour) {
this.colour = colour;
}
#Override
public String toString() {
return String.format("%s=%s,%s=%s", "name", name, "colour", colour);
}
#Override
public boolean equals(Object o) {
HouseholdObject other = (HouseholdObject)o;
return name.equals(other.name) && colour.equals(other.colour);
}
#Override
public int hashCode() {
return name.hashCode() * colour.hashCode();
}
}
And here's my output with your source CSV:
The following groups of household objects were found:
Table
Purple
Pink
Chair
Blue
Green
Yellow
Door
Yellow

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]));

CSV to tab delimited java in command line

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.

OpenCsv writes wrong column names with BeanToCsv + HeaderColumnNameTranslateMappingStrategy

I'm using opencsv 3.6 in order to create a csv file starting from a java bean.
First of all, I tried this code:
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import com.opencsv.bean.BeanToCsv;
import com.opencsv.bean.HeaderColumnNameTranslateMappingStrategy;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class CustomBean {
private String name;
private String surname;
public CustomBean(String n, String s) {
this.name = n;
this.surname = s;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getSurname() {
return surname;
}
public static void main(String[] args) {
Map<String,String> mapping = new HashMap<String,String>();
mapping.put("COLUMN1","name");
mapping.put("COLUMN2","surname");
HeaderColumnNameTranslateMappingStrategy<CustomBean> strategy = new HeaderColumnNameTranslateMappingStrategy<CustomBean>();
strategy.setType(CustomBean.class);
strategy.setColumnMapping(mapping);
ArrayList<CustomBean> customUsers = new ArrayList<CustomBean>();
customUsers.add(new CustomBean("Kobe","Bryant"));
BeanToCsv<CustomBean> bean = new BeanToCsv<CustomBean>();
try {
CSVWriter writer = new CSVWriter(new FileWriter("testOut.csv"));
bean.write(strategy, writer, customUsers);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
But I had the following error:
Exception in thread "main" java.lang.RuntimeException: Error writing CSV !
at com.opencsv.bean.BeanToCsv.write(BeanToCsv.java:74)
at test.CustomBean.main(CustomBean.java:63)
Caused by: java.lang.NullPointerException
at com.opencsv.bean.HeaderColumnNameTranslateMappingStrategy.getColumnName(HeaderColumnNameTranslateMappingStrategy.java:45)
at com.opencsv.bean.HeaderColumnNameMappingStrategy.findDescriptor(HeaderColumnNameMappingStrategy.java:112)
at com.opencsv.bean.BeanToCsv.processHeader(BeanToCsv.java:103)
at com.opencsv.bean.BeanToCsv.write(BeanToCsv.java:69)
... 1 more
This happens because in opencsv source code in getColumnName method in the HeaderColumnNameTranslateMappingStrategy class there is the following line:
return col < header.length ? columnMapping.get(header[col].toUpperCase()) : null;
Therefore, header is null. This is true, in fact this class is a subclass of HeaderColumnNameMappingStrategy class that contains the header variable (String[] type) that is never initialized.
The only useful method I found in this class is captureHeader, but unfortunately it takes a CSVReader as input.
For this reason I created an empty csv file:
COLUMN1,COLUMN2
and I added the following lines at the beginning of the try/catch block:
CSVReader reader = new CSVReader(new FileReader("testIn.csv"));
strategy.captureHeader(reader);
In this way (that I really don't like because I have to create a csv file) I have no exception, but in the result csv file the name of the columns does not follow the mapping strategy:
"name","surname"
"Kobe","Bryant"
Two questions:
How can I have the expected result, i.e. the right column names in the csv file?
There is a way to not use the CSVReader class?
Looking at the source code of BeanToCsv, the processHeader(...) method does nothing with the supplied headers. Your only option is to create a custom strategy ( to avoid CSVReader ) and a custom BeanToCsv as below
public class CustomBean {
...
public static void main(String[] args) {
...
HeaderColumnNameTranslateMappingStrategy strategy = new CustomStrategy<CustomBean>();
strategy.setType(CustomBean.class);
strategy.setColumnMapping(mapping);
...
BeanToCsv bean = new CustomBeanToCsv<CustomBean>();
...
}
static class CustomStrategy<T> extends HeaderColumnNameTranslateMappingStrategy {
#Override
public void setColumnMapping(Map columnMapping) {
super.setColumnMapping(columnMapping);
header = new String[columnMapping.size()];
int i = 0;
for (Map.Entry entry : columnMapping.entrySet()) {
header[i] = entry.getKey().toUpperCase();
i++;
}
}
public String[] getHeader() {
return header;
}
}
static class CustomBeanToCsv<T> extends BeanToCsv {
#Override
protected String[] processHeader(MappingStrategy mapper) throws IntrospectionException {
if (mapper instanceof CustomStrategy) {
return ((CustomStrategy) mapper).getHeader();
} else {
return super.processHeader(mapper);
}
}
}
}
I have been using openCSV for five years now and I am still learning stuff about it. The issue is that the HeaderColumnNameMappingStrategy and HeaderColumnNameTranslateMappingStrategy were made for the CsvToBean. It wants a file to read to get the header out to see where the reader should read from.
For the BeanToCsv class use the ColumnPositionMappingStrategy class. You give it the class you are mapping and a list of the columns you want to map and it does the rest for you.
Here is a little test method I wrote that worked.
public void createUsingBeanToCsv(int numRecords, FileWriter fos) {
List<SmallRecord> smallRecords = new ArrayList<>(numRecords);
for (int i = 0; i < numRecords; i++) {
smallRecords.add(SmallRecordGenerator.createRecord(i));
}
BeanToCsv<SmallRecord> beanToCsv = new BeanToCsv<>();
ColumnPositionMappingStrategy<SmallRecord> strategy = new ColumnPositionMappingStrategy<>();
strategy.setType(SmallRecord.class);
String[] columns = new String[]{"bigDecimal_1", "name_1", "intNumber_1"};
strategy.setColumnMapping(columns);
beanToCsv.write(strategy, fos, smallRecords);
}

Parameterized runner class with 2 arguments in constructor

I wish to use a Parameterized Junit class to read from a .csv file. I want to:-
Read a 'placeID' (a String) and append it to a base url to form a webpage
Assert that the Place name 'name' (a String) is as I expect it to be for the place
The tab delimited .csv file contains 2 records as follows (will have 100's records eventually):
132
The Big House
I'm currently getting an Illegal argument exception. What's a slicker way of achieving this? I guess having the relative URL and then test data in seperate files would be better.
My code:
#RunWith(Parameterized.class)
public class PlaceTest {
public static WebDriver driver;
private String placeId;
private String name;
private PropertyPage propertyPage;
public PlaceTest(String page, String name) {
this.placeId = page;
this.name = name;
}
#Parameterized.Parameters
public static Collection data() {
return csvFileAsCollectionOfStringArrays(
System.getProperty("user.dir") +
"/src/test/resources/" +
"place_ids.csv");
}
private static Collection<String[]> csvFileAsCollectionOfStringArrays(String csvFileName) {
List<String[]> csvRows = new ArrayList<String[]>();
String rawCSVRow;
BufferedReader csvFileReader = null;
String delimiter = "\t";
System.out.println("Reading data from " + csvFileName);
try {
csvFileReader = new BufferedReader(new FileReader(csvFileName));
} catch (FileNotFoundException e) {
System.out.println("Could not find file " + csvFileName);
e.printStackTrace();
}
int rowNumber = 1;
try {
if (csvFileReader != null) {
while ((rawCSVRow = csvFileReader.readLine()) != null) {
String delimitedItems[] = rawCSVRow.split(delimiter);
csvRows.add(delimitedItems);
rowNumber++;
}
}
} catch (IOException e) {
System.out.println("Error reading row number " + rowNumber);
e.printStackTrace();
}
try {
assert csvFileReader != null;
csvFileReader.close();
} catch (IOException e) {
System.out.println("Error closing file " + e.getMessage());
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
return csvRows;
}
#BeforeClass
public static void startDriver() {
driver = Driver.get();
}
#Before
public void getNextPage() {
propertyPage = new PropertyPage(driver);
driver.get(TestWebApp.getURL() + this.placeId);
}
#Test
public void checkNamePresent() {
WebElement placeName = propertyPage.checkName();
assertEquals("Expected match on name", this.name, placeName.getText());
}
#AfterClass
public static void quitDriver() {
driver.quit();
}
}
Try this:
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import au.com.bytecode.opencsv.CSVReader;
#RunWith(Parameterized.class)
public class PlaceTest {
private String placeId;
private String name;
public PlaceTest(String page, String name) {
this.placeId = page;
this.name = name;
}
#Parameterized.Parameters
public static Collection<String[]> data() {
CSVReader reader = new CSVReader(new InputStreamReader(PlaceTest.class.getResourceAsStream("place_ids.csv")));
List<String[]> lines;
try {
lines = reader.readAll();
return lines;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new ArrayList<String[]>();
}
#Test
public void checkNamePresent() {
System.out.println(this.placeId + " " + this.name);
}
}
The place_ids.csv has to be in: \src\test\resources\<your package>\place_ids.csv
Update your pom with CSVReader dependency:
<dependency>
<groupId>net.sf.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>2.3</version>
</dependency>
Update:
csv file:
132, Some text
133, Other text
Your example above has one word per line. The code above was compile and tested.

Categories