Read remote Excel file - java

I have an Excel file that looks like this:
What I'm trying to do now is supply the DEST_NAME_DISPLAY and retrieve the DEST_ID.
As you might have noticed, this file contains a lot of destination, so I don't want to loop over them all to find a DEST_ID. Is this possible? If it is, how?

Since the file rarely changes you can read it into a Map.
For example like this: How to group the values which are in excel to a HashMap
Afterwards, you can get the value like this:
Map<String, Integer> map = ... // from file
Integer value = map.get(key);
Edit: BackSlash points out, a database is better because the data will remain after the application quits. Of course it is a little harder to set up, but worth considering if you need persistance.

In java8 you can use the functional programming features to get it done.Following is the psuedo code written in javascript.
var myColumnDefs = [
{key:"Tokyo", value:"2211"},
{key:"Akihabara", value:"2211"},
{key:"Kyoto",value:"3344"}]
var input = "Kyoto"
var p = myColumnDefs.filter(function(x){ return x.key==input }).map(function(x){return x.value});
alert(p);
The following is the longer version which is written in Java 8
import java.util.Arrays;
class Location{
public String areaCode;
public String areaName;
public String otherInfo;
public Location(String areaName,String areaCode,String otherInfo){
this.areaCode = areaCode;
this.areaName = areaName;
this.otherInfo = otherInfo;
}
}
public class Main {
public static void main(String[] args) {
Location[] locations = {
new Location("Tokyo","2211","TK"),
new Location("Akihabara","2211","AHR"),
new Location("Kyoto","3344","KT")
};
String input = "Tokyo";
Location[] output =(Location[]) Arrays.stream(locations).filter(x->x.areaName.equals(input)).toArray(size -> new Location[size]);
System.out.println(output[0].areaCode);
}
}

Related

Code not working as expected. Using ArrayList and for loop in my Selenium Webdriver Java code

So I have recently started my work on Selenium Webdriver using Java. Below is the code:
List<LineDashboardDetails> LineDashboardDetailList = new ArrayList<LineDashboardDetails>();
LineDashboardDetails objLineDetail = new LineDashboardDetails();
for (int i = 0; i < lineUITextList.size(); i++) {
objLineDetail.lineName=lineUITextList.get(i);
objLineDetail.machineNames = machineUITextList.get(i).toString();
LineDashboardDetailList.add(objLineDetail);
}
System.out.println(LineDashboardDetailList);
I have created a lineUITextList ArrayList of String. This array will always have only 1 value in it. So the issue is above for loop does not work. The loop only executes once and comes out to print the LineDashboardDetailList. The machineUITextList array has around 5-6 values in it. My expectation is to have LineDashboardDetailList such that the lineUITextList common value is paired with each new value of machineUITextList.
For example if lineUITextList= {"Noun"}
machineUITextList= {"Pen","Box","Note","Scale"}
So my list i.e LineDashboardDetailList should give me output as:
Noun,Pen
Noun,Box
Noun,Note
Noun,Scale
I am using LineDashboardDetailList List further in my code.
Thanks in Advance.
I am not totally sure what you are trying to achive. Personally, I would use a java.util.Map to associate each value of the lineUITextList with the list of values of machineUITextList.
However, to help you in achiving your goal, first of all, I would design the LineDashboardDetails class in order to maintain the single value of the lineUITextList, along with the list of machineUITextList, so as you can combine them by using a specific method. That has lots of advantages in terms of encapsulation, distribution of responsabilities, etc.., plus you can always reuse for other purposes.
The function to combine the values can be easily implemented by taking advantages of Java stream and built-in functional interfaces.
Here is the code of the LineDashboardDetails class:
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
public class LineDashboardDetails {
private String lineName;
private List<String> machineNames;
public String getLineName() {
return lineName;
}
public void setLineName(String lineName) {
this.lineName = lineName;
}
public List<String> getMachineNames() {
return new ArrayList<>(machineNames);
}
public void setMachineNames(List<String> machineNames) {
this.machineNames = new ArrayList<>(machineNames);
}
public List<String> getCombinedList() {
return machineNames.stream()
.map(s -> lineName + "," + s)
.collect(Collectors.toList());
}
}
Here is instead the code that you tried to implement, which uses the class above and combine the two list, and finally prints out the list of values as you expect. You can see, I prepared two simple list in the main method, but you can actually generalize it in relation to your own needs:
import java.util.List;
import java.util.ArrayList;
public class SeleniumWebdriverListTest {
public List<LineDashboardDetails> combineUITextListWithMachineUIText(List<String> lineUITextList,
List<String> machineUITextList) {
List<LineDashboardDetails> lineDashboardDetailList = new ArrayList<>();
for (String lineUIText : lineUITextList) {
LineDashboardDetails objLineDetail = new LineDashboardDetails();
objLineDetail.setLineName(lineUIText);
objLineDetail.setMachineNames(machineUITextList);
lineDashboardDetailList.add(objLineDetail);
}
return lineDashboardDetailList;
}
public static void main(String[] args) {
List<String> lineUITextList = new ArrayList<>();
lineUITextList.add("Noun");
List<String> machineUITextList = new ArrayList<>();
machineUITextList.add("Pen");
machineUITextList.add("Box");
machineUITextList.add("Note");
machineUITextList.add("Scale");
List<LineDashboardDetails> lineDashboardDetailList =
new SeleniumWebdriverListTest().combineUITextListWithMachineUIText(
lineUITextList, machineUITextList);
lineDashboardDetailList.stream()
.map(s -> s.getCombinedList())
.forEach(System.out::println);
}
}
I could have used Java streams and a specific lamba expression to implement the combineUITextListWithMachineUIText method as well, but I kept somehow your original version to let you understand my idea of implementation around your code.
Here is the output I get:
[Noun,Pen, Noun,Box, Noun,Note, Noun,Scale]
Feel free to ask for any clarification.

I want to sort JSONArray by one value and return sorted array

Here is my first program using JSON. It is almost finished, only needs to be sorted by the "updated_at" value, and then return the sorted result in the form "name" + "updated_at". Anyone can help me with this / write code?
How can i do this?
public class Main {
public static void main(String[] args) throws Exception {
ArrayWithAllRepos arrayWithAllRepos = new ArrayWithAllRepos();
String dataFromPage1 = URLReader.readUrl(AllegroURL.URL_1);
String dataFromPage2 = URLReader.readUrl(AllegroURL.URL_2);
String dataFromPage3 = URLReader.readUrl(AllegroURL.URL_3);
JSONArray jsonArrayWithDataFromPage1 = new JSONArray(dataFromPage1);
JSONArray jsonArrayWithDataFromPage2 = new JSONArray(dataFromPage2);
JSONArray jsonArrayWithDataFromPage3 = new JSONArray(dataFromPage3);
arrayWithAllRepos.addToJsonToArray(jsonArrayWithDataFromPage1);
arrayWithAllRepos.addToJsonToArray(jsonArrayWithDataFromPage2);
arrayWithAllRepos.addToJsonToArray(jsonArrayWithDataFromPage3);
arrayWithAllRepos.printArray(arrayWithAllRepos.getJsonArray());
}
}
public class AllegroURL {
public static final String URL_1 = "https://api.github.com/users/allegro/repos?pagelen=1000&page=1";
public static final String URL_2 = "https://api.github.com/users/allegro/repos?pagelen=1000&page=2";
public static final String URL_3 = "https://api.github.com/users/allegro/repos?pagelen=1000&page=3";
}
I dont know the class ArrayWithAllRepos, but you can create Comparator which gets two json objects, and compare them with this value (you can see a lot of examples in google, here is one https://www.geeksforgeeks.org/comparator-interface-java/)
and use .stream().map() methods on the collection, in order to change the output (again, you can see a lot of examples in google, here is one https://javarevisited.blogspot.com/2018/05/java-8-filter-map-collect-stream-example.html)
If your collection does not support stream(), you can do a simple for, and create new json with you values.

How do I access an array within an array?

Say I have a .txt file that has information being split by a comma as such:
IN,Indiana,6634007
While this is a snippet which accesses that file and splits it:
for(int i=0; i < count; i++) {
line = bufferedReader2.readLine();
String space[] = line.split(",");
String abb = space[0];
String nme = space[1];
int pop = Integer.parseInt(space[2]);
states[i] = new State(abb, nme, pop);
}
The purpose of that was so that all the information in the txt file could be accessed, so for example this code would print exactly whats present on the .txt file:
System.out.println(states[0]);
would print:
IN,Indiana,6634007
My question is, how would I have it so that I can access the specific part of the array as in how would I print lets say just the name "Indiana" or the population "6634007"?
P.S I'm sorry if the title of my question did not make sense, I did not exactly know how to word it.
Somewhere, you have a class called State. states is an Array of this class. So you can add a getter to State:
public int getPop() {
return pop;
}
And call it on your Object like this:
System.out.println(states[0].getPop());
as states[0] is simply a State object.
Add more getters to access different fields.
if you just want to print every single line, you can try this like below:
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
String line = null;
List<String> list = new ArrayList<String>();
while((line = reader.readLine()) != null ) {
list.add(line);
}
System.out.println(list.get(0));
// TODO realease resources
}
From your question what i can realise is, you are using State class to store the information. In such case, check the state class where the first parameter value is stored. Later to print the corresponding information, access its object variable as SapuSeven mentioned.
For eg.
public class State{
public String a;
public String b;
public int c;
public State(String x, String y, int z){
a=x;
b=y;
c=z;
}
}
now u can access like
System.out.println(states[0].b);
for printing the name of city
OR
you can simply print the value using index like this
System.out.println(states[0].split(",")[2]);

How can I make arrays with own objects in Java in Android Studio.

I have a long piece of code that looks like this
Kwas a1 = new Kwas("Kwas Azotowy(V)", "HNO3");
// etc..
Kwas a17 = new Kwas("Kwas FluorkoWodorowy", "HF");
How can I write it as an Array? I tried something like
Kwas[] a = new Kwas[17]
But it didn`t work.
My "Kwas" class looks like the following:
public class Kwas {
String name;
String formula;
public Kwas( String nazwa, String wzor)
{
name = nazwa;
formula = wzor;
}
void setName(String c)
{
name = c;
}
void setFormula(String c)
{
formula = c;
}
public String getName()
{
return name;
}
public String getFormula() {return formula;}
}
You can do this:
List<Kwas> list = new ArrayList<Kwas>();
list.add(a2);
Just implement an ArrayList like this:
ArrayList<Kwas> newArray= new ArrayList<>();
And then:
newArray.add(a2);
newArray.add(a3);
newArray.add(a4);
newArray.add(a5);
newArray.add(a6);
newArray.add(a7);
...
...
Then if you want to get an specific item just write something like this:
newArray.get(1).getName(); //for example
I can't comment yet, so I have to provide it as an answer. Everyone is answering here how OP can construct a List, but no one is actually answering how he can create an array, which is probably very confusing for OP who might now think you can't create arrays of self-defined objects. You definitely can. But I don't know what the problem is.
Kwas[] a1 = new Kwas[17];
is definitely the right syntax. Are you sure you include the class? Can you post the exact code and error?
My guess is that you didn't import your class. In Android Studio, try placing your cursor after Kwas and pressing Ctrl+Space. This should show a dropdown list. Select the first line and press enter. Now it should have added an import to your class.
ArrayList<yourObjectName> arrayName = new ArrayList<yourObjectName>();
Then .add(object) on every object
You can simply type:
ArrayList<ObjectType> arrayName = new ArrayList<ObjectType>();
Adding Elements:
arrayName.add(someObject);
Removing Elements:
arrayName.remove(arrayName.get(someInteger));
Getting Elements:
arrayName.get(someInteger);
PS: Don't forget to import:
import java.util.ArrayList;

How to easily process CSV file to List<MyClass>

In my application I use a lot of CSV files which I have to read and build a lists based on them. I'd like to discover an easy way to do this. Do you know any easy framework which does it without using number of config files etc?
For instance, I have got a class Person:
public class Person {
String name;
String surname;
double shoeSize;
boolean sex; // true: male, false:female
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public double getShoeSize() {
return shoeSize;
}
public void setShoeSize(double shoeSize) {
this.shoeSize = shoeSize;
}
public boolean isSe) {
return sex;
}
public void setSeboolean sex) {
this.sex = sex;
}
}
For this class, I have prepared CSV file:
name,surname,shoesize,sex
Tom,Tommy,32,true
Anna,Anny,27,false
How can I do it easily?
One of the simplest ways to read and serialize data is by using the Jackson library.
It also has an extension for CSV, you can find the wiki here
Let's say you have a Pojo like this:
#JsonPropertyOrder({ "name", "surname", "shoesize", "gender" })
public class Person {
public String name;
public String surname;
public int shoesize;
public String gender;
}
And a CSV like this:
Tom,Tommy,32,m
Anna,Anny,27,f
Then reading it is done like so:
MappingIterator<Person> personIter = new CsvMapper().readerWithTypedSchemaFor(Person.class).readValues(csvFile);
List<Person> people = personIter.readAll();
This is simple enough for my taste, basically all you need to do is add the column order in your CSV file using the #JsonPropertyOrder annotation and then just read the file using the above 2 lines.
There are lot of good frameworks written in Java to parse a CSV file and form a List of Objects. OpenCSV, JSefa & jCSV are to name a few of them.
For your requirement, I believe jCSV suits the best. Below is the sample code from jCSV which you can make use of easily.
Reader reader = new FileReader("persons.csv");
CSVReader<Person> csvPersonReader = ...;
// read all entries at once
List<Person> persons = csvPersonReader.readAll();
// read each entry individually
Iterator<Person> it = csvPersonReader.iterator();
while (it.hasNext()) {
Person p = it.next();
// ...
}
Moreover, parsing a CSV file and converting it to a List isn't a big deal and it can be achieved without using any framework, as shown below.
br = new BufferedReader(new FileReader(csvFileToRead));
List<Person> personList = new ArrayList<>();
while ((line = br.readLine()) != null) {
// split on comma(',')
String[] personCsv = line.split(splitBy);
// create car object to store values
Person personObj = new Person();
// add values from csv to car object
personObj.setName(personCsv[0]);
personObj.setSurname(personCsv[1]);
personObj.setShoeSize(personCsv[2]);
personObj.setGender(personCsv[3]);
// adding car objects to a list
personList.add(personObj);
}
If the mapping of CSV columns to bean object is complex, repetitive or large in real case scenario, then it can be done easily by using DozerBeanMapper.
Hope this will help you.
Shishir
Not sure if you need to go as far as using an external library (and taking the usually implied performance hit). It's a pretty simple thing to implement. And if nothing else, it always helps to know what's going on behind the scenes in such a library:
public List<Person> readFile(String fileName) throws IOException {
List<Person> result = new ArrayList<Person>();
BufferedReader br = new BufferedReader(new FileReader(new File(fileName)));
try {
// Read first line
String line = br.readLine();
// Make sure file has correct headers
if (line==null) throw new IllegalArgumentException("File is empty");
if (!line.equals("name,surname,shoesize,sex"))
throw new IllegalArgumentException("File has wrong columns: "+line);
// Run through following lines
while ((line = br.readLine()) != null) {
// Break line into entries using comma
String[] items = line.split(",");
try {
// If there are too many entries, throw a dummy exception, if
// there are too few, the same exception will be thrown later
if (items.length>4) throw new ArrayIndexOutOfBoundsException();
// Convert data to person record
Person person = new Person();
person.setName ( items[0] );
person.setSurname ( items[1] );
person.setShoeSize(Double .parseDouble (items[2]));
person.setSex (Boolean.parseBoolean(items[3]));
result.add(person);
} catch (ArrayIndexOutOfBoundsException|NumberFormatException|NullPointerException e) {
// Caught errors indicate a problem with data format -> Print warning and continue
System.out.println("Invalid line: "+ line);
}
}
return result;
} finally {
br.close();
}
}
Note that the catch statement uses Java 7 multi-catch. For older Java versions, either split it into 3 catch blocks or replace ArrayIndexOutOfBoundsException|NumberFormatException|NullPointerException with Exception. The latter is usually discouraged as it masks and ignores all other exceptions as well, but in a simple example like this, the risk is probably not too high.
This answer, unfortunately, is specific to your problem, but given that it is very straight forward, it should be easy to adapt to other situations as well...
Another neat thing you can do is to match line inside the while loop with a regular expression rather than simply splitting it based on a comma. That way you could also implement data validation in one shot (for example only match a sensible number for shoe size).
Note that the above implementation doesn't work if you have names that contain commas which are then enclosed in quotes (like "Jackson, Jr." as a last name). You can cover this case "easily" if you use regular expressions as described above, or by checking the first letter of the last name and if it is a quotation mark, combine item[1] with item[2] and use item[3] and item[4] instead for the shoesize and sex. This special case will likely be covered by most of the external libraries suggested here, so if you're not worried about any dependencies, licensing issues, and performance hits, those might be the easier way out...
opencsv is a good and simple solution. It is a small but powerful library. You can download it from the opencsv website (direct download from sourceforge, use the jar in the deploy directory) or use maven.
The java bean mapping feature makes it really simple because your CSV column names are matching the property names of your class (it ignores the different capitalisation).
How to use it:
Reader reader = // ... reader for the input file
// let it map the csv column headers to properties
CsvToBean<Person> csvPersons = new CsvToBean<Person>();
HeaderColumnNameMappingStrategy<Person> strategy = new HeaderColumnNameMappingStrategy<Person>();
strategy.setType(Person.class);
// parse the file and get a list of persons
List<Person> persons = csvPersons.parse(strategy, reader);
That's all.
I solved this recently by using Immutables and Jackson, and I think it's a great way to go if you're willing to use these libraries.
Immutables and Jackson integrate very well. To take OP's example, all you'd have to do is specify the Immutables class like so (annotations qualified for snippet explicitness):
#org.immutables.value.Value.Immutable
#com.fasterxml.jackson.databind.annotation.JsonDeserialize(as = ImmutablePerson.class)
public interface Person {
String getName();
String getSurname();
double getShoeSize();
boolean getSex();
}
Then, using the Jackson CSV module, you can easily deserialize each row of the CSV into the class Immutables has generated for you:
List<Person> loadPeople(File personsCsvFile) throws IOException {
CsvSchema schema = CsvSchema.emptySchema().withHeader();
MappingIterator<Person> personsIterator = new CsvMapper()
.readerFor(Person.class)
.with(schema)
.readValues(personsCsvFile);
return personsIterator.readAll();
}
Use OpenCSV
Here is a complete example that reads entries and adds them to a List:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import au.com.bytecode.opencsv.CSVReader;
public class CSVReaderImplementor {
private String fileName;
private CSVReader reader;
private List<String[]> entries;
public CSVReaderImplementor(String fileName) throws IOException, FileNotFoundException {
this.fileName = fileName;
reader = new CSVReader(new FileReader(this.fileName));
entries = reader.readAll();
}
public List getEntries() {
return entries;
}
public static void main(String[] args) throws FileNotFoundException, IOException {
CSVReaderImplementor cri = new CSVReaderImplementor("yourfile.csv");
for(int i = 0; i < 50; i++) {
System.out.println(cri.getEntries().get(i).toString());
}
}
}
A List of type String[] is returned. You can iterate through the String array for each entry in the list and use the values at each index to populate your Bean constructor.
I think SuperCSV + Dozer easy to use and quite robust for java bean CSV serialization
http://supercsv.sourceforge.net/dozer.html

Categories