Reading .txt File into a Hashmap and manipulating it - java

Most likely my biggest problem here is not fully understanding Hashmaps and how to manipulate them despite looking at some tutorials. Hopefully you wise souls will be able to point me in the right track.
I'm trying to read a .txt file into a hashmap. The text file contains the popularity of names for 2006. Each line of the inputFile contains a boys name and a girls name as well as how many were named that. For example: 1 Jacob 24,797 Emily 21,365 would be the input from the file for line 1.
I want to put the boys name into one list, and the girls names into a second list maintaining their current positions so that the user can search for jacob and be told it was the number 1 boys name that year, and so on for other names. Previously I was just reading the file line by line and seeing what line the file contained the name i was searching for. This worked, but it was unable to tell if it was a boys name or a girls name, resulting in errors where if I said i was searching for how popular Jacob was for girls, it would still say number 1. I determined a hashmap would be the best way around this, but can't really get it working.
My Code
public void actionPerformed(ActionEvent e)
{
//Parse Input Fields
String name = inputArea.getText();
if (name.equals(""))
{
JOptionPane.showMessageDialog(null, "A name is required.", "Alert", JOptionPane.WARNING_MESSAGE );
return;
}
String genderSelected = genderList.getSelectedItem().toString();
String yearSelected = yearList.getSelectedItem().toString();
String yearFile = "Babynamesranking"+yearSelected+".txt"; //Opens a different name file depending on year selection
boolean foundName = false;
Map<String, String> map = new HashMap<String,String>(); //Creates Hashmap
try
{
File inputFile = new File(yearFile); //Sets input file to whichever file chosen in GUI
FileReader fileReader = new FileReader(inputFile); //Creates a fileReader to open the inputFile
BufferedReader br = new BufferedReader(fileReader); //Creates a buffered reader to read the fileReader
String line;
int lineNum = 1; //Incremental Variable to determine which line the name is found on
while ((line = br.readLine()) != null)
{
if (line.contains(name))
{
outputArea.setText(""+name+" was a popular name during "+yearSelected+".");
outputArea.append("\nIt is the "+lineNum+" most popular choice for "+genderSelected+" names that year.");
foundName = true;
}
String parts[] = line.split("\t");
map.put(parts[0],parts[1]);
lineNum++;
}
fileReader.close();
}
catch(IOException exception)
{
exception.printStackTrace();
}
String position = map.get(name);
System.out.println(position);
}
Sample inputFile:
1 Jacob 24,797 Emily 21,365
2 Michael 22,592 Emma 19,092
3 Joshua 22,269 Madison 18,599
4 Ethan 20,485 Isabella 18,200
5 Matthew 20,285 Ava 16,925
6 Daniel 20,017 Abigail 15,615
7 Andrew 19,686 Olivia 15,474
8 Christopher 19,635 Hannah 14,515

Well, the problem is that by using
if (line.contains(name))
You're checking if the name exists in the whole line, regarding if it's a boy's name or a girl's name. What you can do is to read them separately, then decide which value you want to check. You can do something like this:
while ((line = br.readLine()) != null)
{
Scanner sc = new Scanner(line);
int lineNumber = sc.nextInt();
String boyName = sc.next();
int boyNameFreq = sc.nextInt();
String girlName = sc.next();
int girlNameFreq = sc.nextInt();
if(genderSelected.equals("male") && name.equals(boyName)){
// .. a boy's name is found
}
else if(genderSelected.equals("female") && name.equals(girlName)){
// .. a girl's name is found
}
}
Scanner class is used to parse the line, and read it token-by-token, so you can know if the name is for a boy or girl. Then check on the name that you need only.

You'll want two hashmaps, one for boys' names and one for girls' names - at present you're using boys' names as keys and girls' names as values, which is not what you want. Instead, use two Map<String, IntTuple> data structures where the String is the name and the IntTuple is the line number (rank) and the count of people with this name.
class IntTuple {
final int rank;
final int count;
IntTuple(int rank, int count) {
this.rank = rank;
this.count = count;
}
}

Related

How can I remove specific elements from a linkedlist in java based on user input?

I'm very new (6 weeks into java) trying to remove elements from a csv file that lists a set of students as such (id, name, grades) each on a new line.
Each student id is numbered in ascending value. I want to try and remove a student by entering the id number and I'm not sure how I can do this.
So far I've just tried to reduce the value that user inputs to match the index as students are listed by number and I did this in a while loop. However, each iteration doesn't recognize the reduction from the previous user Input, and I think I need a way that can just search the value of the id, and remove the entire line from the csv file.
Have only tried to include the pertinent code. Reading previous stack questions has shown me a bunch of answers related to nodes, which make no sense to me since I don't have whatever prerequisite knowledge is required to understand it, and I'm not sure the rest of my code is valid for those methods.
Any ideas that are relatively simple?
Student.txt (each on a new line)
1,Frank,West,98,95,87,78,77,80
2,Dianne,Greene,78,94,88,87,95,92
3,Doug,Lei,78,94,88,87,95,92
etc....
Code:
public static boolean readFile(String filename) {
File file = new File("C:\\Users\\me\\eclipse-workspace\\studentdata.txt");
try {
Scanner scanner = new Scanner(file);
while(scanner.hasNextLine()) {
String[] words=scanner.nextLine().split(",");
int id = Integer.parseInt(words[0]);
String firstName = words[1];
String lastName = words[2];
int mathMark1 = Integer.parseInt(words[3]);
int mathMark2 = Integer.parseInt(words[4]);
int mathMark3 = Integer.parseInt(words[5]);
int englishMark1 = Integer.parseInt(words[6]);
int englishMark2 = Integer.parseInt(words[7]);
int englishMark3 = Integer.parseInt(words[8]);
addStudent(id,firstName,lastName,mathMark1,mathMark2,mathMark3,englishMark1,englishMark2,englishMark3);
}scanner.close();
}catch (FileNotFoundException e) {
System.out.println("Failed to readfile.");
private static void removeStudent() {
String answer = "Yes";
while(answer.equals("Yes") || answer.equals("yes")) {
System.out.println("Do you wish to delete a student?");
answer = scanner.next();
if (answer.equals("Yes") || answer.equals("yes")) {
System.out.println("Please enter the ID of the student to be removed.");
//tried various things here: taking userInput and passing through linkedlist.remove() but has never worked.
This solution may not be optimal or pretty, but it works. It reads in an input file line by line, writing each line out to a temporary output file. Whenever it encounters a line that matches what you are looking for, it skips writing that one out. It then renames the output file. I have omitted error handling, closing of readers/writers, etc. from the example. I also assume there is no leading or trailing whitespace in the line you are looking for. Change the code around trim() as needed so you can find a match.
File inputFile = new File("myFile.txt");
File tempFile = new File("myTempFile.txt");
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String lineToRemove = "bbb";
String currentLine;
while((currentLine = reader.readLine()) != null) {
// trim newline when comparing with lineToRemove
String trimmedLine = currentLine.trim();
if(trimmedLine.equals(lineToRemove)) continue;
writer.write(currentLine + System.getProperty("line.separator"));
}
writer.close();
reader.close();
boolean successful = tempFile.renameTo(inputFile);

Reading multiple data types from a CSV file in Java

So I want to create a constructor that reads in a line of a file from a csv and save the first token into a variable and the remaining tokens into an array. This constructor will be used in a gradebook application but being new to txt/file manipulation I'm having a hard time.
A line will look like:
Billy Bob,68,79,95,83
I want to separate the tokens into these:
name = Billy Bob
grades[] = "68,79,95,83"
here is the code I have so far:
import java.io.*;
public class gradeBook {
public static void main(String[] args){
System.out.println("Java Grade Book version 1.0");
int lineCounter = 0;
String array[];
try{
File data = new File("/file/path/that/works");
InputStream f = new FileInputStream(data);
BufferedReader br = new BufferedReader(new InputStreamReader(f));
for (String line = br.readLine(); line != null; line = br.readLine()) {
System.out.println(line); // just here to check that the code is working thus far
//insert code here
//name should equal first token (which is two names like Billy Bob)
//grades[] should contain the other double type tokens (e.g. 56,87,89,90)
}
br.close();
}
catch(Exception e){
System.err.println("Error: File Couldn't Be Read");
}
}
}
And I want to loop through the file to get as many students as are on the file stored so I can manipulate the grades for averages among other things. This is a personal project to help improve my developing skills so any help, useful tutorial links, and tips will be greatly appreciated. But please don't suggest simplistic examples like the many tutorials I have already read that only use one data type.
Thanks for any help!
Split the line into an array;
String[] input = line.split(",");
String variable = input[0];
int[] grades= new int[input.lenght - 2];
for(int i = 1; i < input.length; i++)
{
grades[i] = input[i];// you might have to do Integer.pareseInt(input[i]);
}
I did not write this in an IDE, but the logic should be correct.
You are going to run into a new problem. You grade book will only contain the last entry. Try using a 2D array for grades and 1D array for names; I personally would not use arrays. I would use arraylist.
So I haven't tested computing my tokens with methods or anything else yet but I have tokenized the line to sum (ha ha oops, meant some) degree with this bit of code:
String[] tokens = line.split(",");
String name = tokens[0];
String grade1 = tokens[1];
String grade2 = tokens[2];
String grade3 = tokens[3];
String grade4 = tokens[4];

Java Reading File and output to console [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
So i have a tiny problem, for some reason I'm blanking and I've tried moving it inside the loop and back to the outside of the loop it doesn't work. In option two which returns method display_names it reads them from the file it writes them to the console on one line instead of two separate lines.
ex:
Enter two knew people clicking 3:
smith, rob, 123-123-1234
smith, tom, 123-123-1235
Display names by clicking 2:
smith, rob, 123-123-1234smith, tom, 123-123-1235
instead of:
smith, rob, 123-123-1234
smith, tom, 123-123-1235
Main Code:
import java.util.*;
import java.io.*;
public class ContactList
{
/**
Contact list file name
*/
private String filename;
String findMe;
/**
ContactList constructor accepts a String parameter
*/
public ContactList(String inFileName)
{
filename = inFileName;
}
/**
3) add a new record to the file. Open the file for writing in append mode(there is a FileWriter constructor with the appropriate parameters).
a) prompt the user to enter data for each field in the record. Each field is a String.
The last name is required. If the last name is the empty string(""), return to the menu.
b) when the user has completed entering data(i.e., all the fields have been prompted), re-display the user choices
c) do not overwrite existing data
*/
public void new_record()
{
/*
Prompt for data:
Last name
First name
Phone
*/
//Create a scanner object
Scanner scan = new Scanner(System.in);
//prompt for the last name
System.out.println("Last Name: ");
//input the last name
String lastName = scan.next();
//the Last_name must not be empty
if(lastName.length() > 0)
{
//get the first name and the phone
System.out.println("Enter First Name: ");
String firstName = scan.next();
System.out.println("Enter phone number(xxx-xxx-xxxx): ");
String phone = scan.next();
//create the output string
String info = String.format("%s, %s, %s", lastName, firstName, phone);
//Declare variables to hold file types
File file = new File(filename);
//try to open the file for writing - append the data
try
{
if(!file.exists()){
PrintWriter out = new PrintWriter(filename);
out.println(info);
out.flush();
out.close();
}
else if(file.exists()){
FileWriter fw = new FileWriter(filename, true);
fw.write(info);
fw.close();
}
}
catch(IOException ioe)
{
System.out.println("new_record: Exception opening the file for writing");
}
}//end of test of Last_name
}//end of new_record
/**
2) display all last names and first names in the file.
Open the file for reading, read each record and
display the field values.
a) display all the lastName, firstName paired fields in the file;
display with the format lastName, firstName
b) when all records have been displayed, display the record count - the record count is the number of records read and should equal the number of records in the file
c) after all the records and the count have been displayed, display the user choices
*/
public void display_names()
{
//delare variables to hold file types
File file = new File(filename);
//try to open the file for reading
try
{
if(file.exists()){ //if the file exists allow it to be read
BufferedReader br = new BufferedReader(new FileReader(filename)); //Allows the file to be read line by line
String line = br.readLine();
int count = 0;
System.out.println("");
while(line != null){
System.out.println(line);
line = br.readLine();
count++;
}
System.out.println("");
System.out.println("Total records read: " +count);
br.close();
}
}
catch(IOException ioe)
{
System.out.println("display_names: Exception opening the file");
}
}//end of display_names
/**
1) search an address file for a particular last name
and then display the Last name, the first name, and
the phone for each match
2) display the count of records which match the last name
*/
public void search(String LastName)
{
//Declare variables to hold file types
File file = new File(filename);
this.findMe = LastName;
//try to open the file for reading
try
{
if(file.exists()){
BufferedReader br = new BufferedReader(new FileReader(filename)); //Allows the file to be read line by line
String s="", line = null;
int count = 0;
while((line = br.readLine()) != null){
String [] parts = line.split(",");
if(parts[0].equals(findMe)){
count = 1;
s= line;
}
}
System.out.println("\n"+s+"\n");
System.out.println("Total matching records found: " +count);
br.close();
}
}
catch(IOException ioe)
{
System.out.println("search: Exception opening the file");
}
}//end of search
}//end of class
Tester Code:
import java.util.*;
public class TestContactList
{
/**
main
*/
public static void main(String args [])
{
final int ONE = 1;
final int TWO = 2;
final int THREE = 3;
final int FOUR = 4;
final int FIVE = 5;
Scanner scan = new Scanner(System.in);
/*
*/
while(true)
{
System.out.println("1) Search an address file for a particular last name ");
System.out.println("2) Display all last names and first names in the file ");
System.out.println("3) Add a new record to the file ");
System.out.println("4) End the program ");
System.out.print("Please choose 1 - 4: ");
int choice = scan.nextInt();
scan.nextLine();
/*
Create a new ContactList object with the name of the
contact list file.
*/
ContactList cl = new ContactList("MyAddressBook.txt");
/*
if 4 exit program
*/
if(choice == FOUR)
{
System.exit(0);
}
/*
if 1 call search method
*/
if(choice == ONE)
{
System.out.print("Enter name to find: ");
String findMe = scan.nextLine();
cl.search(findMe);
}
/*
if 2 call display_names method
*/
if(choice == TWO)
{
cl.display_names();
}
/*
if 3 call new_record method
*/
if(choice == THREE)
{
cl.new_record();
}
}//end of while loop
}//end of main
}
thanks in advance xD, I think this should be a simple fix
well, it seems that the data files are the ones missing here :-) but from your code
while((line = br.readLine()) != null){
s += line;
count++;
}
System.out.println("\n"+s+"\n");
it seems that you're appending your items into "s" and only in the end you're embracing it between newlines.
Instead, I think you should add the newline inside the while loop.
Of course, there are other issues like using StringBuilder or StringBuffer to concatenate strings.
Your format string (String.format) needs to have a line separator.

how to generate a .txt file from a list whose title is an abbreviation of a full name

this is what I'm trying to accomplish:
To write a program code such that when the user is allowed to enter an employee name from the given list of employees, the program will search for
the employee’s payroll data and then generate a report in the form of a .txt file,
whose file name is the employee’s first initial of his / her first name, followed by
their complete last name.
For example, if a report is generated for David Davies, the report will be located in the text file bearing the name DDavies.txt.
I've generated the list and I know how to pick the records I'm looking for. My problem is in creating a text file based on the user selection.
i.e How do I create a file DDavies.txt based on a user entering "David Davies" as 1 string.
Since names have different lengths, that means each string length is potentially different so I can't pick out the characters by index alone (or I don't know how).
Since each full name is in 1 string, I was thinking of writing a code to pick the very first character, then the following string after the break(space) BUT since it's all in 1 string and the length isn't fixed, I don't know how to accomplish that.
And Filewriter doesn't help matters cos' I have to specify the .txt extension to create a text file so I don't know how to generate the text file dynamically (having a specified title) without entering the name myself.
I was thinking of breaking the string apart into a first and last name basis but that will change the code fundamentally cos what I'm trying to accomplish is part of a larger program.
Please pardon my long intro, this is my first time so I hope I'm being specific enough.
Below is the code. (Please note that the report doesn't need to be displayed to the user, I just need it to be generated in that firstInitial-LastName format)Thanks guys!
//Report.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.JOptionPane;
public class Report {
String firstLine = "", secondLine = "", thirdLine = "";
double hours = 0, wages = 0;
DecimalFormat twoDecimal = new DecimalFormat("0.00");
static ArrayList<String> emps = new ArrayList<String>();
public Report() throws Exception {
//code here the logic to create a report for the user
FileReader file = new FileReader("payroll.txt");
BufferedReader buffer = new BufferedReader(file);
String line;
File check = new File("Overtime.txt");
FileWriter file1;
if (check.exists())
file1 = new FileWriter("Overtime.txt", true);
else
file1 = new FileWriter("Overtime.txt");
int count = 0;
while ((line = buffer.readLine()) != null) {
firstLine = line;
secondLine = buffer.readLine();
thirdLine = buffer.readLine();
double grosspay;
emps.add(line);
}//end while
buffer.close();
file1.close();
String empList = "";
Collections.sort(emps);
for (String str : emps) {
empList += str + "\n";
}
//Employee Listing (names)
JOptionPane.showMessageDialog(null, "Name:\n" + empList, "Employee Listing",
JOptionPane.PLAIN_MESSAGE);
//Get input then of desired employee name to save employee data to a file
String userInput = "";
while (userInput == null || userInput.equals("")) {
userInput = JOptionPane.showInputDialog("To get a payroll report, enter a name from the list");
}
if (empList.toLowerCase().contains(userInput.toLowerCase())) {
/*Upon retrieval of a CORRECT employee name that exists from the employee list,
open payroll.txt file, grab the employee data from the name given
and write the emp's data to a file given the employee’s first initial of his / her first name,
followed by their complete last name. **THIS IS WHERE I NEED HELP!!** */
/**Examples of random names to choose from, we have David Davies, Hyacinth Ho, Betty Boop etc**/
// "Report Generated" Notification
JOptionPane.showMessageDialog(null, "Report Generated.", "Result", JOptionPane.PLAIN_MESSAGE);
}
//Error Message
else {
JOptionPane.showMessageDialog(null, "Error!! Name invalid or doesn't exist, please try again.");
}
System.exit(0);
} //END of Public Report ()
public static void main(String[] args) throws Exception {
new Report();
} //End of Main
} // End of Report Class
After checking the user input is not null and is correct. Try this:
String userInput;
....
String filename;
String[] split = userInput.split(" ");
//get the first names first character and gets the last name
filename = userInput.charAt(0)+split[split.length-1];
I was thinking of writing a code to pick the very first character, then the following string after the break(space) BUT since it's all in 1 string and the length isn't fixed, I don't know how to accomplish that.
You can use yourString.charAt(0) to pick first character of String.
To pick string after fist space you can just find index of that first space using yourString.indexOf(' ') and substring after it.
Example
String someString = "Foo Bar";
System.out.println(someString.charAt(0)
+ someString.substring(someString.indexOf(' ') + 1))
//+1 because we don't want to include space in substring
output: FBar
You can also add ".txt" to result.
Perhaps this is what you want:
String name = "Doctor Who";
String[] name_parts = name.split(" ");
String filename = name_parts[0].charAt(0) + name_parts[1] + ".txt");
//filename = DWho.txt

Java Delete a line from txt after reding the file [duplicate]

This question already has answers here:
Java - delete line from text file by overwriting while reading it
(3 answers)
Closed 8 years ago.
I have this file
1007 book1 5 3
1004 book2 4 1
1003 book3 3 0
1002 book4 2 1
and I am trying to delete the book number 1004 from the file, but before that I let the user enter the number of the book that he wants to delete.
First check if the book exists in the file or not, if the book is exists I delete it if not show "the book does not exists".
Scanner kb = new Scanner(System.in);
FileInputStream book = new FileInputStream("input.txt");
Scanner infile = new Scanner(book);
FileOutputStream out = new FileOutputStream("output.txt");
PrintWriter pw = new PrintWriter(out);
boolean found = false;
System.out.print("Enter the bookID : ");
int bID = kb.nextInt();
while(infile.hasNext()){
int id = infile.nextInt();
String title = infile.next();
int quantity = infile.nextInt();
int bQuantity = infile.nextInt();
if(bID == id){
found = true;
}
if(found == true){
pw.printf("%8d\t%-30s\t%8d\t%8d", infile.nextInt(), infile.next(), infile.nextInt(), infile.nextInt());
infile.nextLine();
System.out.println("The book has been deleted");
break;
}
}
if(found == false)
System.out.print("Not found");
pw.close();
infile.close();
I am trying to print all the file with out the book I have deleted.
You will need a book class, like this:
public class Book {
private int series;
private String name;
private int intA;
private int intB;
public Book(int series,String name, int intA, int intB) {
this.series = series;
this.name = name;
this.intA = intA;
this.intB = intB;
}
....
.... (add other methods as needed, you will definitely need a
toString() method, and getIntA(), getIntB(), getSeriesNum(),
getName() etc.)
}
When you use scanner to read the file, read them into an arraylist of type Book. When user enter a number, use a for loop to find the Book that matches that number, and remove that book object from your arraylist.
Also, try to keep data in memory and not write files too often. Writing files to disks is very inefficient comparing with changing data in memory. Once user is done with all his/her operations, you can use a printwriter to write the data to your file.
To read your file into this array of objects, you can do this:
public static ArrayList<Book> readbooklist() {
ArrayList<Book> booklist = new ArrayList<Book>();
File file = new File("path/filename.fileextension");
try {
Scanner scnr = new Scanner(file);
while (scnr.hasNextLine()) {
String entry = scnr.nextLine();
String [] parts = entry.split("\t"); // Depends on how data was delimited
int series = Integer.parseInt(parts[0]);
int intA = Integer.parseInt(parts[2]);
int intB = Integer.parseInt(parts[3]);
Book single = new Book(series, parts[1], intA, intB);
booklist.add(single);
}
scnr.close();
} catch (FileNotFoundException e) {
System.out.println("File Not Found!");
}
return booklist;
}
Remember to import proper dependency at the beginning of your class. Wish it helps!
I'd recommend to use a Map to store each line as value and the Id as the key only once. That way you don't have to reopen the file and read it each time you want to remove or add an entry, all you have to do is remove it and add it to the map. Once you are done, you can overwrite the old file you have by the values stored in the map or just create a new temp file to hold the data, delete the old file and then rename the temp file with old file's name
Store all the lines you would like to save in a String and close the scanner. Create a printwriter, print the string to the file and close it.
Example code:
File file = new File("yourTextFile.txt");
Scanner in = new Scanner(file);
String saveThisToFile = "";
while (in.hasNext()) {
String temp = in.nextLine();
if (condition to be true if you whant to keep this line) {
saveThisToFile += temp + "\n";
}
}
in.close();
PrintWriter printWriter = new PrintWriter(file);
printWriter.print(saveThisToFile);
printWriter.close();

Categories

Resources