8-1 写入日志文件
编写程序,要求:用户在键盘每输入一行文本,程序将这段文本显示在控制台中。当用户输入的一行文本是“exit”(不区分大小写)时,程序将用户所有输入的文本都写入到文件log.txt中,并退出。(要求:控制台输入通过流封装System.in获取,不要使用Scanner)
package test;
import java.io.*;
public class FileOperations {
public static void main(String []args) {
String dirname="src/test/log.txt";
BufferedReader br=null;
BufferedWriter bw=null;
try {
br=new BufferedReader(new InputStreamReader(System.in));//缓冲流
bw=new BufferedWriter(new FileWriter(dirname));
while (true){
String s=br.readLine();
String ss=s.toUpperCase();
if(ss.equals("EXIT"))
break;
System.out.println(s);
bw.write(s);
bw.newLine();//换行
}
bw.flush();
bw.close();
}catch(Exception e){
e.printStackTrace();
}finally {
try {
br.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
8-2 文件和目录输出
查看File类的API文档,使用该类实现一个类FileList
,它提供两个静态方法:1)readContentsInDirectory(String path)
:能够将输入参数path所指定的本地磁盘路径下的所有目录和文件的名称打印出来;2)readContentsInDirectoryRecursive(String path)
:能够将输入参数path所指定的本地磁盘路径下的所有目录(包含所有子孙目录)和文件的名称以层次化结构打印出来。程序的输出如下所示。
package test;
import java.io.*;
public class FileList {
public static void readContentsInDirectory(String path) {
File file=new File(path);
try {
File[] files=file.listFiles();获取File对象的所有子文件和路径
for(File i:files) {
if(i.isFile()) {
System.out.format("[文件] %s\n", i.getName());
}else {
System.out.format("[目录] %s\n", i.getName() );
}
}
}catch(Exception e) {
System.out.println("路径不存在");
}
}
public static void readContentsInDirectoryRecursive(String path,int levels) {
File file=new File(path);
try {
File[] files=file.listFiles();获取File对象的所有子文件和路径
for(File i:files) {
for(int j=0;j<levels;j++) {
System.out.print("--");
}
if(i.isFile()) {
System.out.format("[文件] %s\n", i.getName());
}else {
System.out.format("[目录] %s\n",i.getName());
readContentsInDirectoryRecursive(i.getAbsolutePath(),levels+1);
}
}
}catch(Exception e) {
System.out.println("路径错误");
}
}
}
package test;
import java.util.Scanner;
public class Main {
public static void main(String []args)
{
Scanner cin=new Scanner(System.in);
String path=cin.nextLine();
FileList.readContentsInDirectory(path);
System.out.println("----------------");//分割线
FileList.readContentsInDirectoryRecursive(path, 0);
cin.close();
}
}
8-3 菜单文件处理
假设某个餐馆平时使用:1)文本文件(orders.txt)记录顾客的点菜信息,每桌顾客的点菜记录占一行。每行顾客点菜信息的记录格式是“菜名:数量,菜名:数量,…菜名:数量”。例如:“烤鸭:1,土豆丝:2,烤鱼:1”。2)文本文件(dishes.txt)记录每种菜的具体价格,每种菜及其价格占一行,记录格式为“菜名:价格“。例如:“烤鸭:169”。编写一个程序,能够计算出orders.txt中所有顾客消费的总价格。(注意,请使用文本读写流,及缓冲流来处理文件)
/*假设某个餐馆平时使用:1)文本文件(orders.txt)记录顾客的点菜信息,每桌顾客的点菜记录占一行。
每行顾客点菜信息的记录格式是“菜名:数量,菜名:数量,…菜名:数量”。
例如:“烤鸭:1,土豆丝:2,烤鱼:1”。
2)文本文件(dishes.txt)记录每种菜的具体价格,每种菜及其价格占一行,
记录格式为“菜名:价格“。例如:“烤鸭:169”。
编写一个程序,能够计算出orders.txt中所有顾客消费的总价格。
(注意,请使用文本读写流,及缓冲流来处理文件)*/
import org.omg.CosNaming.NamingContextExtPackage.StringNameHelper;
import java.io.*;
import java.util.*;
public class MenuFileOperations {
public static void main(String[] args) throws FileNotFoundException{
BufferedReader br1=null;//读
//BufferedWriter bw1=null;//写
BufferedReader br2=null;
//BufferedWriter bw2=null;
String path1="D:\\java\\Work8\\src\\orders.txt";//绝对路径
String filename1="src\\orders.txt";// //相对路径(相对于项目工程为根目录)
//File file1=new File(path1);
// 使用Map记录菜名以及数量
Map<String,Integer> orders=new HashMap<String, Integer>();
try{//读入菜单
br1=new BufferedReader(new InputStreamReader(new FileInputStream(filename1)));//创建 FileInputStream通过使用文件描述符 fdObj ,其表示在文件系统中的现有连接到一个实际的文件。
//
// bw1=new BufferedWriter(new FileWriter("scr/orders.txt"));
String s=br1.readLine();//读一行文字。
while(s!=null){
String []s1=s.split(",");
for (int i = 0; i <s1.length ; i++) {
String []s2=s1[i].split(":");
if(s2.length==2){
orders.put(s2[0],Integer.parseInt(s2[1]));
}
}
s=br1.readLine();
}
// bw1.write(s);
// bw1.newLine();
br1.close();
}catch (Exception e){
e.printStackTrace();
}
String path2="D:\\java\\Work8\\src\\dishes.txt";
String filename2="src\\dishes.txt";
//File file2=new File(path2);
//获取价格
int sum=0;
try{
br2=new BufferedReader(new InputStreamReader(new FileInputStream(filename2)));
String ss=br2.readLine();
while(ss!=null) {
String[] ss1 = ss.split(":");
if (ss1.length == 2)
sum += orders.get(ss1[0]) * Integer.parseInt(ss1[1]);
ss=br2.readLine();
}
br2.close();
}catch (Exception e){
System.out.println("路径错误");
}
System.out.println("总价格:"+sum);
}
}
8-4 成绩文件处理
设计学生类Student,属性:学号(整型);姓名(字符串),选修课程(名称)及课程成绩(整型)。编写一个控制台程序,能够实现Student信息的保存、读取。具体要求:(1)提供Student信息的保存功能:通过控制台输入若干个学生的学号、姓名以及每个学生所修课程的课程名和成绩,将其信息保存到data.dat中;(2)数据读取显示:能够从data.dat文件中读取学生及其课程成绩并显示于控制台。(要求,学号和课程成绩按照整数形式(而非字符串形式)存储)
本题考察使用Object流进行对象序列化(串行化)和反序列化
import java.io.*;
import java.util.*;
public class ScoreFileOperations {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
//提供Student信息的保存功能
ObjectOutputStream objectOutputStream=null;
try{
objectOutputStream=new ObjectOutputStream(
new FileOutputStream("data.dat"));
System.out.println("请输入学生数量");
int n=sc.nextInt();
System.out.println("请输入学生信息,例如001 张三 JAVA 95");
for (int i = 0; i < n ; i++) {
Studnet studnet=new Studnet(sc.nextInt(),sc.next(),sc.next(),sc.nextInt());
objectOutputStream.writeObject(studnet);
}
objectOutputStream.writeObject(null);//增加一个空对象,用于以后读取时的判断
}catch (IOException e){
e.printStackTrace();
}finally {
try{
objectOutputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
objectOutputStream.flush();
objectOutputStream.close();
//数据读取显示
try( ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("data.dat")))//这种写法可以省掉finally里的close()语句
{
Studnet s=(Studnet)(objectInputStream.readObject());
while(s!=null){
System.out.println("学号:"+s.getNo()+" 姓名:"+s.getName()+" 课程"+s.getCourse()+" 成绩"+s.getScore());
s=(Studnet)objectInputStream.readObject();
}
}catch (IOException | ClassNotFoundException e){
e.printStackTrace();
}
objectOutputStream.close();
}
}
class Studnet implements Serializable{
private static final long serialVersionUID = 8597440706406158146L;//版本号,标记类的版本,同一版本类下的对象具有兼容性
//serialVersionUID 的作用是什么呢?
//JAVA序列化的机制是通过判断类的serialVersionUID来验证的版本一致的。
// 在进行反序列化时,JVM会把传来的字节流中的serialVersionUID于本地相应实体类的serialVersionUID进行比较。
// 如果相同说明是一致的,可以进行反序列化
private int no;
private String name;
private String course;
private int score;
public Studnet(int no, String name, String course, int score) {
this.no = no;
this.name = name;
this.course = course;
this.score = score;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
8-5 图书馆持久化 (0分)
构造图书类,包含名称(字符串)、作者(字符串)、出版社(字符串)、版本号(整数)、价格(浮点数),构造图书馆类,其中包含若干图书,用容器存储图书对象,然后定义方法void addBook(Book b)添加图书对象,定义方法void persist(),将所有图书存至本地文件books.dat里,定义方法Book[] restore() 从文件books,dat中读取所有图书,并返回图书列表数组。 main函数中构造图书馆类对象,向其中添加3个图书对象,测试其persist和restore方法。(注意,请使用对象序列化方法实现)
import java.util.*;
import java.io.*;
public class LibraryPersistence {
public static void main(String[] args) {
Book b1=new Book("理想国","柏拉图","人民出版社",54156,30);
Book b2=new Book("疯狂JAVA","李刚","电子工业出版社",564154,59.9f);
Book b3=new Book("C Primer Plus","Stephen Prata","人民邮电出版社",15415641,89.00f);
Library library=new Library();
library.addBooks(b1);
library.addBooks(b2);
library.addBooks(b3);
library.persist();
library.restore();
}
}
//构造图书类,包含名称(字符串)、作者(字符串)、出版社(字符串)、版本号(整数)、价格(浮点数)
class Book implements Serializable{
private static final long serialVersionUID = 4326494201236011493L;
private String name;
private String author;
private String publisher;
private int version;
private float price;
public Book(String name, String author, String publisher, int version, float price) {
this.name = name;
this.author = author;
this.publisher = publisher;
this.version = version;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
@Override
public String toString(){
return "名称:"+getName()+" 作者:"+getAuthor()+" 出版社:"+getPublisher()+" 版本号:"+getVersion()+" 价格:"+getPrice();
}
}
//构造图书馆类,其中包含若干图书,用容器存储图书对象,然后定义方法void addBook(Book b)添加图书对象,
// 定义方法void persist(),将所有图书存至本地文件books.dat里,
// 定义方法Book[] restore() 从文件books,dat中读取所有图书,并返回图书列表数组
class Library{
private List<Book> bookList;
private Book[] bookarray;
private int size=10;
public Library(){
bookList=new ArrayList<>();
bookarray=new Book[size];
}
public void addBooks(Book b){
bookList.add(b);
}
public void persist(){
ObjectOutputStream oos=null;
try{
oos= new ObjectOutputStream(new FileOutputStream("books.dat"));
Iterator<Book> it=bookList.iterator();
while (it.hasNext()){
oos.writeObject(it.next());
}
oos.writeObject(null);
oos.flush();
oos.close();
}catch (IOException e){
e.printStackTrace();
}finally {
try{
oos.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
public Book[] restore(){
ObjectInputStream ois=null;
try{
ois=new ObjectInputStream(new FileInputStream("books.dat"));
Book ob=null;
int i=0;
while((ob=(Book)ois.readObject())!=null){
bookarray[i++]=ob;
if(i==size){//扩容
Book []temp=new Book[2*size];
System.arraycopy(bookarray,0,temp,0,bookarray.length);
bookarray=temp;
bookarray[i++]=ob;
}
}
for (int j = 0; j <i ; j++) {
System.out.println(bookarray[j].toString());
}
} catch (FileNotFoundException ex){
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try{
ois.close();
}catch (Exception e){
e.printStackTrace();
}
}
return bookarray;
}
}
arraycopy