首页 > 代码库 > 文件及输入输出流模拟ATM机
文件及输入输出流模拟ATM机
题目:两部分要求都要实现。
一、ATM机的账户记录Account有账户的唯一性标识(11个长度的字符和数字的组合),用户的姓名,操作日期(Date),操作类型,账户密码(六位的数字,可以用0开头),当前的余额(可以为0)。 模拟ATM的功能设计,用户插卡后显示选择语言界面,输入密码界面,用户输入正确密码(用户输入错误密码,则提示该卡已被锁定,无法操作),则弹出选择界面:存款、取款、转账汇款、修改密码、查询余额。 选择“取款”,则显示100元、500元、1000元、1500元、2000元、5000元、其他金额、退卡、返回操作供用户选择; 选择“存款”,则提示用户输入存款金额,修改余额; 选择“转账”,则提示用户输入转账行号、转账金额,并提示转账成功。
二、假定银行的一个存取款系统有两类客户,一类是现金用户,一类是信用卡用户。银行对每个客户都要登记其姓名name,并为之分配一个唯一的账户号码aid,现金用户还要记录其卡的类型(工资卡、借记卡、理财卡),而信用卡用户则根据其信用级别有一定的透支限额lineOfCredit(A级10000元、B级5000元、C级2000元、D级1000元)。每种客户都可以实现存deposit、取withdraw、和查询余额getBalance,信用卡用户还可以查询透支情况findOverdraw。对于现金用户,每次取款操作只能在账户实际额度balance内操作,允许现金用户改变自己的帐户类型。
(1) 分析有哪些属性和方法可以作为两个子类的共同属性和方法,然后写出抽象类
Account的定义。
(2) 分析CashAccount有那些新增的属性和方法,定义一个继承于Account的子类
CashAccount。
(3) 分析CreditAccount有那些新增的属性和方法,然后定义一个继承于Account
的子类CreditAccount,添加增加的属性和方法。
(4) 请按照要求编写一个程序Test,用你所定义的类完成下列业务操作。
1) 用 Account 作为类型定义两个变量 credit 和 debit,分别引用
CreditAccount和CashAccount的对象,并完成存款500元的操作。
第 3 页 共 5 页
2) 每个对象完成取款200元的操作后再次取款400元,请输出各自的余额。
3) 可以通过credit查看引用对象的透支额吗,如果不能,怎样修改可以查
看?
(5) 添加一个取款异常WithdrawException,请定义异常类WithdrawException,
要求:
1) 异常对象记录取款发生时的帐户余额、取款额还有取款人。
2) 覆盖继承于超类的方法getMessage(),按以下格式返回信息:
取款人,账号余额,取款额,原因:透支。
3) 修改CashAccount的取款方法,当用户取款超出额度时,抛出异常。
4) 编写一个可执行类Test,创建一个CashAccount的对象,其初始余额为500,
连续取款2次,每次300,写出运行结果。
(6) 构建客户基本信息表(ClientInfoTable.txt)和账户流水表(BankInfoTable
.txt)两个数据文件;
客户基本信息表存储信息包括账户号码aid(唯一性),姓名name,,客户
类型(现金卡用户或信用卡用户),卡类型(工资卡、借记卡、理财卡(客户
类型为现金卡时有效)),信用卡透支类型(A级10000元、B级5000元、C级
2000元、D级1000元),卡余额,日期;
账户流水表存储信息包括序号(自动增 1,并保持唯一),账户号码,姓
名,日期,流水类型(存款、取款、透支取款),金额。
(7) 增加查询功能,可以查询账号或姓名查询客户信息,可以查询账号或姓名查询
流水信息。
(8) 增加统计功能,可以根据账号,起始日期、终止日期、流水类型,统计账号流
水信息。
***************************************************************************************************************
拿到这个题目,我开始分析出:
两类账户及其操作可以由不同的类来表示;
存款、转账、取款等操作实际上对文件的读写、修改等操作;
增加的统计功能实际上是考察如何对文件进行统一格式的读写操作。
画上代码的继承关系和类包含的方法图:
前两段代码就是展开写两个类CashAccount(现金用户)和CreditAccount(信用卡用户)类。
第一段代码:
1 package ATM; 2 import java.io.*; 3 import java.util.Calendar; 4 import java.util.GregorianCalendar; 5 import java.util.Scanner; 6 import java.util.StringTokenizer; 7 8 abstract class Account1{ 9 //抽象类,现金类用户和信用卡用户父类。 10 String aid,name; 11 double balance;//余额 12 public void deposit(){}//存款 13 public void withdraw(){}//取款 14 public void getBalance(){}//查询余额 15 public void getMssage(){}//查询信息 16 } 17 public class CashAccount extends Account1{ 18 String cardtype;//卡的类型 19 CashAccount(){ 20 this.aid=""; 21 this.name=""; 22 this.balance=0; 23 } 24 CashAccount(String a,String b,double c,String d){ 25 this.aid=a; 26 this.name=b; 27 this.balance=c; 28 this.cardtype=d; 29 } 30 /* 31 *存款方法,写操作 32 */ 33 public void deposit(PrintWriter in,int i){ 34 Scanner s1=new Scanner(System.in); 35 System.out.println("请输入要存入的数额"); 36 double s=s1.nextDouble(); 37 balance=balance+s; 38 System.out.println("存款成功!您的余额为"+balance); 39 this.Writerecord(in, "存款", s,i);//调用函数 40 } 41 /* 42 * 取款方法,写操作 43 */ 44 public void withdraw(PrintWriter in,int i){ 45 System.out.println("请输入要取的数额"); 46 Scanner S=new Scanner(System.in); 47 double s=S.nextDouble(); 48 try{ 49 if(balance-s>0){ 50 balance=balance-s; 51 System.out.println("取款成功!您的余额为"+balance); 52 this.Writerecord(in, "取款", -s,i); 53 } 54 else 55 throw new WithdrawException("余额不足!重新输入!"); 56 }catch(WithdrawException e){System.out.println(e); 57 this.getMssage(s); 58 withdraw(in,i);} 59 } 60 /* 61 显示余额方法,写入操作 62 */ 63 public void getBalance(PrintWriter in,int i){ 64 System.out.println("您的余额为"+balance); 65 this.Writerecord(in, "查询余额", 0,i); 66 } 67 /* 68 改变卡类型方法 69 */ 70 public void Changetype(PrintWriter in,int i){ 71 System.out.println("您当前的卡类型为"+cardtype); 72 System.out.println("选择您需要的卡类型\n1.工资卡\n2.借记卡\n3.理财卡"); 73 Scanner S=new Scanner(System.in); 74 int s=S.nextInt(); 75 switch(s){ 76 case 1:cardtype="工资卡";break; 77 case 2:cardtype="借记卡";break; 78 case 3:cardtype="理财卡";break; 79 } 80 this.Writerecord(in, "变更卡的类型", 0,i); 81 } 82 /* 83 * 显示信息方法*/ 84 public void getMssage(double a){ 85 System.out.println("取款人"+name+"\n"+"账户余额"+balance+"\n"+"取款额"+a+"\n"+"原因:透支"); 86 } 87 /* 88 * 写文件的方法 89 * @参数 out在print writer*/ 90 public void writeData(PrintWriter out) throws IOException 91 { 92 out.println(aid + "|" 93 + name + "|" 94 + cardtype + "|" 95 + Double.toString(balance)); 96 } 97 /* 98 * 独文件的方法 99 * @ in的参数在buffer 100 */ 101 public void readData(BufferedReader in) throws IOException 102 { 103 String s = in.readLine(); 104 StringTokenizer t = new StringTokenizer(s, "|"); 105 aid=t.nextToken(); 106 name = t.nextToken(); 107 cardtype=t.nextToken(); 108 balance=t.countTokens(); 109 } 110 /* 111 * 写操作记录的方法 112 * 参数来自主类的文件路径和print writer 113 * */ 114 public void Writerecord(PrintWriter in,String op,double a,int i) { 115 String months[] = { 116 "Jan", "Feb", "Mar", "Apr", 117 "May", "Jun", "Jul", "Aug", 118 "Sep", "Oct", "Nov", "Dec"}; 119 //初始化当前时间并在后续写入文件 120 Calendar calendar = Calendar.getInstance(); 121 in.println(String.valueOf(i)+"|"+aid + "|" 122 + name + "|"+String.valueOf(calendar.get(Calendar.YEAR))+ 123 "|"+String.valueOf(months[calendar.get(Calendar.MONTH)])+"|"+ 124 String.valueOf(calendar.get(Calendar.DATE)) 125 + "|"+String.valueOf(calendar.get(Calendar.HOUR))+"|"+ 126 String.valueOf(calendar.get(Calendar.MINUTE)) 127 +"|"+op+"|" 128 + Double.toString(a)); 129 } 130 } 131 class WithdrawException extends Exception{ 132 WithdrawException(String s){super(s);} 133 }
第二段:
1 package ATM; 2 import java.io.*; 3 import java.util.Calendar; 4 import java.util.GregorianCalendar; 5 import java.util.Scanner; 6 import java.util.StringTokenizer; 7 8 public class CreditAccount extends Account1 { 9 double lineOfCredit;//信用等级对应的可透支额 10 String creditrate;//信用等级 11 CreditAccount(){ 12 this.aid=""; 13 this.name=""; 14 this.balance=0; 15 this.lineOfCredit=0; 16 this.creditrate="A"; 17 } 18 CreditAccount(String a,String b,double c,String d){ 19 this.aid=a; 20 this.name=b; 21 this.balance=c; 22 this.creditrate=d; 23 switch(d){ 24 case "A":lineOfCredit=10000;break; 25 case "B":lineOfCredit=5000;break; 26 case "C":lineOfCredit=2000;break; 27 case "D":lineOfCredit=1000;break; 28 } 29 } 30 /* 31 * 存款方法 32 * */ 33 public void deposit(PrintWriter in,int i){ 34 System.out.println("请输入要存入的数额"); 35 Scanner S=new Scanner(System.in); 36 double s=S.nextDouble(); 37 balance=balance+s; 38 System.out.println("存款成功!您的余额为"+balance); 39 this.Writerecord(in, "存款", s,i); 40 } 41 /* 42 * 取款方法*/ 43 public void withdraw(PrintWriter in,int i){ 44 System.out.println("请输入要取的数额"); 45 Scanner S=new Scanner(System.in); 46 double s=S.nextDouble(); 47 try{ 48 if(balance-s>0){ 49 balance=balance-s; 50 System.out.println("取款成功!您的余额为"+balance); 51 this.Writerecord(in, "取款", -s,i); 52 } 53 else 54 if(lineOfCredit+balance-s>0){ 55 balance=balance-s; 56 lineOfCredit=lineOfCredit+balance; 57 System.out.println("您的余额为"+balance+"您的可透支余额为"+lineOfCredit); 58 } 59 else 60 throw new WithdrawException("余额不足!重新输入!"); 61 }catch(WithdrawException e){System.out.println(e); 62 this.getMssage(s); 63 withdraw(in,i);} 64 } 65 /*显示余额方法 66 * */ 67 public void getBalance(PrintWriter in,int i){ 68 System.out.println("您的余额为"+balance); 69 this.Writerecord(in, "查询余额", 0,i); 70 } 71 /*显示可透支余额方法 72 * */ 73 public void findOverdraw(PrintWriter in,int i){ 74 System.out.println("您的可透支余额为"+lineOfCredit); 75 this.Writerecord(in, "查询可透支余额", 0,i); 76 } 77 /*显示信息方法 78 * */ 79 public void getMssage(double a){ 80 System.out.println("取款人"+name+"\n"+"账户余额"+balance+"\n"+"取款额"+a+"\n"+"原因:透支"); 81 } 82 /* 83 * 写文件的方法 84 * @参数 out在print writer*/ 85 public void writeData(PrintWriter out) throws IOException 86 { 87 out.println(aid + "|" 88 + name + "|"+ creditrate + "|" 89 + Double.toString(lineOfCredit) + "|" 90 + Double.toString(balance)); 91 } 92 /* 93 * 独文件的方法 94 * @ in的参数在buffer 95 */ 96 public void readData(BufferedReader in) throws IOException 97 { 98 String s = in.readLine(); 99 StringTokenizer t = new StringTokenizer(s, "|"); 100 aid=t.nextToken(); 101 name = t.nextToken(); 102 creditrate=t.nextToken(); 103 lineOfCredit=Double.parseDouble(t.nextToken()); 104 balance=Double.parseDouble(t.nextToken()); 105 } 106 /* 107 * 写操作记录的方法 108 * 参数来自主类的文件路径和print writer 109 * */ 110 public void Writerecord(PrintWriter in,String op,double a,int i) { 111 String months[] = { 112 "Jan", "Feb", "Mar", "Apr", 113 "May", "Jun", "Jul", "Aug", 114 "Sep", "Oct", "Nov", "Dec"}; 115 //初始化当前时间并在后续写入文件 116 Calendar calendar = Calendar.getInstance(); 117 in.println(String.valueOf(i)+"|"+aid + "|" 118 + name + "|"+String.valueOf(calendar.get(Calendar.YEAR))+ 119 "|"+months[calendar.get(Calendar.MONTH)]+"|"+ 120 String.valueOf(calendar.get(Calendar.DATE)) 121 + "|"+String.valueOf(calendar.get(Calendar.HOUR))+"|"+ 122 String.valueOf(calendar.get(Calendar.MINUTE))+"|"+ 123 op+"|"+Double.toString(a)); 124 } 125 }
第三段代码包含一个Record类,其中包含读取记录和统计以及重写的ToString方法。
第三段:
package ATM; import java.io.*; import java.util.Scanner; import java.util.StringTokenizer; public class Record { String aid,name,operation; int number,year,month,data,hour,minute; double money; /* * 读取操作记录的方法*/ public void readData(BufferedReader in)throws IOException{ int i=0; String s = in.readLine(); StringTokenizer t = new StringTokenizer(s, "|"); number=Integer.parseInt(t.nextToken()); aid=t.nextToken(); name = t.nextToken(); year=Integer.parseInt(t.nextToken()); switch(t.nextToken()){ case "Jan":i=1;break; case "Feb":i=2;break; case "Mar":i=3;break; case "Apr":i=4;break; case "May":i=5;break; case "Jun":i=6;break; case "Jul":i=7;break;case "Aug":i=9;break; case "Sep":i=9;break;case "Oct":i=10;break; case"Nov":i=11;break;case "Dec":i=12;break; } month=i; data=Integer.parseInt(t.nextToken()); hour=Integer.parseInt(t.nextToken()); minute=Integer.parseInt(t.nextToken()); operation=t.nextToken(); money=Double.parseDouble(t.nextToken()); } /* * 统计操作记录的方法 * 参数分别为 * 记录数组 * 1代表按aid查询 2代表按日期查询 * s表示aid*/ public void Sort(Record[] a,int i,String s){ if(i==1)//按照aid查询所有记录 { System.out.println("您的操作记录为"); for (Record e : a) if(e.aid.equals(s)) System.out.println(e); } else if(i==2)//按照aid和日期查找记录 { System.out.println("请输入您想查找的时间区间"); Scanner q=new Scanner(System.in); System.out.println("请输入您想查找的起始年,格式为2016"); int tyear=q.nextInt(); System.out.println("请输入您想查找的起始月,格式为3"); int tmonth=q.nextInt(); System.out.println("请输入您想查找的起始日期,格式为1"); int tdata=http://www.mamicode.com/q.nextInt(); System.out.println("请输入您想查找的终止年,格式为2016"); int tyeare=q.nextInt(); System.out.println("请输入您想查找的终止月,格式为3"); int tmonthe=q.nextInt(); System.out.println("请输入您想查找的终止日期,格式为1"); int tdatae=q.nextInt(); for (Record e : a) if(e.aid.equals(s)&&e.year>=tyear&&e.year<=tyeare&&e.month>=tmonth&&e.month<=tmonthe &&e.data>=tdata&&e.data<=tdatae) System.out.println(e); q.close(); } } //将对象转换为字符串 public String toString() { return getClass().getName() + "[number="+String.valueOf(number)+" aid=" + aid + ",name=" + name+" "+String.valueOf(year)+"/"+String.valueOf(month)+"/"+ String.valueOf(data)+"/"+String.valueOf(hour)+"/"+String.valueOf(minute)+"/" + "操作:" + operation+" 金额: "+String.valueOf(money) + "]"; } }
第四段代码就是主类,其中包含界面控制、等操作。
第四段:
1 package ATM; 2 import java.io.*; 3 import java.util.Scanner; 4 5 public class Login { 6 public static void main(String[] args){ 7 int number=1; 8 CashAccount[] a=new CashAccount[3]; 9 CreditAccount[] b=new CreditAccount[3]; 10 a[0]=new CashAccount("01","a",100,"借记卡"); 11 a[1]=new CashAccount("02","b",100,"借记卡"); 12 a[2]=new CashAccount("03","c",100,"借记卡"); 13 b[0]=new CreditAccount("04","d",100,"A"); 14 b[1]=new CreditAccount("05","e",100,"A"); 15 b[2]=new CreditAccount("06","f",100,"A"); 16 try 17 { 18 // 写入文件,从末尾写入 分别写现金操作和信用卡操作 19 //不论记录数据还是记录操作,都按现金和信用卡分别建立文件 1对应信用卡 20 PrintWriter out = new PrintWriter(new FileWriter("C://ClientInfoTable.txt"),true); 21 PrintWriter out1 = new PrintWriter(new FileWriter("C://ClientInfoTable1.txt"),true); 22 PrintWriter in = new PrintWriter(new FileWriter("C://BankInfoTable.txt",true)); 23 PrintWriter in1 = new PrintWriter(new FileWriter("C://BankInfoTable1.txt",true)); 24 in.println("序号"+"|"+"卡号"+"|"+"姓名"+"|"+"年"+"|"+"月"+"|"+"日"+"|"+"时"+"|"+"分"+"|"+"操作类型"+"|"+"金额"); 25 in1.println("序号"+"|"+"卡号"+"|"+"姓名"+"|"+"年"+"|"+"月"+"|"+"日"+"|"+"时"+"|"+"分"+"|"+"操作类型"+"|"+"金额"); 26 out.println("卡号"+"|"+"姓名"+"|"+"卡类型"+"|"+"余额"); 27 out1.println("卡号"+"|"+"姓名"+"|"+"信用等级"+"|"+"可透支额"+"|"+"余额"); 28 writeDatacash(a, out); 29 writeDatacredit(b, out1); 30 do{ 31 try{ 32 System.out.print("请选择用户类型\t1.现金卡\t2.信用卡"); 33 Scanner s=new Scanner(System.in); 34 int i=s.nextInt(); 35 if(i==1) 36 {showface(a[i],in,number); 37 in.flush();} 38 else if(i==2) 39 {showface(a[i],in1,number); 40 in.flush();} 41 else 42 throw new In("错误!从1或2中选择输入"); 43 }catch(In e){System.out.print(e); 44 System.exit(0);} 45 number++; 46 }while(number<=6); 47 System.out.print("来统计一下"); 48 Statistics(); 49 out.checkError(); 50 out1.close(); 51 in.close(); 52 in1.close(); 53 } 54 catch(IOException exception) 55 { 56 exception.printStackTrace(); 57 } 58 } 59 //现金用户界面 60 static void showface(CashAccount a,PrintWriter in,int number){ 61 String s="*****************************************\n"; 62 s=s+" 模拟银行ATM系统 \n"; 63 s=s+"*****************************************\n"; 64 s=s+" 1、存款\n"; 65 s=s+" 2、取款\n"; 66 s=s+" 3、查询余额\n"; 67 s=s+" 4、改变卡的种类\n"; 68 s=s+" 5、输入5结束\n"; 69 do{ 70 System.out.println(s); 71 Scanner S1=new Scanner(System.in); 72 int i=S1.nextInt(); 73 if(i==1) 74 a.deposit(in,number); 75 else if(i==2) 76 a.withdraw(in,number); 77 else if(i==3) 78 a.getBalance(in,number); 79 else if(i==4) 80 a.Changetype(in,number); 81 else 82 break; 83 }while(true); 84 } 85 //信用卡用户界面 86 static void showface(CreditAccount a,PrintWriter in,int number){ 87 String s1="*****************************************\n"; 88 s1=s1+" 模拟银行ATM系统 \n"; 89 s1=s1+"*****************************************\n"; 90 s1=s1+" 1、存款\n"; 91 s1=s1+" 2、取款\n"; 92 s1=s1+" 3、查询余额\n"; 93 s1=s1+" 4、查询可透支余额\n"; 94 s1=s1+" 5、输入5结束\n"; 95 do{ 96 System.out.println(s1); 97 Scanner S1=new Scanner(System.in); 98 int i=S1.nextInt(); 99 if(i==1) 100 a.deposit(in,number); 101 else if(i==2) 102 a.withdraw(in,number); 103 else if(i==3) 104 a.getBalance(in,number); 105 else if(i==4) 106 a.findOverdraw(in,number); 107 else 108 break; 109 }while(true); 110 } 111 /** 112 将信息写入文件,现金用户 113 @param out a print writer 114 */ 115 static void writeDatacash(CashAccount[] employees, PrintWriter out) 116 throws IOException 117 { 118 // write number of employees 119 out.println(employees.length); 120 121 for (CashAccount e : employees) 122 e.writeData(out); 123 } 124 /** 125 将信息写入文件,信用卡用户 126 @param out a print writer 127 */ 128 static void writeDatacredit(CreditAccount[] account, PrintWriter out) 129 throws IOException 130 { 131 // write number of employees 132 out.println(account.length); 133 134 for (CreditAccount e : account) 135 e.writeData(out); 136 } 137 /** 138 将记录信息读进Record类数组 139 */ 140 static Record[] readDatarecord(BufferedReader in) 141 throws IOException 142 { 143 Record[] a = new Record[6]; 144 for (int i = 0; i < 6; i++) 145 { 146 a[i] = new Record(); 147 a[i].readData(in); 148 } 149 return a; 150 } 151 /** 152 读现金用户 153 @param in the buffered reader 154 @return the array of employees 155 */ 156 static CashAccount[] readData(BufferedReader in) 157 throws IOException 158 { 159 // retrieve the array size 160 int n = Integer.parseInt(in.readLine()); 161 162 CashAccount[] employees = new CashAccount[n]; 163 for (int i = 0; i < n; i++) 164 { 165 employees[i] = new CashAccount(); 166 employees[i].readData(in); 167 } 168 return employees; 169 } 170 /** 171 Reads an array of 信用卡用户 from a buffered reader将文件信息读为数组 172 @param in the buffered reader 173 @return the array of employees 174 */ 175 static CreditAccount[] readDatacredit(BufferedReader in) 176 throws IOException 177 { 178 CreditAccount[] a = new CreditAccount[6]; 179 for (int i = 0; i < 6; i++) 180 { 181 a[i] = new CreditAccount(); 182 a[i].readData(in);; 183 } 184 return a; 185 } 186 /* 187 * 实现统计功能 188 * */ 189 static void Statistics()throws IOException{ 190 // 将文件中的内容读进一个新数组 191 BufferedReader in = new BufferedReader(new FileReader("C:\\BankInfoTable.txt")); 192 String t=in.readLine(); 193 BufferedReader in1 = new BufferedReader(new FileReader("C:\\BankInfoTable1.txt")); 194 String t1=in1.readLine(); 195 do{ 196 try{ 197 System.out.print("请选择用户类型\n1.现金卡\n2.信用卡\n3.退出"); 198 Scanner s=new Scanner(System.in); 199 int i=s.nextInt(); 200 Record a=new Record(); 201 if(i==1) 202 {Record[] newcashaccount=readDatarecord(in); 203 System.out.println("选择查询方式:\n1.查询您的所有历史操作记录\n2.按日期查询"); 204 int j=s.nextInt(); 205 if(j==1) 206 a.Sort(newcashaccount, 1, "02"); 207 else 208 a.Sort(newcashaccount, 2, "02"); 209 } 210 else if(i==2) 211 {Record[] newcashaccount1=readDatarecord(in1); 212 System.out.println("选择查询方式:\n1.查询您的所有历史操作记录\n2.按日期查询"); 213 int j=s.nextInt(); 214 if(j==1) 215 a.Sort(newcashaccount1, 1, "02"); 216 else 217 a.Sort(newcashaccount1, 2, "02");} 218 else if(i==3) 219 break; 220 else 221 throw new In("错误!从1或2中选择输入"); 222 }catch(In e){System.out.print(e); 223 System.exit(0);} 224 }while(true); 225 in.close(); 226 in1.close(); 227 } 228 } 229 class In extends Exception{ 230 In(String s){super(s);} 231 }
那么现在我把四段代码中的方法的功能参数等写下,然后再把结构说一下就OK。
文件及输入输出流模拟ATM机