Displaying Information Within Random Access File - java

I have created an application that allows the user to enter their account number, balance(no more than 99999), and last name. The program will take this information and insert it into a .txt file at a location corresponding to the account number(acct). Here is the code for that:
import java.io.*;
public class NationalBank {
public static void main(String[] args) throws Exception{
InputStreamReader temp = null;
BufferedReader input = null;
try {
temp = new InputStreamReader(System.in);
input = new BufferedReader(temp);
int acct;
double amount;
String name;
RandomAccessFile file = new RandomAccessFile("bank.txt", "rw");
while(true) {
// Asks for input
System.out.println("Enter Account Number (0-9999): ");
acct = Integer.parseInt(input.readLine());
System.out.println("Enter Last Name: ");
name = input.readLine();
System.out.println("Enter Balance ");
amount = Double.parseDouble(input.readLine());
// Making sure account numbers are between 0 and 9999
if(acct >=0 && acct <= 9999) {
file.seek(acct*17);
file.write(truncateName(name));
file.writeBytes(" " +amount);
}
else {
continue;
}
// Asks user if more entries are needed
System.out.println("Enter More? (y/n)");
if (input.readLine().toLowerCase().equals("n"))
break;
}
file.close();
}
catch (Exception e) {
}
}
// Truncate/adding spaces to name until 8 characters
public static byte[] truncateName (String name) {
byte[] result = new byte[8];
for (int i = 0; i < 8; i++)
result [i] = i < name.length () ? (byte)name.charAt (i) : (byte)' ';
return result;
}
}
Now, I am trying to make an application that will write back all of the accounts that have information within them(with last name and balance). I need to display the account number, balance, and last name of those accounts. So far, I have:
import java.io.*;
public class DisplayBank {
public static void main(String[] args) throws IOException {
FileInputStream input = new FileInputStream ("bank.txt");
try {
byte[] record = new byte[17];
while (input.read(record) == 17) {
String name = new String(record, 0, 8);
long bits = 0;
for (int i = 8; i < 17; i++) {
bits <<= 8;
bits |= record[i] & 0xFF;
}
double amount = Double.longBitsToDouble(bits);
System.out.println("Account Number: " + record + " Name: " + name + ", amount: " + amount);
}
}
catch (IOException e) {
}
finally {
input.close();
}
}
}
This currently displays only the name correctly. The balance is incorrect, and I don't know how to get the account number. In order to get the account number, I would need to get the position of name. In order to get the amount, I would need to seek name, offset 9 bytes, then read the next 8 bytes...

If you want to parse a text file that contains last names and amounts similar what you provided:
example provided
LastName 93942.12
What I would do is to try something like the following
public void read_file(){
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("C:\\Users\\Alos\\Desktop\\test.txt");
// Use DataInputStream to read binary NOT text.
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
int record = 0;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
String[] splits = strLine.split("\t");
String LastName = splits[0];
String Amount = splits[1];
System.out.println("Account Number: " + record + " Name: " + LastName + ", amount: " + Amount);
record++;
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
This might not be exactly what you're looking for but please take a look and update your question if you would like something different.

I it's not a homework, I would strongly recommend to use some RDBMS like Derby or MySQL.

Related

Java File Problems

So we want an application to allow the user to enter the names and grades of students the user should be prompted for the name of the file to create and for the number of students to be entered (1 grade per student). Then the program takes all of the grades and averages them. The problem is that it is not reading the file and always gives us a average of -0.0.
`
public static void main(String[] args) throws IOException {
System.out.println("What is the name of the file you would like to create?");
filename = p.next();
File fd = new File(filename + ".txt");
fd.createNewFile();
students(fd);
}
public static void students(File fd) throws IOException {
int numbstudents;
FileWriter ap = new FileWriter(fd, true);
BufferedWriter ad = new BufferedWriter(ap);
System.out.println("How many students would you like to add?");
numbstudents = p.nextInt();
int i = 0;
while (i != numbstudents) {
for (i = 0; i < numbstudents; i++) {
System.out.println("What is the name of student number " + i + " ?");
String name = p.next();
ad.write(name);
ad.newLine();
System.out.println("What grade did student number " + i + " acheive?");
String a = f.next();
ad.write(a);
ad.newLine();
}
}
read(fd);
ad.close();
}
public static void read(File fd) throws FileNotFoundException {
int counter = 0;
FileReader h;
BufferedReader g;
String test;
double average, total = 0;
int number = 0;
int i = 0;
try {
h = new FileReader(fd);
g = new BufferedReader(h);
while ((test = g.readLine()) != null) {
number += 1;
System.out.println(test);
counter = counter + 1;
i = counter % 2;
if (i == 0) {
total += Double.parseDouble(test);
}
}
average = total / (number - 1);
System.out.println("The students average is: " + average);
g.close();
fd.delete();
} catch (FileNotFoundException e) {
System.out.println("File could not be found.");
} catch (IOException e) {
System.out.println("Your file could not be read.");
}
}
}
`
You're attempting to read from the file before you've closed the writer.
The close() call includes flushing buffered data to disk. You're reading before data is flushed to disk.
As a side note, consider what you're accomplishing with this pair of statements:
while (i != numbstudents) {
for (i = 0; i < numbstudents; i++) {
The while is unnecessary. The for statement iterates over the comfortably numb students.
Also note the difference in conditions between the two. In general, when iterating over numbers, it's safer to use '<', '<=', '>' or '>=' than '==' or '!='. Otherwise, if you pass by the endpoint before an equality condition, it will continue happily past the end.
Finally, consider naming your methods with descriptive verb phrases. This will help you with breaking the big problem down into smaller pieces. For example, you could have one method called inputStudents() that reads input and creates and closes the file, called before another method printAverageOfStudents() that reads the file and computes the average.

How would I change this code to make it so that it asks me the location of the file that I want to load?

So my code currently has the user specify the name of the file that they want to load within the code itself but how would I make it so that when the program is run then the user will enter the location of the file that they want to load?
import java.io.*;
import java.util.*;
public class reader {
static int validresults = 0;
static int invalidresults = 0;
//used to count the number of invalid and valid matches
public static boolean verifyFormat(String[] words) {
boolean valid = true;
if (words.length != 4) {
valid = false;
} else if (words[0].isEmpty() || words[0].matches("\\s+")) {
valid = false;
} else if ( words[1].isEmpty() || words[1].matches("\\s+")) {
valid = false;
}
return valid && isInteger(words[2]) && isInteger(words[3]);}
//checks to see that the number of items in the file are equal to the four needed and the last 2 are integers
//also checks to make sure that there are no results that are just whitespace
public static boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
//checks to make sure that the data is an integer
public static void main(String[] args) throws FileNotFoundException {
String hteam;
String ateam;
int hscore;
int ascore;
int totgoals = 0;
Scanner s = new Scanner(new BufferedReader(
new FileReader("fbscores.txt"))).useDelimiter("\\s*:\\s*|\\s*\\n\\s*");
while (s.hasNext()) {
String line = s.nextLine();
String[] words = line.split("\\s*:\\s*");
//splits the file at colons
if(verifyFormat(words)) {
hteam = words[0]; // read the home team
ateam = words[1]; // read the away team
hscore = Integer.parseInt(words[2]); //read the home team score
totgoals = totgoals + hscore;
ascore = Integer.parseInt(words[3]); //read the away team score
totgoals = totgoals + ascore;
validresults = validresults + 1;
System.out.println(hteam + " " + "[" + hscore + "]" + " " + ateam + " " + "[" + ascore + "]");
//output the data from the file in the format requested
}
else{
invalidresults = invalidresults + 1;
}
}
System.out.println("Total number of goals scored was " + totgoals);
//displays the the total number of goals
System.out.println("Valid number of games is " + validresults);
System.out.println("Invalid number of games is " + invalidresults);
System.out.println("EOF");
}
}
One approach would be to use a main loop asking for a file name and quitting program execution when no input is given.
Therefore I'd refactor most code of your main method into another function e.g. processFile(String fileName).
Then your main only deals with user input
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
while(true){ //keep running till we break
System.out.println("Enter filename or return blank line to quit");
String fileName = sc.nextLine();
if(fileName != null && !fileName.isEmpty()){
processFile(fileName)
}else{
break; //no user input => exit
}
}
System.out.println("bye");
}
private static processFile(String fileName){
String hteam;
String ateam;
int hscore;
int ascore;
int totgoals = 0;
Scanner s = new Scanner(new BufferedReader(
new FileReader(fileName))).useDelimiter("\\s*:\\s*|\\s*\\n\\s*");
while (s.hasNext()) {
… //rest of your original code
}

How can I read numeric passwords in Java?

I am trying to get the user to enter a four digit pin but I don't want it to be printed out on the screen as they type it. I have tried using System.console().readPassword(); like so:
import java.util.Scanner;
import java.io.*;
import java.util.InputMismatchException;
public class VirtualATM{
private static String Details;
public static void main(String [] args){
try{
//Create variables & scanner to be used throughout the program.
Scanner sc = new Scanner(System.in);
boolean RegisterOrExist = false;
int cardNo = 0;
String DirToWriteFile = System.getProperty("user.dir") + "/VirtualATM.txt"; //Get path to write text file to.
DirToWriteFile.trim();
File file = new File(DirToWriteFile);
// if file doesn't exists, then create it
if (!file.exists()) {
file.createNewFile();
}
//Create writer to write to files.
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
System.out.println("Enter card number, or type register to register a new card.");
String register = sc.nextLine();
if(register.equalsIgnoreCase("register")){
RegisterOrExist = false;
RegisterNewCard();
} else {
RegisterOrExist = true;
cardNo = Integer.valueOf(register);
}
bw.write(Details);
//Close the writer.
bw.close();
} catch(IOException e) {
e.printStackTrace();
}
}
/*** Method for registering a new card **/
public static void RegisterNewCard(){
Scanner sc = new Scanner(System.in);
System.out.print("Name: ");
String name = sc.nextLine();
int MaxVal = Integer.MAX_VALUE;
int CardNo = new java.util.Random().nextInt(MaxVal) + 1;
int balance = new java.util.Random().nextInt(10000) + 1;
boolean OverDraft = false;
int OverDraftLimit = 0;
if(OverDraft = true){
OverDraftLimit = 250;
}
char [] PIN = {};
System.out.println("Create a FOUR digit pin: ");
try{
PIN = System.console().readPassword();
}catch(InputMismatchException e){
e.printStackTrace();
}
int P1 = (int) PIN[0];
int P2 = (int) PIN[1];
int P3 = (int) PIN[2];
int P4 = (int) PIN[3];
int [] PinNo = {P1, P2, P3, P4};
Details = "Name: " + name + " CardNo: " + CardNo + " Current Balance: " + balance + " overdraft? " + OverDraft + " OverDraftLimit: " + OverDraftLimit + " pin: " + PinNo;
}
}
I then try to write the pin int [] pinNo = {P1, P2, P3, P4} to a text file using the BufferedWriter. I get the following this text in the text file when I input the pin as 2566:
[I#42a57993
Is there another way to read a password without it printing on the screen as the user types?
well this line
bw.write(Details);
is writing the details in the file where
Details = "..otherdetails..."+"pin: " + PinNo;
shows that you are writing the hash of the array. So simply replace "pin: " + PinNo with
the actual elements of the array
You can simply follow what Rod said or try this
Details = "..otherdetails..."+"pin: " + java.util.Arrays.toString(PinNo)
Tip - using this makes you password more secure
try like this
char[] PIN = System.console.readPassword();
Arrays.fill(password, ' ');
problem:
pin: " + PinNo;
You are actually printing the memory location of the array object not the array elements itself
solution:
you can get each index of the PinNo array and append each of them to the string
"pin: " + PinNo[0] + PinNo[1] + PinNo[2] + PinNo[3]
If you are trying to run your code on Eclipse IDE console then it'll not work. It is bug System.console() (Java 6.0) returns null when running inside Eclipse.
You need to run from command prompt or teminal, etc.
For more on this see these post :-
Hide input on command line - stackoverflow
Masking password input from the console - stackoverflow

Updating a double in a text file

I have an ArrayList with user accounts stored into a text file, each account represents a virtual bank account.
What is the most efficient way for me to update the balance of an account, after a user decides to add, or withdraw money?
I have successfully retrieved the balance, just need to save it.
Here is what I have so far, most of the magic happens in the ATM and Bank classes
ATM CLASS
public class ATM {
public static void main(String[] args) throws IOException {
Bank bank = new Bank();
double balance = 0;
// Welcome screen
String dash = "-------------------\n";
System.out.print(dash);
System.out.print("Welcome to the Bank\n");
System.out.print(dash);
System.out.println("Do you have an account with us? (y/n) ");
Scanner scanner = new Scanner(System.in);
String answer = scanner.nextLine();
while (true) {
if (answer.equalsIgnoreCase("y")) {
System.out.println("Username: ");
String userName = scanner.next();
System.out.println("PIN: ");
int pin = scanner.nextInt();
bank.hasUser(userName, pin);
if (bank.hasUser(userName, pin)) {
User.balance = bank.getBalance(userName, pin, balance);
bank.menu();
break;
} else if (!bank.hasUser(userName, pin)) {
System.out.println("\n** Incorrect username or password, please try again**\n");
}
} else if (answer.equalsIgnoreCase("n")) {
Bank.newUser();
break;
} else {
System.out.println("\nThat's not an option, do you have an account with us?");
}
}
}
}
BANK CLASS
public class Bank {
public static void newUser() {
// new user is created
String dash = "-------------------\n";
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your full name below (e.g. John M Smith): ");
String name = scanner.nextLine();
System.out.println("Create a username: ");
String userName = scanner.nextLine();
System.out.println("Enter your starting deposit amount: ");
double balance = scanner.nextDouble();
System.out.print(dash);
System.out.print("Generating your information...\n");
System.out.print(dash);
int pin = PIN();
String accountNum = Bank.accountNum();
User user = new User(name, userName, pin, accountNum, balance);
// new user gets added to the array list
Bank.users.add(user);
try {
File file = new File("users.text");
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
BufferedWriter bw = new BufferedWriter(fw);
bw.append(String.valueOf(Bank.users + "\n"));
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void menu() {
while (true) {
System.out.print("\n1");
System.out.print(" - Acount Summary ");
System.out.print("3");
System.out.print(" - Deposit Money\n");
System.out.print("2");
System.out.print(" - Withdraw Money ");
System.out.print("4");
System.out.print(" - Exit\n\n");
System.out.print("I would like to: \n");
Scanner bscanner = new Scanner(System.in);
int mc = bscanner.nextInt();
if (mc == 1) {
System.out.print("Your current balance is: $"
+ User.getBalance() + "\n");
} else if (mc == 2) {
System.out.print("Enter withdrawl amount: ");
double wd = bscanner.nextDouble();
User.balance -= wd;
System.out.println("\n$" + User.getBalance()
+ " is your new account balance.");
} else if (mc == 3) {
System.out.print("Enter deposit amount: ");
double dp = bscanner.nextDouble();
User.balance += dp;
System.out.println("\n$" + User.getBalance()
+ " is your new account balance.");
} else if (mc == 4) {
System.exit(0);
} else {
System.out
.print("\nThat's not an option, please select an option listed below!\n");
}
}
}
public boolean hasUser(String userName, int pin) {
try {
BufferedReader reader = new BufferedReader(new FileReader(
"users.text"));
String line;
while ((line = reader.readLine()) != null) {
line = line.replaceAll("[\\[\\]]", "");
String[] tokens = line.split(",");
if (userName.equals(tokens[1])
&& pin == Integer.parseInt(tokens[3])) {
return true;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
public double getBalance(String userName, int pin, double balance) {
boolean r = false;
try {
BufferedReader br = new BufferedReader(new FileReader("users.text"));
String line;
while ((line = br.readLine())!= null) {
line = line.replaceAll("[\\[\\]]", "");
String[] num = line.split(",");
if (userName.equals(num[1]) && pin == Integer.parseInt(num[3])) {
r = true;
}
if (r) {
balance = Double.parseDouble(num[4]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return balance;
}
// array list for users
static ArrayList users = new ArrayList();
{
};
}
A good way to do this would be to keep the accounts in ArrayList (as you are doing) and then just save the whole text file again. If you are dealing with small amounts of data it would not take very long. (A better way to think about optimizing is not re-opening the file every time you need to access it's data, just keep it in an array list).
Also, you may not need to save the file after every change. If you are the only app using the file try just saving it when you get closed.
If you want really good performance you will need a data base.
You have to write to the file i dont see any of that...
File fileWriter = new File("user.txt"); //recall it or whatever
PrintWriter writer = new PrintWriter(new FileWriter(fileWriter, true)); //APPEND
writer.println(balance, name, eg...);
writer.close();
}
Printwriter is more effective than filewriter, and filewriter is needed anyhow but this will work, also if you want to do multiples people then just for loop it, and dont forget to close!
for (int i = 0; i < users; i++) { //the for loop
if you still have issues then ask again i've done dbms and the other answer is wayyy off. Hope this helps!

OutOfBoundsException When Calling Return For A Method JAVA

i'll get straight to the chase. If a user wants to read another file they must type r in the menu, then they are thrown with a return readFile(); method which takes them to the top of the program and asks them the same question it did at the beggining when they first ran this program. Only issue is when you type R or Default it throws an OutOFBoundsException. BTW It is Reading a CSV file
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1000
at studentrecs.StudentRecs.in(StudentRecs.java:71)
at studentrecs.StudentRecs.readFile(StudentRecs.java:55)
at studentrecs.StudentRecs.menu(StudentRecs.java:97)
at studentrecs.StudentRecs.main(StudentRecs.java:33)
Java Result: 1
/
public static Boolean readFile(String filename) throws IOException { //Constructor for filename
try {
Scanner userInput = new Scanner(System.in);
System.out.println("Type R To Read a File or Type Default for the default file");
user = userInput.nextLine();
if (user.equalsIgnoreCase("r")) {
user = userInput.nextLine();
}
filename = user;
if (user.equalsIgnoreCase("default")) {
filename = "newreg2.csv";
}
Scanner input = new Scanner(new FileReader(filename));
while (input.hasNext()) {
in(input.nextLine());
numstu++;
}
input.close();
return true;
} catch (IOException e) {
System.err.println(e.getMessage());
}
return false;
}
public static void in(String reader) {
String splitter[];
splitter = reader.split(",");
stu[numstu] = new StuRec();
stu[numstu].studentID = splitter[0];
stu[numstu].lastName = splitter[1];
stu[numstu].firstName = splitter[2];
stu[numstu].phoneNumber = splitter[3];
stu[numstu].courseCode = splitter[4];
stu[numstu].periodNumber = Integer.parseInt(splitter[5]); // parseInt turns a string of digits into an integer
stu[numstu].mark = Integer.parseInt(splitter[6]);
}
public static boolean menu() throws IOException {
String choice;
Scanner userInput = new Scanner(System.in);
System.out.println("=============================================");
System.out.println("Type R To Read Another File");
System.out.println("Type L To Print all File Records");
System.out.println("Type AA To Print The Average Of All The Marks");
System.out.println("Type X To Exit The Program");
choice = userInput.nextLine();
double average = 0.0; // declare average
if (choice.equalsIgnoreCase("L")) {
for (int i = 0; i < numstu; i++) {
System.out.println(stu[i].lastName + ", " + stu[i].firstName + ", " + stu[i].studentID + ", " + stu[i].phoneNumber + ", " + stu[i].courseCode + ", " + stu[i].periodNumber + ", " + stu[i].mark);
}
}else if (choice.equalsIgnoreCase("R")){
return readFile(filename);
} else if (choice.equalsIgnoreCase("AA")) {
for (int i = 0; i < numstu; i++) {
average += stu[i].mark; // keep adding to average
}
}else if (choice.equalsIgnoreCase("X")) {
for (int i = 0; i < numstu; i++) {
System.exit(i);
}
}else if (choice.equalsIgnoreCase("AC")) {
} else {System.err.println("Unknown Key Try Again...");
}
// divide by zero protection
if ( choice.equalsIgnoreCase("AA") && numstu > 0 ) {
average = average/numstu; // compute the average. Always use the size in terms of a variable whenever possible.
System.out.println(average); // as noted below, if this is an integer value, < #of students computations will eval to 0.
}
else if (!choice.equalsIgnoreCase("AA") && numstu < 0) {
System.out.println("Oops! No Marks To Calculate! :(");
}
return menu();
}
}
It looks like EITHER you have initialised numstu to start at 1, OR you have more than 1000 lines in your file.
The effect of either of these errors would be that you eventually attempt to write data to entry 1000 of stu. But since you've initialised stu with 1000 entries, numbered from 0 to 999, this gives your error.
You should make sure that numstu is initially 0, not 1.
And next time you post a question, post ALL of your code, not just the parts where you think the error might be. It's very difficult for most people to find bugs in code that they can't see.

Categories

Resources