Parse file values using Java - java

I'm new to Java and I would like to read this file content using Java:
Filename Type Size Used Priority
/dev/mapper/VolGroup00-LogVol01 partition 524280 0 -1
/dev/mapper/VolGroup00-LogVol02 partition 324280 0 -1
Can you show me some working example with Java 8?
This is the code so far:
private static HashMap<String, HashMap<String, Long>> totalSwap() throws FileNotFoundException, IOException
{
File file = new File("/proc/swaps");
if (!file.exists())
{
System.err.println("/proc/swaps did not exist!");
return null;
}
else if (file.isDirectory())
{
System.err.println("/proc/swaps is a directory, not a file.");
return null;
}
Pattern pattern = Pattern.compile("([\\/A-Za-z0-9]+)[\\s]+([a-z]+)[\\s]+([0-9]+)[\\s]+([0-9]+)[\\s]+([\\-0-9]+).*");
BufferedReader reader = new BufferedReader(new FileReader("/proc/swaps"));
String s = reader.readLine();
while (s != null)
{
Matcher matcher = pattern.matcher(s);
if (matcher.matches())
{
HashMap<String, Long> usageData2 = new HashMap<>();
usageData2.put("allSwap", Long.parseLong(matcher.group(3)));
usageData2.put("utilizedSwap", Long.parseLong(matcher.group(4)));
data.put("First", usageData2);
}
s = reader.readLine();
}
reader.close();
return data;
}
I don't know how to read the FileName column. Finally I would like to get this result:
HashMap</dev/mapper/VolGroup00-LogVol01, HashMap<Size, 524280>
HashMap<Used, 0>>
HashMap</dev/mapper/VolGroup00-LogVol02, HashMap<Size, 334220>
HashMap<Used, 0>>
Can you help to solve this problem?

It may be better to split using a tab delimeter, if i remember correctly, linux is outputting using the tab character.
I have had to improvise with youre code but it should be easy to plug your code back in.
See my example below:
private static HashMap<String, HashMap<String, Long>> totalSwap()
{
HashMap<String, HashMap<String, Long>> data = new HashMap<String, HashMap<String, Long>>();
Pattern pattern = Pattern.compile("([\\/A-Za-z0-9]+)[\\s]+[A-Za-z]+[\\s]+([0-9]+)[\\s]+([0-9]+)[\\s]+([\\-0-9]+).*");
String s = "/dev/mapper/VolGroup00-LogVol01\tpartition\t524280\t0\t-1\n/dev/mapper/VolGroup00-LogVol02\tpartition\t324280\t0\t-1";
String[] columns = s.split("\t");
for (String line : columns) {
HashMap<String, Long> usageData2 = new HashMap<>();
usageData2.put("allSwap", Long.parseLong(columns[2]));
usageData2.put("utilizedSwap", Long.parseLong(columns[3]));
data.put(columns[0], usageData2);
}
return data;
}

Maybe it would be better to use StringTokenizer with delimiter tab("\t") and retrieve required columns.

Related

how do I convert this piece of code to stream using java stream api

I am trying to convert below code into stream. It's not that difficult but I am not sure how to handle null values in stream. I did checked out Optinal.ofNullable method but quite not sure if I have to use it 2-3 times to get the correct stream code. I can use the below code for now, but I wish to learn doing it in stream. Please help me learn.
Map<String, Map<String, List<String>>> fileTypeMapping = new HashMap<>();
Map<String, List<String>> map = new HashMap<>();
map.put("codec", new ArrayList(Arrays.asList("ext1", "ext2")));
fileTypeMapping.put("image", map);
String fileType = "Image";
String codec = "Codec";
String extension = "ext2";
boolean exist = false;
if(fileType != null) {
Map<String, List<String>> codecMap = fileTypeMapping.get(fileType.toLowerCase());
if(codecMap != null) {
List<String> list = codecMap.get(codec.toLowerCase());
if (list != null) {
exist = list.contains(extension.toLowerCase());
}
}
}
System.out.print(exist);
Seems not related to Stream API, just use Map.getOrDefault to get rid of null return.
import java.util.*;
public class NullableMapGet {
public static void main(String[] args) {
Map<String, Map<String, List<String>>> fileTypeMapping = new HashMap<>();
Map<String, List<String>> map = new HashMap<>();
map.put("codec", new ArrayList(Arrays.asList("ext1", "ext2")));
fileTypeMapping.put("image", map);
String fileType = "Image";
String codec = "Codec";
String extension = "ext2";
boolean exist = false;
if (fileType == null || codec == null || extension == null) {
exist = false;
} else {
exist = fileTypeMapping
.getOrDefault(fileType.toLowerCase(), Collections.emptyMap())
.getOrDefault(codec.toLowerCase(), Collections.emptyList())
.contains(extension.toLowerCase());
}
System.out.print(exist);
}
}

text file reading first line has key and second line onward value

****text file format:****
FirstName,lastname,role,startdate,emptype
sreedhar,reddy,Admin,20-2-2018,contract
shekar,kumar,Admin,20-2-2018,contract
RAJ,roy,Admin,20-2-2018,contract
somu,reddy,Admin,20-2-2018,contract
sumanth,reddy,Admin,20-2-2018,contract
Question:
How to read the text file and how to put in Map (Key ,vaule);
first line has key in map (ex: firstname,lastname,ect)
Second line on onwards value in map(eg:sreedhar,reddy,ect)
Map output:{Firstname:sreedhar,Lastname:reddy,role:Admin,startdat:2-6-2018}
please any one provide java code read the text file and put into map read has key, value pair.
You'll need to specify a different key for the Map as it requires a unique one each time:
A map cannot contain duplicate keys; each key can map to at most one
value.
So you're more than likely going to need a Map of Maps here:
Read in the file:
File file = new File("\\\\share\\path\\to\\file\\text.txt");
Add to scanner:
Scanner input = new Scanner(file);
Read the first line as your "header":
String[] headerArray = input.nextLine().split(",");
Create a Map of Maps:
Map<String, Map<String, String>> myMap = new HashMap<>();
Loop through the rest of the text file, adding to a Map, then adding that Map to the main Map, along with a key (I've used User0, User1...):
int pos = 0;
String user = "User";
while (input.hasNextLine()) {
Map<String, String> map = new HashMap<>();
int loop = 0;
String[] temp = input.nextLine().split(",");
for (String temp1 : temp) {
map.put(headerArray[loop], temp1);
loop++;
}
myMap.put(user + " " + pos, map);
pos++;
}
Once you break it down into steps, it makes life easier.
You can do something like this -
br = new BufferedReader(new FileReader("file.txt"));
String line = br.readLine();
String headerLine = line;
List<String> headerList = Arrays.asList(headerLine.split(","));
List<List<String>> valueListList = new ArrayList<List<String>>();
while (line != null) {
line = br.readLine();
String valueLine = line;
if(valueLine != null) {
List<String> valueList = Arrays.asList(valueLine.split(","));
valueListList.add(valueList);
}
}
Map<String, List<String>> map = new HashMap<String, List<String>>();
for(int i=0; i<headerList.size();i++){
List<String> tempList = new ArrayList<String>();
for(int j=0; j<headerList.size();j++){
tempList.add(valueListList.get(i).get(i));
}
map.put(headerList.get(i), tempList);
}
System.out.println(map);
Output:
{emptype=[contract, contract, contract, contract, contract],
startdate=[20-2-2018, 20-2-2018, 20-2-2018, 20-2-2018, 20-2-2018],
role=[Admin, Admin, Admin, Admin, Admin],
lastname=[kumar, kumar, kumar, kumar, kumar],
FirstName=[sreedhar, sreedhar, sreedhar, sreedhar, sreedhar]}

Merge two array list into a TreeMap in java

I want to combine these two text files
Driver details text file:
AB11; Angela
AB22; Beatrice
Journeys text file:
AB22,Edinburgh ,6
AB11,Thunderdome,1
AB11,Station,5
And I want my output to be only the names and where the person has been. It should look like this:
Angela
Thunderdone
Station
Beatrice
Edinburgh
Here is my code. I'm not sure what i'm doing wrong but i'm not getting the right output.
ArrayList<String> names = new ArrayList<String>();
TreeSet<String> destinations = new TreeSet<String>();
public TaxiReader() {
BufferedReader brName = null;
BufferedReader brDest = null;
try {
// Have the buffered readers start to read the text files
brName = new BufferedReader(new FileReader("taxi_details.txt"));
brDest = new BufferedReader(new FileReader("2017_journeys.txt"));
String line = brName.readLine();
String lines = brDest.readLine();
while (line != null && lines != null ){
// The input lines are split on the basis of certain characters that the text files use to split up the fields within them
String name [] = line.split(";");
String destination [] = lines.split(",");
// Add names and destinations to the different arraylists
String x = new String(name[1]);
//names.add(x);
String y = new String (destination[1]);
destinations.add(y);
// add arraylists to treemap
TreeMap <String, TreeSet<String>> taxiDetails = new TreeMap <String, TreeSet<String>> ();
taxiDetails.put(x, destinations);
System.out.println(taxiDetails);
// Reads the next line of the text files
line = brName.readLine();
lines = brDest.readLine();
}
// Catch blocks exist here to catch every potential error
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
// Finally block exists to close the files and handle any potential exceptions that can happen as a result
} finally {
try {
if (brName != null)
brName.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static void main (String [] args){
TaxiReader reader = new TaxiReader();
}
You are reading 2 files in parallel, I don't think that's gonna work too well. Try reading one file at a time.
Also you might want to rethink your data structures.
The first file relates a key "AB11" to a value "Angela". A map is better than an arraylist:
Map<String, String> names = new HashMap<String, String>();
String key = line.split(",")[0]; // "AB11"
String value = line.split(",")[1]; // "Angela"
names.put(key, value)
names.get("AB11"); // "Angela"
Similarly, the second file relates a key "AB11" to multiple values "Thunderdome", "Station". You could also use a map for this:
Map<String, List<String>> destinations = new HashMap<String, List<String>>();
String key = line.split(",")[0]; // "AB11"
String value = line.split(",")[1]; // "Station"
if(map.get(key) == null) {
List<String> values = new LinkedList<String>();
values.add(value);
map.put(key, values);
} else {
// we already have a destination value stored for this key
// add a new destination to the list
List<String> values = map.get(key);
values.add(value);
}
To get the output you want:
// for each entry in the names map
for(Map.Entry<String, String> entry : names.entrySet()) {
String key = entry.getKey();
String name = entry.getValue();
// print the name
System.out.println(name);
// use the key to retrieve the list of destinations for this name
List<String> values = destinations.get(key);
for(String destination : values) {
// print each destination with a small indentation
System.out.println(" " + destination);
}
}

How to compare and edit two csv files in java depending on one column?

public class CompareCSV {
public static void main(String args[]) throws FileNotFoundException, IOException {
String path = "C:\\csv\\";
String file1 = "file1.csv";
String file2 = "file2.csv";
String file3 = "file3.csv";
ArrayList<String> al1 = new ArrayList<String>();
ArrayList<String> al2 = new ArrayList<String>();
BufferedReader CSVFile1 = new BufferedReader(new FileReader("/C:/Users/bida0916/Desktop/macro.csv"));
String dataRow1 = CSVFile1.readLine();
while (dataRow1 != null) {
String[] dataArray1 = dataRow1.split(",");
for (String item1 : dataArray1) {
al1.add(item1);
}
dataRow1 = CSVFile1.readLine();
}
CSVFile1.close();
BufferedReader CSVFile2 = new BufferedReader(new FileReader("C:/Users/bida0916/Desktop/Deprecated.csv"));
String dataRow2 = CSVFile2.readLine();
while (dataRow2 != null) {
String[] dataArray2 = dataRow2.split(",");
for (String item2 : dataArray2) {
al2.add(item2);
}
dataRow2 = CSVFile2.readLine();
}
CSVFile2.close();
for (String bs : al2) {
al1.remove(bs);
}
int size = al1.size();
System.out.println(size);
try {
FileWriter writer = new FileWriter("C:/Users/bida0916/Desktop/NewMacro.csv");
while (size != 0) {
size--;
writer.append("" + al1.get(size));
writer.append('\n');
}
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I want to compare two csv files in java and want to have the complete details removed of one csv file from the other by comparing the first column of both the files. Currently I am getting a csv file with one column only having all details jumbled up.
You are adding all values of all columns to a single list, that's why you get the mess in your output:
ArrayList<String> al1=new ArrayList<String>();
//...
String[] dataArray1 = dataRow1.split(",");
for (String item1:dataArray1)
{
al1.add(item1);
}
Add the complete string array from your file to your list, then you can access your data in a structured way:
List<String[]> al1 = new ArrayList<>();
//...
String[] dataArray1 = dataRow1.split(",");
al1.add(dataArray1);
But for removal of rows I'd recommend to use Maps for faster access, where the key is the element on which you decide which row to delete and the value is the full row from your cvs file:
Map<String, String> al1 = new HashMap<>(); // or LinkedHashMap if row order is relevant
//...
String[] dataArray1 = dataRow1.split(",");
al1.put(dataArray1[0], dataRow1);
But be aware, that if two rows in a file contain the same value in the first column, only one will be preserved. If that's possible you might need to adopt that solution to store the data in a Map<String, Set<String>> or Map<String, List<String>>.
At this point I'd like to recommend to extract the file-reading to a separate method, which you can reuse to read both of your input-files and reduce duplicate code:
Map<String, String> al1 = readInputCsvFile(file1);
Map<String, String> al2 = readInputCsvFile(file2);
For the deletion of the lines which shall be removed, iterate over the key set of one of the maps and remove the entry from the other:
for (String key : al2.keySet()) {
al1.remove(key);
}
And for writing your output file, just write the row read from the original file as stored in the 'value' of your map.
for (String dataRow : al1.values()) {
writer.append(dataRow);
writer.append('\n');
}
EDIT
If you need to perform operations based on other data columns you should rather store the 'split-array' in the map instead of the full-line string read from the file. Then you have all data columns separately available:
Map<String, String[]> al2 = new HashMap<>();
//...
String[] dataArray2 = dataRow2.split(",");
al2.put(dataArray2[0], dataArray2);
You might then, e.g. add a condition for deleting:
for (Entry<String, String[]> entry : al2.entrySet()) {
String[] data = entry.getValue();
if ("delete".equals(data[17])) {
al1.remove(entry.getKey());
}
}
For writing your output file you have to rebuild the csv-format.
I'd recommend to use Apache commons-lang StringUtils for that task:
for (String[] data : al1.values()) {
writer.append(StringUtils.join(data, ","));
writer.append('\n');
}

How to put contents in hashmap with in hashmap

I have contents in CSV file like this
User1,What is your favorite color?,color
User1,What is the name of your pet?,pet
User1,What is your mother's maiden name?,mother
User2,In what city were you born?,city
User2,What elementary school did you attend?,school
User2,What was your first best friend's name?,friend
I need to call OIM API which will take parameters like this
void setUserChallengeValues(java.lang.String userID,
boolean isUserLogin,
java.util.HashMap quesAnsMap)
where quesAnsMap parameter means HashMap of challenge question and answers
What is the efficient way of parsing the CSV file with hashmap of userid as key and question and answer as value?
My hashmap should be like User1 is key and value should have question as key and answer as value.
Any sample snippet to refer?
Thanks
Read the file line by line, spliting it by ',' using String.split()
HashMap<String, Map<String, String>> userAnswers = new HashMap<>();
BufferedReader reader = new BufferedReader(new FileReader("/PATH/TO/YOUR/FILE.cvs"));
String ln;
while((ln = reader.readLine()) != null)
{
String [] split = ln.split(",");
String user = split[0];
Map<String, String> userMap = userAnswers.get(user);
if(userMap == null)
{
userMap = new HashMap<String, String>();
userAnswers.put(user, userMap);
}
userMap.put(split[1], split[2]);
}
reader.close();
Here I am writing an method in which you can provide file (.csv) name as an parameter and get HashMap<String, String> as a Result
public Map<String, String> putYourCSVToHashMap(String prm_csvFile) {
BufferedReader br = null; //bufferReader
String line = "";
HashMap<String,Map<String, String>> hMapData = new HashMap<>();
Map<String, String> userMap; //refering to inner Hashmap.
String cvsSplitBy = ","; //parameter on which your csv lines is splitted as an Array.
try {
br = new BufferedReader(new FileReader(prm_csvFile)); // Read Your File and Stored into BufferedReader.
while ((line = br.readLine()) != null) { //read each Line of File till last.
String[] csv_LineAsArray= line.split(cvsSplitBy); //each line will is splitted into an String Array.
String username = csv_LineAsArray[0]; //pick username available at 0th Index.
userMap= hMapData.get(username);
if(userMap == null) //if perticular user doesnot have any record
{
//Create a New Object for each new line where Question as a key Answer as a Value.
userMap = new HashMap<String, String>();
hMapData.put(user, userMap);
}
// put question as a key and Answer as a Value.
userMap.put(csv_LineAsArray[1], csv_LineAsArray[2]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return hMapData; // return your csv file as a HashMap.
}
I will tell you how I would do it, following the principle "Keep it as simple as possible".
I have read the other answers and I think using String.split is bad idea since you know exactly where to look for your values in each line of the CSV file.
Much better approach would be to use substring.
So here is sort of complete solution.
We create the class Tuple to store Q/A tuple. ( I am no using map since its a overkill :) )
class Tuple {
public String question;
public String answer;
public Tuple(String question, String answer) {
this.question = question;
this.answer = answer;
}
}
Its a simple class but it will save you lots of code later.
Now for the main class to do all the work.
class Questions {
private final Map csvData;
public Questions() {
csvData = new HashMap<String, Tuple>();
}
public void setUserChallengeValues(String line) {
String name = "";
String question = "";
String answer = "";
name = line.substring(0, line.indexOf(","));
line = line.substring(line.indexOf(",") + 1);
question = line.substring(0, line.indexOf(","));
line = line.substring(line.indexOf(",") + 1);
answer = line;
this.csvData.put(name, new Tuple(question, answer));
}
}
There is your method, the logic is very simple (a lot simpler compared to split in my opinion). You just look for ","'s index.
That way you can easily extract Name, Question and Answer from each line.
And finally the actual parsing becomes few lines of code.
Questions questions = new Questions();
//Feed the lines here one by one
String line1 = "User1,What is your favorite color?,color";
questions.setUserChallengeValues(line1);
Let me know if you need the whole code snippet.
Good luck :)

Categories