Tab-Separated File:
2019-06-06 10:00:00 1.0
2019-06-06 11:00:00 2.0
I'd like to iterate over the file once and add the value of each column to a list.
My working approach would be:
import java.util.*;
import java.io.*;
public class Program {
public static void main(String[] args)
{
ArrayList<Double> List_1 = new ArrayList<Double>();
ArrayList<Double> List_2 = new ArrayList<Double>();
String[] values = null;
String fileName = "File.txt";
File file = new File(fileName);
try
{
Scanner inputStream = new Scanner(file);
while (inputStream.hasNextLine()){
try {
String data = inputStream.nextLine();
values = data.split("\\t");
if (values[1] != null && !values[1].isEmpty() == true) {
double val_1 = Double.parseDouble(values[1]);
List_1.add(val_1);
}
if (values[2] != null && !values[2].isEmpty() == true) {
double val_2 = Double.parseDouble(values[2]);
List_2.add(val_2);
}
}
catch (ArrayIndexOutOfBoundsException exception){
}
}
inputStream.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println(List_1);
System.out.println(List_2);
}
}
I get:
[1.0]
[2.0]
It doesn't work without the checks for null, ìsEmpty and the ArrayIndexOutOfBoundsException.
I would appreciate any hints on how to save a few lines while keeping the scanner approach.
One option is to create a Map of Lists using column number as a key. This approach gives you "unlimited" number of columns and exactly the same output than one in the question.
public class Program {
public static void main(String[] args) throws Exception
{
Map<Integer, List<Double>> listMap = new TreeMap<Integer, List<Double>>();
String[] values = null;
String fileName = "File.csv";
File file = new File(fileName);
Scanner inputStream = new Scanner(file);
while (inputStream.hasNextLine()){
String data = inputStream.nextLine();
values = data.split("\\t");
for (int column = 1; column < values.length; column++) {
List<Double> list = listMap.get(column);
if (list == null) {
listMap.put(column, list = new ArrayList<Double>());
}
if (!values[column].isEmpty()) {
list.add(Double.parseDouble(values[column]));
}
}
}
inputStream.close();
for(List<Double> list : listMap.values()) {
System.out.println(list);
}
}
}
You can clean up your code some by using try-with resources to open and close the Scanner for you:
try (Scanner inputStream = new Scanner(file))
{
//your code...
}
This is useful because the inputStream will be closed automatically once the try block is left and you will not need to close it manually with inputStream.close();.
Additionally if you really want to "save lines" you can also combine these steps:
double val_2 = Double.parseDouble(values[2]);
List_2.add(val_2);
Into a single step each, since you do not actually use the val_2 anywhere else:
List_2.add(Double.parseDouble(values[2]));
Finally you are also using !values[1].isEmpty() == true which is comparing a boolean value to true. This is typically bad practice and you can reduce it to !values[1].isEmpty() instead which will have the same functionality. Try not to use == with booleans as there is no need.
you can do it like below:
BufferedReader bfr = Files.newBufferedReader(Paths.get("inputFileDir.tsv"));
String line = null;
List<List<String>> listOfLists = new ArrayList<>(100);
while((line = bfr.readLine()) != null) {
String[] cols = line.split("\\t");
List<String> outputList = new ArrayList<>(cols);
//at this line your expected list of cols of each line is ready to use.
listOfLists.add(outputList);
}
As a matter of fact, it is a simple code in java. But because it seems that you are a beginner in java and code like a python programmer, I decided to write a sample code to let you have a good start point. good luck
Related
I'm trying to parse a csv of over 100,000 lines and the performance problems don't even let me get to the end of the file before hitting "Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded"
Is there something wrong, or any way I can improve?
public static List<String[]> readCSV(String filePath) throws IOException{
List<String[]> csvLine= new ArrayList<String[]>();
CSVReader reader = new CSVReader(new FileReader(filePath), '\n');
String[] row;
while((row = reader.readNext()) != null){
csvLine.add(removeWhiteSpace(row[0].toString().split(",")));
}
reader.close();
return csvLine;
}
private static String[] removeWhiteSpace(String[] split) {
for(int index =0; index < split.length;index++){
split[index] = split[index].trim();
}
return split;
}
First you are running out of memory because all rows are being added to a list.
Second you are using String.split() which is extremely slow.
Third never try processing CSV by writing your own parsing code as there are many edge cases around this format (need to handle escape of delimiter, quotes, etc).
The solution is to use a library for that, such as univocity-parsers. You should be able to read 1 million rows in less than a second.
To parse, just do this:
public static IterableResult<String[], ParsingContext> readCSV(String filePath) {
File file = new File(filePath);
//configure the parser here. By default all values are trimmed
CsvParserSettings parserSettings = new CsvParserSettings();
//create the parser
CsvParser parser = new CsvParser(parserSettings);
//create an iterable over rows. This will not load everything into memory.
IterableResult<String[], ParsingContext> rows = parser.iterate(file);
return rows;
}
Now you can use your method like this:
public static void main(String... args) {
IterableResult<String[], ParsingContext> rows = readCSV("c:/path/to/input.csv");
try {
for (String[] row : rows) {
//process the rows however you want
}
} finally {
//the parser closes itself but in case any errors processing the rows (outside of the control of the iterator), close the parser.
rows.getContext().stop();
}
}
This is just an example of how you can use the parser, but there are many different ways to use it.
Now for writing, you can do this:
public static void main(String... args) {
//this is your output file
File output = new File("c:/path/to/output.csv");
//configure the writer if you need to
CsvWriterSettings settings = new CsvWriterSettings();
//create the writer. Here we write to a file
CsvWriter writer = new CsvWriter(output, settings);
//get the row iterator
IterableResult<String[], ParsingContext> rows = readCSV("c:/temp");
try {
//do whatever you need to the rows here
for (String[] row : rows) {
//then write it each one to the output.
writer.writeRow(row);
}
} finally {
//cleanup
rows.getContext().stop();
writer.close();
}
}
If all you want is to read the data, modify it and write it back to another file, you can just do this:
public static void main(String... args) throws IOException {
CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.setProcessor(new AbstractRowProcessor() {
#Override
public void rowProcessed(String[] row, ParsingContext context) {
//modify the row data here.
}
});
CsvWriterSettings writerSettings = new CsvWriterSettings();
CsvRoutines routines = new CsvRoutines(parserSettings, writerSettings);
FileReader input = new FileReader("c:/path/to/input.csv");
FileWriter output = new FileWriter("c:/path/to/output.csv");
routines.parseAndWrite(input, output);
}
Hope this helps.
Disclaimer: I'm the author of this libary. It's open source and free (Apache 2.0 license).
Is a design error try to put such a large file in memory.
Depending of what you want to do, you should either write a new file processed, or put the lines into a dba.
This implements the first:
FileInputStream inputStream = null;
Scanner sc = null;
try {
inputStream = new FileInputStream(path);
sc = new Scanner(inputStream, "UTF-8");
while (sc.hasNextLine()) {
String line = sc.nextLine();
// System.out.println(line);
}
// note that Scanner suppresses exceptions
if (sc.ioException() != null) {
throw sc.ioException();
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (sc != null) {
sc.close();
}
}
This is a project i'm working on at college, everything seems good except in the game class which initializes the game. Here is a snippet
public class Game{
private Player player;
private World world;
private ArrayList<NonPlayableFighter> weakFoes;
private ArrayList<NonPlayableFighter> strongFoes;
private ArrayList<Attack> attacks;
private ArrayList<Dragon> dragons;
public Game() throws IOException{
player = new Player("");
world = new World();
weakFoes = new ArrayList<NonPlayableFighter>();
strongFoes = new ArrayList<NonPlayableFighter>();
attacks = new ArrayList<Attack>();
dragons = new ArrayList<Dragon>();
loadAttacks ("Database-Attacks_20309.csv");
loadFoes ("Database-Foes_20311.csv");
loadDragons ("Database-Dragons_20310.csv");
}
after that follows some getters and the 4 method i am supposed to implement.
These methods are loadCSV(String filePath),loadAttacks(String filePath),loadFoes(String filePath),loadDragons(String filePath)
I have created loadCSV(String filePath) such that it returns an ArrayList of String[] here:
private ArrayList<String[]> loadCSV(String filePath) throws IOException{
String currentLine = "";
ArrayList<String[]> result = new ArrayList<String[]>();
FileReader fileReader = new FileReader(filePath);
BufferedReader br = new BufferedReader(fileReader);
currentLine = br.readLine();
while (currentLine != null){
String[] split = currentLine.split(",");
result.add(split);
}
br.close();
return result;
}
Then i would like to load some attacks, foes, and dragons and inserting them in the appropriate ArrayList.
I applied loadAttacks(String filePath) here:
private void loadAttacks(String filePath) throws IOException{
ArrayList<String[]> allAttacks = loadCSV(filePath);
for(int i = 0; i < allAttacks.size(); i++){
String[] current = allAttacks.get(i);
Attack temp = null;
switch(current[0]){
case "SA": temp = new SuperAttack(current[1],
Integer.parseInt(current[2]));
break;
case "UA": temp = new UltimateAttack(current[1],
Integer.parseInt(current[2]));
break;
case "MC": temp = new MaximumCharge();
break;
case "SS": temp = new SuperSaiyan();
break;
}
attacks.add(temp);
}
}
I wrote it such that it takes the ArrayList returned from loadCSV(String filePath) and searches in each String[] within the ArrayList on the first String using a switch thus creating the appropriate attack and adding it to attacks.
Then i would like to read another CSV for the Foes and the CSV file is structured such that in the first line there are some attributes the second line some attacks of type SuperAttack and the third line holds some attacks of type Ultimate attack. Also within each foe there is a boolean attribute that determines if it is a Strong or Weak Foe thus putting it in the right Arraylist. Here is the code for loadFoes(String filePath):
private void loadFoes(String filePath) throws IOException{
ArrayList<String[]> allFoes = loadCSV(filePath);
for(int i = 0; i < allFoes.size(); i += 3){
String[] current = allFoes.get(i);
String[] supers = allFoes.get(i+1);
String[] ultimates = allFoes.get(i+2);
ArrayList<SuperAttack> superAttacks = new ArrayList<SuperAttack>();
ArrayList<UltimateAttack> ultimateAttacks = new ArrayList<UltimateAttack>();
NonPlayableFighter temp = null;
for(int j = 0; i < supers.length; j++){
int index = attacks.indexOf(supers[j]);
if(index != -1){
superAttacks.add((SuperAttack)attacks.get(index));
}
else break;
}
for(int j = 0; i < ultimates.length; j++){
int index = attacks.indexOf(ultimates[j]);
if(index != -1){
ultimateAttacks.add((UltimateAttack)attacks.get(index));
}
else break;
}
if(current[7].equalsIgnoreCase("True")){
temp = new NonPlayableFighter(current[0], Integer.parseInt(current[1]),
Integer.parseInt(current[2]), Integer.parseInt(current[3]),
Integer.parseInt(current[4]), Integer.parseInt(current[5]),
Integer.parseInt(current[6]), true, superAttacks, ultimateAttacks);
strongFoes.add(temp);
}
else{
temp = new NonPlayableFighter(current[0], Integer.parseInt(current[1]),
Integer.parseInt(current[2]), Integer.parseInt(current[3]),
Integer.parseInt(current[4]), Integer.parseInt(current[5]),
Integer.parseInt(current[6]), false, superAttacks, ultimateAttacks);
weakFoes.add(temp);
}
}
}
First i get the first three String[] in the ArrayList returned from loadCSV(String filePath and made 2 loops to check if the attacks are within the previously loaded attacks CSV then i check for the attribute that determines if it is a strong or weak and accordingly creating a new NonPlayableFighter and adding it to the appropriate list.
Running the jUnit4 tests for this assignment it gives me a Compilation Error: Unhandled exception type IOException. And generally speaking does the code have any notable problems ?
It's better to reuse already exist CSV file readers for Java (e.g. CVSReader) if isn't a part of you task.
That makes a lot of code. I'll answer to your Compilation Error.
While reading a file you have to pu your code in a try catch in order to avoid this kind of error. In your loadCSV method you have to set up a try catch block.
Please refer to this site for complete tutorial.
try (BufferedReader br = new BufferedReader(new FileReader("C:\\testing.txt")))
{
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
String[] split = currentLine.split(",");
result.add(split);
}
} catch (IOException e) {
e.printStackTrace();
}
To make it short, code that access to files have to be in a try catch to avoid IO Exception, or be in a method that throws the exception (but then it has to be catched elsewhere).
In that code you have a good example of a try-with-resource, very good way to manage your ressource and memory.
loadCSV(String filePath) is a infinite loop isn't it? And as for the IOException it as #RPresle suggested a try/catch would do the trick around the BufferedReader.
To speed-up a lookup search into a multi-record file I wish to store its elements into a String array of array so that I can just search a string like "AF" into similar strings only ("AA", "AB, ... , "AZ") and not into the whole file.
The original file is like this:
AA
ABC
AF
(...)
AP
BE
BEND
(...)
BZ
(...)
SHORT
VERYLONGRECORD
ZX
which I want to translate into
AA ABC AF (...) AP
BE BEND (...) BZ
(...)
SHORT
VERYLONGRECORD
ZX
I don't know how much records there are and how many "elements" each "row" will have as the source file can change in the time (even if, after being read into memory, the array is only read).
I tried whis solution:
in a class I defined the string array of (string) arrays, without defining its dimensions
public static String[][] tldTabData;
then, in another class, I read the file:
public static void tldLoadTable() {
String rec = null;
int previdx = 0;
int rowidx = 0;
// this will hold each row
ArrayList<String> mVector = new ArrayList<String>();
FileInputStream fStream;
BufferedReader bufRead = null;
try {
fStream = new FileInputStream(eVal.appPath+eVal.tldTabDataFilename);
// Use DataInputStream to read binary NOT text.
bufRead = new BufferedReader(new InputStreamReader(fStream));
} catch (Exception er1) {
/* if we fail the 1.st try maybe we're working into some "package" (e.g. debugging)
* so we'll try a second time with a modified path (e.g. adding "bin\") instead of
* raising an error and exiting.
*/
try {
fStream = new FileInputStream(eVal.appPath +
"bin"+ File.separatorChar + eVal.tldTabDataFilename);
// Use DataInputStream to read binary NOT text.
bufRead = new BufferedReader(new InputStreamReader(fStream));
} catch (FileNotFoundException er2) {
System.err.println("Error: " + er2.getMessage());
er2.printStackTrace();
System.exit(1);
}
}
try {
while((rec = bufRead.readLine()) != null) {
// strip comments and short (empty) rows
if(!rec.startsWith("#") && rec.length() > 1) {
// work with uppercase only (maybe unuseful)
//rec.toUpperCase();
// use the 1st char as a row index
rowidx = rec.charAt(0);
// if row changes (e.g. A->B and is not the 1.st line we read)
if(previdx != rowidx && previdx != 0)
{
// store the (completed) collection into the Array
eVal.tldTabData[previdx] = mVector.toArray(new String[mVector.size()]);
// clear the collection itself
mVector.clear();
// and restart to fill it from scratch
mVector.add(rec);
} else
{
// continue filling the collection
mVector.add(rec);
}
// and sync the indexes
previdx = rowidx;
}
}
streamIn.close();
// globally flag the table as loaded
eVal.tldTabLoaded = true;
} catch (Exception er2) {
System.err.println("Error: " + er2.getMessage());
er2.printStackTrace();
System.exit(1);
}
}
When executing the program, it correctly accumulates the strings into mVector but, when trying to copy them into the eVal.tldTabData I get a NullPointerException.
I bet I have to create/initialize the array at some point but having problems to figure where and how.
First time I'm coding in Java... helloworld apart. :-)
you can use a Map to store your strings per row;
here something that you'll need :
//Assuming that mVector already holds all you input strings
Map<String,List<String>> map = new HashMap<String,List<String>>();
for (String str : mVector){
List<String> storedList;
if (map.containsKey(str.substring(0, 1))){
storedList = map.get(str.substring(0, 1));
}else{
storedList = new ArrayList<String>();
map.put(str.substring(0, 1), storedList);
}
storedList.add(str);
}
Set<String> unOrdered = map.keySet();
List<String> orderedIndexes = new ArrayList<String>(unOrdered);
Collections.sort(orderedIndexes);
for (String key : orderedIndexes){//get strings for every row
List<String> values = map.get(key);
for (String value : values){//writing strings on the same row
System.out.print(value + "\t"); // change this to writing to some file
}
System.out.println(); // add new line at the end of the row
}
I have two files Which should contain the same values between Substring 0 and 10 though not in order. I have Managed to Outprint the values in each file but I need to Know how to Report say id the Value is in the first File and Notin the second file and vice versa. The files are in these formats.
6436346346....Other details
9348734873....Other details
9349839829....Other details
second file
8484545487....Other details
9348734873....Other details
9349839829....Other details
The first record in the first file does not appear in the second file and the first record in the second file does not appear in the first file. I need to be able to report this mismatch in this format:
Record 6436346346 is in the firstfile and not in the secondfile.
Record 8484545487 is in the secondfile and not in the firstfile.
Here is the code I currently have that gives me the required Output from the two files to compare.
package compare.numbers;
import java.io.*;
/**
*
* #author implvcb
*/
public class CompareNumbers {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
File f = new File("C:/Analysis/");
String line;
String line1;
try {
String firstfile = "C:/Analysis/RL001.TXT";
FileInputStream fs = new FileInputStream(firstfile);
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
while ((line = br.readLine()) != null) {
String account = line.substring(0, 10);
System.out.println(account);
}
String secondfile = "C:/Analysis/RL003.TXT";
FileInputStream fs1 = new FileInputStream(secondfile);
BufferedReader br1 = new BufferedReader(new InputStreamReader(fs1));
while ((line1 = br1.readLine()) != null) {
String account1 = line1.substring(0, 10);
System.out.println(account1);
}
} catch (Exception e) {
e.fillInStackTrace();
}
}
}
Please help on how I can effectively achieve this.
I think I needed to say that am new to java and may not grab the ideas that easily but Am trying.
Here is the sample code to do that:
public static void eliminateCommon(String file1, String file2) throws IOException
{
List<String> lines1 = readLines(file1);
List<String> lines2 = readLines(file2);
Iterator<String> linesItr = lines1.iterator();
while (linesItr.hasNext()) {
String checkLine = linesItr.next();
if (lines2.contains(checkLine)) {
linesItr.remove();
lines2.remove(checkLine);
}
}
//now lines1 will contain string that are not present in lines2
//now lines2 will contain string that are not present in lines1
System.out.println(lines1);
System.out.println(lines2);
}
public static List<String> readLines(String fileName) throws IOException
{
List<String> lines = new ArrayList<String>();
FileInputStream fs = new FileInputStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
String line = null;
while ((line = br.readLine()) != null) {
String account = line.substring(0, 10);
lines.add(account);
}
return lines;
}
Perhaps you are looking for something like this
Set<String> set1 = new HashSet<>(FileUtils.readLines(new File("C:/Analysis/RL001.TXT")));
Set<String> set2 = new HashSet<>(FileUtils.readLines(new File("C:/Analysis/RL003.TXT")));
Set<String> onlyInSet1 = new HashSet<>(set1);
onlyInSet1.removeAll(set2);
Set<String> onlyInSet2 = new HashSet<>(set2);
onlyInSet2.removeAll(set1);
If you guarantee that the files will always be the same format, and each readLine() function is going to return a different number, why not have an array of strings, rather than a single string. You can then compare the outcome with greater ease.
Ok, first I would save the two sets of strings in to collections
Set<String> s1 = new HashSet<String>(), s2 = new HashSet<String>();
//...
while ((line = br.readLine()) != null) {
//...
s1.add(line);
}
Then you can compare those sets and find elements that do not appear in both sets. You can find some ideas on how to do that here.
If you need to know the line number as well, you could just create a String wrapper:
class Element {
public String str;
public int lineNr;
public boolean equals(Element compElement) {
return compElement.str.equals(str);
}
}
Then you can just use Set<Element> instead.
Open two Scanners, and :
final TreeSet<Integer> ts1 = new TreeSet<Integer>();
final TreeSet<Integer> ts2 = new TreeSet<Integer>();
while (scan1.hasNextLine() && scan2.hasNexLine) {
ts1.add(Integer.valueOf(scan1.nextLigne().subString(0,10));
ts1.add(Integer.valueOf(scan1.nextLigne().subString(0,10));
}
You can now compare ordered results of the two trees
EDIT
Modified with TreeSet
Put values from each file to two separate HashSets accordingly.
Iterate over one of the HashSets and check whether each value exists in the other HashSet. Report if not.
Iterate over other HashSet and do same thing for this.
I'm building a RMI game and the client would load a file that has some keys and values which are going to be used on several different objects. It is a save game file but I can't use java.util.Properties for this (it is under the specification). I have to read the entire file and ignore commented lines and the keys that are not relevant in some classes. These properties are unique but they may be sorted in any order. My file current file looks like this:
# Bio
playerOrigin=Newlands
playerClass=Warlock
# Armor
playerHelmet=empty
playerUpperArmor=armor900
playerBottomArmor=armor457
playerBoots=boot109
etc
These properties are going to be written and placed according to the player's progress and the filereader would have to reach the end of file and get only the matched keys. I've tried different approaches but so far nothing came close to the results that I would had using java.util.Properties. Any idea?
This will read your "properties" file line by line and parse each input line and place the values in a key/value map. Each key in the map is unique (duplicate keys are not allowed).
package samples;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.TreeMap;
public class ReadProperties {
public static void main(String[] args) {
try {
TreeMap<String, String> map = getProperties("./sample.properties");
System.out.println(map);
}
catch (IOException e) {
// error using the file
}
}
public static TreeMap<String, String> getProperties(String infile) throws IOException {
final int lhs = 0;
final int rhs = 1;
TreeMap<String, String> map = new TreeMap<String, String>();
BufferedReader bfr = new BufferedReader(new FileReader(new File(infile)));
String line;
while ((line = bfr.readLine()) != null) {
if (!line.startsWith("#") && !line.isEmpty()) {
String[] pair = line.trim().split("=");
map.put(pair[lhs].trim(), pair[rhs].trim());
}
}
bfr.close();
return(map);
}
}
The output looks like:
{playerBoots=boot109, playerBottomArmor=armor457, playerClass=Warlock, playerHelmet=empty, playerOrigin=Newlands, playerUpperArmor=armor900}
You access each element of the map with map.get("key string");.
EDIT: this code doesn't check for a malformed or missing "=" string. You could add that yourself on the return from split by checking the size of the pair array.
I 'm currently unable to come up with a framework that would just provide that (I'm sure there are plenty though), however, you should be able to do that yourself.
Basically you just read the file line by line and check whether the first non whitespace character is a hash (#) or whether the line is whitespace only. You'd ignore those lines and try to split the others on =. If for such a split you don't get an array of 2 strings you have a malformed entry and handle that accordingly. Otherwise the first array element is your key and the second is your value.
Alternately, you could use a regular expression to get the key/value pairs.
(?m)^[^#]([\w]+)=([\w]+)$
will return capture groups for each key and its value, and will ignore comment lines.
EDIT:
This can be made a bit simpler:
[^#]([\w]+)=([\w]+)
After some study i came up with this solution:
public static String[] getUserIdentification(File file) throws IOException {
String key[] = new String[3];
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String lines;
try {
while ((lines = br.readLine()) != null) {
String[] value = lines.split("=");
if (lines.startsWith("domain=") && key[0] == null) {
if (value.length <= 1) {
throw new IOException(
"Missing domain information");
} else {
key[0] = value[1];
}
}
if (lines.startsWith("user=") && key[1] == null) {
if (value.length <= 1) {
throw new IOException("Missing user information");
} else {
key[1] = value[1];
}
}
if (lines.startsWith("password=") && key[2] == null) {
if (value.length <= 1) {
throw new IOException("Missing password information");
} else {
key[2] = value[1];
}
} else
continue;
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
return key;
}
I'm using this piece of code to check the properties. Of course it would be wiser to use Properties library but unfortunately I can't.
The shorter way how to do that:
Properties properties = new Properties();
String confPath = "src/main/resources/.env";
try {
properties.load(new FileInputStream(confPath));
} catch (IOException e) {
e.printStackTrace();
}
String specificValueByKey = properties.getProperty("KEY");
Set<Object> allKeys = properties.keySet();
Collection<Object> values = properties.values();