Reading information from a textfile to get specific information - java

I am working on an assignment where I have to create an interval(which I have already completed) and from a text file, read in the girls names that are found within the interval and put them into an array list. I also have to read in all the male names that start with the letter "J", and then calculate how many male births start with the letter "J" and print out that information. Below is the code I have so far:
public static int generateRandomInt(int lowerLimit, int upperLimit) {
int value = lowerLimit + (int)Math.ceil( Math.random() * ((upperLimit - lowerLimit) + 1)); //generates a random number between 1 and 10
return value;
}// end generateRandomInt
public static void main(String[] args) {
// Read from filename: top20namesNM1994.txt
// Generating a interval, the lower random number comes from 50 to 100, and the upper random number comes from 150 to 200.
// Print out this interval
// Read all the girls names, which birth numbers are inside of the interval you construct, into a array or ArrayList.
// Print out the array.
//Print out all the males names, which start with letter "J".
//Determine how many male births start with names starting with the letter "J", and print out the summary information.
final int LOW1 = 50;
final int LOW2 = 100;
final int HIGH1 = 150;
final int HIGH2 = 200;
ArrayList<String>girlNames = new ArrayList<String>();
String line = "";
int interval_low = generateRandomInt(LOW1, LOW2);
int interval_high = generateRandomInt(HIGH1, HIGH2);
System.out.println("The interval is ( " + interval_low + " , " + interval_high + " )" );
try {
FileReader inputFile = new FileReader("C:\\Users\\drago\\eclipse-workspace-Ch6to7FinalExam2\\MorrisJFinalExam2\\src\\top20namesNM1994.txt");
//Scanner scan = new Scanner (inputFile);
BufferedReader br = new BufferedReader(inputFile);
while((line = br.readLine()) != null) {
line.split("\\s+");
if()
girlNames.add();
}
}
catch(IOException e) {
System.out.println("File not Found!");
}
if()
System.out.println(girlNames.toString());
}
I am stuck on how to get the girl names that are within the interval created and also how to read in the boy names. Attached is the text file.
TextFile

Okay...you know how to read in the text file (somewhat) which is good however you can simplify the code a bit:
ArrayList<String> girlNames = new ArrayList<>();
String filePath = "C:\\Users\\drago\\eclipse-workspace-Ch6to7FinalExam2\\"
+ "MorrisJFinalExam2\\src\\top20namesNM1994.txt";
String line = "";
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
while ((line = br.readLine()) != null) {
// .....................
// ..... Your Code .....
// .....................
}
}
catch (IOException ex) {
ex.printStackTrace();
}
Try With Resources is used here so that your BufferedReader is automatically closed. If all your going to do is read the desired text file then the Scanner object you have commented out in your code is also a pretty good alternative for reading text files if properly used.
It's obvious from your incomplete code that each data line within this file is White-Space or Tab delimited simply based on the Regular Expression ("\\s+") used within the String#split() method (the "\\s+" expression will split a string on any number of white-spaces and or tabs that are contained within that string). Do Note however that the code line where you are using the String#split() method is not completed properly.... If you read the linked tutorial you will find that this method is used to fill a String Array which is good because usually, this is what you want to do with file data lines. Doing so of course allows you to retrieve the exact data portion desired from each data file line.
No one here has a clue what is contained within your specific data text file because like so many others the contents within it is obviously so supper-duper classified that not even fictitious data will suffice. Because of this there is in no way a means provide you with an accurate array index value or values to use against your String Array in order to retrieve your desired data from each data file line. This is good however since it is you who needs to figure this out and once you do you will have the task beaten to submission.

Related

Read data from file and convert to key value pair

I have the below integers in File :
758 29
206 58
122 89
I have to read these integers in an integer array and then need to store the values in key value pair. Then print the output as :
Position 29 has been initialized to value 758.
Position 89 has been initialized to value 122.
I have tried as of now :
private static Scanner readFile() {
/*
* Your program will prompt for the name of an input file and the read
* and process the data contained in this file. You will use three
* integer arrays, data[], forward[] and backward[] each containing 100
* elements
*/
int data[] = new int[100];
int forward[] = new int[100];
int backward[] = new int[100];
System.out.print("Please enter File Name : ");
#SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
String filename = scanner.nextLine();
File inputFile = new File(filename);
Scanner linReader = null;
try {
linReader = new Scanner(new File(filename));
while (linReader.hasNext()) {
String intStringSplit = linReader.nextLine();
String[] line = intStringSplit.split("\t",-1);
data = new int[line.length];
for (int i = 0; i < data.length; i++) {
data[i] = Integer.parseInt(line[i]);
}
System.out.println(data);
}
linReader.close();
} catch (Exception e) {
System.out.println("File Not Found");
}
return linReader;
}
I am not able to figure out how to get the key and value from the read data.
When posting information related to your question it is very important that you provide the data (in file for example) exactly as it is intended in reality so that we can make a more positive determination as to why you are experiencing difficulty with your code.
What you show as an in file data example indicates that each file line (which contains actual data) consists of two specific integer values. The first value being the initialization value and the second being the position value.
There also appears to be a blank line after ever line which contains actual data. This really doesn't matter since the code provided below has a code line to take care of such a thing but it could be the reason as to why you may be having difficulty.
To me, it looks like the delimiter used to separate the two integer values in each file line is indeed a whitespace as #csm_dev has already mentioned within his/her comment but you claim you tried this in your String.split() method and determined it is not a whitespace. If this is truly the case then it will be up to you to determine exactly what that delimiter might be. We couldn't possibly tell you since we don't have access to the real file.
You declare a File object within your provided code but yet nowhere do you utilize it. You may as well delete it since all it's doing is sucking up oxygen as far as I'm concerned.
When using try/catch it's always good practice to catch the proper exceptions which in this case is: IOException. It doesn't hurt to also display the stack trace as well upon an exception since it can solve a lot of your coding problems should an exception occur.
This code should work:
private static Scanner readFile() {
/*
* Your program will prompt for the name of an input file and the read
* and process the data contained in this file. You will use three
* integer arrays, data[], forward[] and backward[] each containing 100
* elements
*/
int data[] = new int[100];
int forward[] = new int[100];
int backward[] = new int[100];
System.out.print("Please enter File Name : ");
Scanner scanner = new Scanner(System.in);
String filename = scanner.nextLine();
File inputFile = new File(filename); // why do you have this. It's doing nothing.
Scanner linReader = null;
try {
linReader = new Scanner(new File(filename));
while (linReader.hasNext()) {
String intStringSplit = linReader.nextLine();
// If the file line is blank then just
// continue to the next file line.
if (intStringSplit.trim().equals("")) { continue; }
// Assuming at least one whitespace is used as
// the data delimiter but what the heck, we'll
// use a regular expression within the split()
// method to handle any number of spaces between
// the integer values.
String[] line = intStringSplit.split("\\s+");
data = new int[line.length];
for (int i = 0; i < line.length; i++) {
data[i] = Integer.parseInt(line[i]);
}
System.out.println("Position " + data[1] +
" has been initialized to value " +
data[0] + ".");
// do whatever else you need to do with the
// data array before reading in the next file
// line......................................
}
linReader.close();
}
catch (IOException ex) {
System.out.println("File Not Found");
ex.printStackTrace();
}
return linReader;
}

Randomly search a text file for keyword using fastest & efficient string-search method

I've got a text file with one customer record per line. Each record is formatted as "ID num, first name, last name, dollar amount". I need to read a line of this text file based on the ID number entered by the user.
I've been following a Java ebook that does this by using the length of a single record and multiplying it by the ID number entered. The problem is, that only works if every record has the exact same length. My records do not truncate or pad out the first and last name, and the dollar amount ranges from two to five characters in length which means that the method that the book uses won't work.
Is there any way to read a specific line in a text file without requiring all the records to be the exact same length? I'd have thought that there would be a way to use the line separator character to do it.
For reference I'll put up the code that doesn't work due to my varying record sizes, in case it helps.
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
Path filepath = Paths.get("U:\\Programming\\Java\\Chapter 13\\customersdata.txt");
String s = " , , , 00.00" + System.getProperty("line.separator");
final int RECSIZE = s.length();
byte[] data = s.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(data);
FileChannel fc = null;
try {
fc = (FileChannel)Files.newByteChannel(filepath, READ, WRITE);
System.out.println("Enter an ID number to display the customer details for that ID. Or \"quit\".");
String idString = keyboard.nextLine();
while(!idString.equals("quit")) {
int id = Integer.parseInt(idString);
buffer = ByteBuffer.wrap(data);
fc.position(id * RECSIZE);
fc.read(buffer);
s = new String(data);
System.out.println("ID #" + id + " " + s);
System.out.println("Enter an ID number to display the customer details for that ID. Or \"quit\".");
idString = keyboard.nextLine();
}
fc.close();
}catch(Exception e) {
System.out.println("Error message: " + e);
}
}
EDIT: As the text file being read from could hypothetically contain tens of thousands of records, I can't use Sequential Access, if the ID number I need is near the bottom of the file, it would take an unacceptable amount of time to read them all, as such, the solution must be Random Access.
I've got a text file with one customer record per line. Each record is
formatted as "ID num, first name, last name, dollar amount". I need to
read a line of this text file based on the ID number entered by the
user.
and
Is there any way to read a specific line in a text file without
requiring all the records to be the exact same length?
In the main method at readData("33"), i hardcoded the id string. You can change it according to your data.txt and get the data.
data.txt
1 harry singh 456
2 lauren dat 25
33 pingle pooh 8797
10002 yogeshvari bahman 897461
parseTxt.java
import java.io.File;
import java.util.Scanner;
public class parseTxt {
private static Scanner fileReader ;
public static void main(String[] args)
{
try{
readData("33");
} catch(Exception e){
System.out.println("Exception : " + e);
}
}
private static void readData(String id) throws Exception{
fileReader = new Scanner(new File("E://data.txt"));
String cusId, fname, lname, dollar;
while(fileReader.hasNextLine()){
String line = fileReader.nextLine();
String[] lineParts = line.split(" ");
if(lineParts[0].equals(id)){ // lineParts[0] is ID NUMBER
cusId = lineParts[0];
fname = lineParts[1];
lname = lineParts[2];
dollar = lineParts[3];
System.out.println("Customer ID : #" + cusId);
System.out.println("First Name : " + fname);
System.out.println("Last Name : " + lname);
System.out.println("Dollar Amount : $" + dollar);
break;
} else {
System.out.println("This ID:" + id + " does not exist");
}
}
}
}
For Edited Question (search while keeping good performance)
source-1:
try (SeekableByteChannel ch = Files.newByteChannel(Paths.get("test.txt"))) {
ByteBuffer bb = ByteBuffer.allocateDirect(1000);
for(;;) {
StringBuilder line = new StringBuilder();
int n = ch.read(bb);
// add chars to line
// ... don't forget to break
}
}
It requires a bit of coding but it can be really faster because of ByteBuffer.allocateDirect. It allows OS to read bytes from file to ByteBuffer directly, without copying
source-2: Every answer on this link adds bits of information
Convert the search string ('are') to a byte-array in the same
encoding as the file.
Open a memory-mapped byte-buffer from a File-Channel on the file.
Scan the ByteBuffer, looking for matches to the search byte-array
count the newlines as you go.
close the ByteBuffer
source-3:
A simple technique that could well be considerably faster than indexOf() is to use a Scanner, with the method findWithinHorizon(). If you use a constructor that takes a File object, Scanner will internally make a FileChannel to read the file. And for pattern matching it will end up using a Boyer-Moore algorithm for efficient string searching.
source-4: Implementation of Boyer-Moore's String Search algorithm
I am sorry but I will leave the researching to you. If you ask my suggestion, I think GNU-Grep is faster of them all because it, too, uses Boyer-Moore's string search algorithm.
Hope this helps! correct me if i misunderstood your problem.

Find a specific line in a file, write that line and the 2 after to a new file

I need to search for a specific line in a .txt file like someones name and then write the name and the next 2 lines after which is data about the person to a new file.
How it should work:
I enter a menu which lists employees taken from an arraylist and asks for my input for who I want a "report" for. I enter "John Doe" and the program creates a "report" called "JDoe.txt" and searches the arraylist for "John Doe" and writes his name in the new file along with his information (the next 2 lines after his name in the same file).
My code is creating the "report" and is writing data to it, but it just writing the data of what is first in the arraylist and not specifically the user who I entered. How do I write for the specific user I inputted?
Here is some of the code I have which is in the right direction but isn't producing what I want and I can't seem to figure out a fix:
import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class Report { // FirstName LastName, Programmer
public Report() {
// code here the logic to create a report for the user
try {
String empList = "";
ArrayList<String> emps = new ArrayList<>();
String[] firstLine = new String[100], secondLine = new String[100], thirdLine = new String[100];
int index;
FileReader file = new FileReader("payroll.txt");
BufferedReader buffer = new BufferedReader(file);
String line;
for (index = 0; index < 100; index++) {
firstLine[index] = "";
secondLine[index] = "";
thirdLine[index] = "";
}
index = 0;
while ((line = buffer.readLine()) != null) {
firstLine[index] = line;
secondLine[index] = buffer.readLine();
thirdLine[index] = buffer.readLine();
emps.add(firstLine[index]);
index++;
}
buffer.close();
Collections.sort(emps);
for (String str : emps) {
empList += str + "\n";
}
String input = JOptionPane.showInputDialog(null, empList,
"Employee List", JOptionPane.PLAIN_MESSAGE);
index = 0;
// Iterate through the array containing names of employees
// Check if a match is found with the input got from the user.
// Break from the loop once you encounter the match.
// Your index will now point to the data of the matched name
if (emps.contains(input)) {
JOptionPane.showMessageDialog(null, "Report Generated.",
"Result", JOptionPane.PLAIN_MESSAGE);
String names[] = new String[2];
names = input.split(" ");
String fileName = names[0].charAt(0) + names[1] + ".txt";
// Create a FileWritter object with the filename variable as the
// name of the file.
// Write the necessary data into the text files from the arrays
// that
// hold the employee data.
// Since the index is already pointing to the matched name, it
// will
// also point to the data of the matched employee.
// Just use the index on the appropriate arrays.
File check1 = new File(fileName);
FileWriter file2;
if (check1.exists())
file2 = new FileWriter(fileName, true);
else
file2 = new FileWriter(fileName);
BufferedWriter buffer2 = new BufferedWriter(file2);
buffer2.write("Name: " + firstLine[index]);
buffer2.newLine();
buffer2.write("Hours: " + secondLine[index]);
buffer2.newLine();
buffer2.write("Wage: " + thirdLine[index]);
buffer2.newLine();
buffer2.close();
} else {
JOptionPane.showMessageDialog(null, input + " does not exist");
Report rpt = new Report();
}
} catch (IOException e) {
System.out.println(e);
}
}
public static void main(String[] args) {
new Report();
}
}
What the file it is reading from looks like:
There were two problems I found. The first was that after you when through and built your list of names, you were setting index = 0, and it never got changed.
for (String str : emps) {
empList += str + "\n";
}
//Make the JOptionPane...
index = 0;
This meant you were always getting the first value. If you set index to 1, you would get the second value. You can use the method indexOf(Object o) from the ArrayList library to get the correct index given the name that the user input. Example:
int i = emps.indexOf(input);
buffer2.write("Name: " + firstline[i]);
However, this would only partly solve the problem, as you sorted the list of employee names in emps, but not in the arrays you are using to write.
One solution to this is to not sort the emps array, which gives you the correct ordering to indexOf to work properly, but the employees listed in the JOptionPane will be listed in the order they were in the file.
However, since the values given for each employee are tied to that employee, I would suggest using a data structure that ties those values to the employee name, such as a Map. (Documentation is here: http://docs.oracle.com/javase/7/docs/api/java/util/Map.html ).
To initialize it, you can use it like this. I'm using a linkedHashMap because it came to my mind, you can select the proper type for your needs.
LinkedHashMap myMap<String, String[]> = new LinkedHashMap<String, String[]>();
The first field, String is your Key, which will be your employees name. The Value is the String[], and can be an array with the required two values. This ties these values to the name, ensuring they cannot get lost. To check for a name, just use myMap.containsKey(name), and compare to null to see if it exists, and then use myMap.get(name) to get the entry for that name.

Check if large list of words has specific length

I have a dictionary text file of around 60000 words. I would like to read in that text file and see if it has a certain amount of n words, provided by the user. At the recommendation of my Professor, I'm going to create a method that expands the array to compensate the different n values. I know how to do that. My question is, how do I initially read the text file and determine if each of the 60000 words has a specific n length?
I know I have to use a loop and import the file: (although I've never done throw exception)
Scanner inputFile = new Scanner(new File("2of12inf.txt"));
for(int i = 0; i < sizeWord; i++) {
}
But what I would normally do is use a charAt(i) , and check if the word has n many characters. But I can't possibly do that for 60000 words. Suggestions?
try{
BufferedReader br = new BufferedReader(new FileReader(new File("2of12inf.txt")));
String line;
while ((line = br.readLine()) != null) {
// process the line.
int lineLength = line.length();
// assuming each line contains one word, do whatever you want to with this length
}
} catch (Exception e) {
System.out.println("Exception caught! Should handle it accordingly: " + e);
} finally {
be.close();
}

Read one line of a csv file in Java

I have a csv file that currently has 20 lines of data.
The data contains employee info and is in the following format:
first name, last name, Employee ID
So one line would like this: Emma, Nolan, 2
I know how to write to the file in java and have all 20 lines print to the console, but what I'm not sure how to do is how to get Java to print one specific line to the console.
I also want to take the last employee id number in the last entry and have java add 1 to it one I add new employees. I thinking this needs to be done with a counter just not sure how.
You can do something like this:
BufferedReader reader = new BufferedReader(new FileReader(<<your file>>));
List<String> lines = new ArrayList<>();
String line = null;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
System.out.println(lines.get(0));
With BufferedReader you are able to read lines directly. This example reads the file line by line and stores the lines in an array list. You can access the lines after that by using lines.get(lineNumber).
You can read text from a file one line at a time and then do whatever you want to with that line, print it, compare it, etc...
// Construct a BufferedReader object from the input file
BufferedReader r = new BufferedReader(new FileReader("employeeData.txt"));
int i = 1;
try {
// "Prime" the while loop
String line = r.readLine();
while (line != null) {
// Print a single line of input file to console
System.out.print("Line "+i+": "+line);
// Prepare for next loop iteration
line = r.readLine();
i++;
}
} finally {
// Free up file descriptor resources
r.close();
}
// Remember the next available employee number in a one-up scheme
int nextEmployeeId = i;
BufferedReader reader =new BufferedReader(new FileReader("yourfile.csv"));
String line = "";
while((line=reader.readLine())!=null){
String [] employee =line.trim().split(",");
// if you want to check either it contains some name
//index 0 is first name, index 1 is last name, index 2 is ID
}
Alternatively, If you want more control over read CSV files then u can think about CsvBeanReader that will give you more access over files contents..
Here is an algorithm which I use for reading csv files. The most effective way is to read all the data in the csv file into a 2D array first. It just makes it a lot more flexible to manipulate the data.
That way you can specify which line of the file to print to the console by specifying it in the index of the array and using a for. I.e: System.out.println(employee_Data[1][y]); for record 1. y is the index variable for fields. You would need to use a For Loop of course, to print every element for each line.
By the way, if you want to use the employee data in a larger program, in which it may for example store the data in a database or write to another file, I'd recommend encapsulating this entire code block into a function named Read_CSV_File(), which will return a 2D String array.
My Code
// The return type of this function is a String.
// The CSVFile_path can be for example "employeeData.csv".
public static String[][] Read_CSV_File(String CSVFile_path){
String employee_Data[][];
int x;
int y;
int noofFields;
try{
String line;
BufferedReader in = new BufferedReader(new FileReader(CSVFile_path));
// reading files in specified directory
// This assigns the data to the 2D array
// The program keeps looping through until the line read in by the console contains no data in it i.e. the end of the file.
while ( (( line = in.readLine()) != null ){
String[] current_Record = line.split(",");
if(x == 0) {
// Counts the number of fields in the csv file.
noofFields = current_Record.length();
}
for (String str : values) {
employee_Data[x][y] = str;
System.out.print(", "+employee_Data[x][y]);
// The field index variable, y is incremented in every loop.
y = y + 1;
}
// The record index variable, x is incremented in every loop.
x = x + 1;
}
// This frees up the BufferedReader file descriptor resources
in.close();
/* If an error occurs, it is caught by the catch statement and an error message
* is generated and displayed to the user.
*/
}catch( IOException ioException ) {
System.out.println("Exception: "+ioException);
}
// This prints to console the specific line of your choice
System.out.println(("Employee 1:);
for(y = 0; y < noofFields ; y++){
// Prints out all fields of record 1
System.out.print(employee_Data[1][y]+", ");
}
return employee_Data;
}
For reading large file,
log.debug("****************Start Reading CSV File*******");
copyFile(inputCSVFile);
StringBuilder stringBuilder = new StringBuilder();
String line= "";
BufferedReader brOldFile = null;
try {
String inputfile = inputCSVFile;
log.info("inputfile:" + inputfile);
brOldFile = new BufferedReader(new FileReader(inputfile));
while ((line = brOldFile.readLine()) != null) {
//line = replaceSpecialChar(line);
/*do your stuff here*/
stringBuilder.append(line);
stringBuilder.append("\n");
}
log.debug("****************End reading CSV File**************");
} catch (Exception e) {
log.error(" exception in readStaffInfoCSVFile ", e);
}finally {
if(null != brOldFile) {
try {
brOldFile.close();
} catch (IOException e) {
}
}
}
return stringBuilder.toString();

Categories