0. 字节流与二进制文件
使用DataOutputStream与FileOutputStream将Student对象写入二进制文件student.data
二进制文件与文本文件的区别
try...catch...finally注意事项
使用try..with...resouces关闭资源
使用DataInputStream与FileInputStream从student.data中读取学生信息并组装成对象
我的代码
1 classStudent {2 private intid;3 privateString name;4 private intage;5 private doublegrade;6 publicStudent(){7
8 }9 public Student(int id, String name, int age, doublegrade) {10 this.id =id;11 this.setName(name);12 this.setAge(age);13 this.setGrade(grade);14 }15 public intgetId() {16 returnid;17 }18 public void setId(intid) {19 this.id =id;20 }21 publicString getName() {22 returnname;23 }24 public voidsetName(String name) {25 if (name.length()>10){26 throw new IllegalArgumentException("name's length should <=10 "+name.length());27 }28 this.name =name;29 }30 public intgetAge() {31 returnage;32 }33 public void setAge(intage) {34 if (age<=0){35 throw new IllegalArgumentException("age should >0 "+age);36 }37 this.age =age;38 }39 public doublegetGrade() {40 returngrade;41 }42 public void setGrade(doublegrade) {43 if (grade<0 || grade >100){44 throw new IllegalArgumentException("grade should be in [0,100] "+grade);45 }46 this.grade =grade;47 }48 @Override49 publicString toString() {50 return "Student [id=" + id + ", name=" + name + ", age=" + age + ", grade=" + grade + "]";51 }52
53 }54 public classMain {55 public static voidmain(String[] args)56 {57
58 String fileName="d:\\student.data";59 try(DataOutputStream dos=new DataOutputStream(newFileOutputStream(fileName)))60 {61 Student[] stu=new Student[3];62 stu[0]=new Student(1,"zhangsan",19,65.0);63 stu[1]=new Student(2,"lisi",19,75.0);64 stu[2]=new Student(3,"wangwu",20,85.0);65 for(Student stu1:stu) {66 dos.writeInt(stu1.getId());67 dos.writeUTF(stu1.getName());68 dos.writeInt(stu1.getAge());69 dos.writeDouble(stu1.getGrade());70 }71
72 } catch(FileNotFoundException e) {73 //TODO Auto-generated catch block
74 e.printStackTrace();75 System.out.println("1");76 } catch(IOException e) {77 //TODO Auto-generated catch block
78 e.printStackTrace();79 System.out.println("2");80 }81 try(DataInputStream dis=new DataInputStream(newFileInputStream(fileName)))82 {83 while(dis!=null) {84 int id=dis.readInt();85 String name=dis.readUTF();86 int age=dis.readInt();87 double grade=dis.readDouble();88 Student stu=newStudent(id,name,age,grade);89 System.out.println(stu);90 }91
92
93 } catch(FileNotFoundException e) {94 //TODO Auto-generated catch block
95 e.printStackTrace();96 System.out.println("3");97 } catch(IOException e) {98 //TODO Auto-generated catch block
99 e.printStackTrace();100 System.out.println("4");101 }102
103 }
我的总结
在读取文件数据时while循环会报错,加入测试点后发现while循环多读了一次,
后将while(dis!=null)改成while(dis.available()!=0),问题解决
1. 字符流与文本文件:使用 PrintWriter(写),BufferedReader(读)
任务:
使用BufferedReader从编码为UTF-8的文本文件中读出学生信息,并组装成对象然后输出。
中文乱码问题(FileReader使用系统默认编码方式读取文件,会产生乱码,可使用InputStreamReader解决)
String的split方法使用\\s+可以使用多个空格作为分隔符。
进阶:修改Students.txt文件,在正确的数据行中间增加一些错误行(如,每行只有3个数据,或者应该是数字的地方放入其他字符),修改自己的程序,让起可以处理出错的行(报错但可以继续运行)。
编写public static ListreadStudents(String fileName);从fileName指定的文本文件中读取所有学生,并将其放入到一个List中
使用PrintWriter将Student对象写入文本文件,基础代码见后。注意:缓冲区问题。
使用ObjectInputStream/ObjectOutputStream读写学生对象。
我的代码
1.
1 public classMain {2 public static void main(String[] args) throwsIOException3 {4 String FileName="D:\\TSBrowserDownloads\\Students.txt";5 BufferedReader br = null;6 try{7 br = new BufferedReader(new InputStreamReader(new FileInputStream(FileName),"UTF-8"));8 String line = null;9 while((line=br.readLine())!=null)10 System.out.println(line);11 } finally{12 if (br!=null){13 br.close();14 }15 }16 }17
18 }
我的总结
默认方法打开读取会产生乱码
将模式读取方式改成"UTF-8"后显示正常
2.
1 public static voidListreadStudents(String fileName){2 ArrayList StudentList=new ArrayList();3 BufferedReader br = null;4 try{5 br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName),"UTF-8"));6 while(br!=null) {7 String line=br.readLine();8 String[] stu=line.split("\\s+");9 int id=Integer.parseInt(stu[0]);10 String name=stu[1];11 int age=Integer.parseInt(stu[2]);12 double grade=Double.parseDouble(stu[3]);13 Student Stu=newStudent(id,name,age,grade);14 StudentList.add(Stu);15 }16 } finally{17 if (br!=null){18 br.close();19 }20 }21 }
实验调试
刚开始本来想用和DataInputStream一样直接读,发现BufferedReader只用read和ReadLine方法,得用实验提到的"\\s+"的方法将读到的一整行用分隔符来分开,再用类型转换来读。
3.
2 String FileName="D:\\TSBrowserDownloads\\Students.txt";3 PrintWriter pw=new PrintWriter(new OutputStreamWriter(new FileOutputStream(FileName,true),"UTF-8"));4 pw.print("4 陈六 21 93");5 pw.close();
我的总结
正确写入文件
4.
1 String FileName="D:\\TSBrowserDownloads\\student.dat";2 try(3 FileOutputStream fos=newFileOutputStream(FileName);4 ObjectOutputStream oos=newObjectOutputStream(fos))5 {6 Student ts=new Student(5,"asd",14,60);7 oos.writeObject(ts);8 }9 catch(Exception e) {10 //TODO Auto-generated catch block
11 e.printStackTrace();12 }13 try(14 FileInputStream fis=newFileInputStream(FileName);15 ObjectInputStream ois=newObjectInputStream(fis))16 {17 Student newStudent =(Student)ois.readObject();18 System.out.println(newStudent);19 } catch(IOException e) {20 //TODO Auto-generated catch block
21 e.printStackTrace();22 } catch(ClassNotFoundException e) {23 //TODO Auto-generated catch block
24 e.printStackTrace();25 }
2. 缓冲流(结合使用JUint进行测试)
使用PrintWriter往文件里写入1千万行随机整数,范围在[0,10]。随机数种子设置为100.
然后从文件将每行读取出来转换成整数后相加。然后依次输出“个数 和 平均值(保留5位小数)”。
对比使用BufferedReader与使用Scanner从该文件中读取数据(只读取,不输出),使用哪种方法快?
使用junit对比BufferedReader与Scanner读文件的效率
格式化输出:System.out.format。
要使用Scanner的hasNextXXX方法来判断是否到文件尾,否则会抛异常。
Scanner的asNextXXX方法应与相对应的nextXXX方法配合使用,否则容易出。
请删除fail("Not yet implemented");;并且在需要测试的方法上使用@Test进行标注。
写入文件代码
1 String FILENAME = "test.txt";2 double sum=0,aver;3 PrintWriter pw=null;4 try{5 pw = newPrintWriter(FILENAME);6 for(int i = 0;i<10000000;i++){//写入1千万行
7 int r=new Random().nextInt(10);8 sum+=r;9 pw.println(r);10 //System.out.println(r);
11 }12 } catch(FileNotFoundException e) {13 e.printStackTrace();14 }finally{15 pw.close();16 }17 aver=sum/10000000;18 System.out.format("%.5f", aver);19 }
使用JUint的代码
1 public classtest {2 @Test3 public voidtest() {4 String FILENAME = "test.txt";5 long begin =System.currentTimeMillis();6 Scanner scanner=null;7 try{8 scanner = new Scanner(newFile(FILENAME));9 while(scanner.hasNextLine()){//只是读出每一行,不做任何处理
10 scanner.nextLine();11 }12 } catch(FileNotFoundException e) {13 e.printStackTrace();14 }finally{15 scanner.close();16 }17 long end =System.currentTimeMillis();18 System.out.println("last "+(end-begin));19 System.out.println("read using Scanner done");20 }21 @Test22 public voidBufftest() {23 String FILENAME = "test.txt";24 long begin =System.currentTimeMillis();25 BufferedReader br = null;26 try{27 br = new BufferedReader(new FileReader(newFile(FILENAME)));28 while(br.readLine()!=null){};//只是读出,不进行任何处理
29 } catch(FileNotFoundException e) {30 e.printStackTrace();31 } catch(IOException e) {32 e.printStackTrace();33 }finally{34 try{35 br.close();36 } catch(IOException e) {37 e.printStackTrace();38 }39 }40 long end =System.currentTimeMillis();41 System.out.println("last "+(end-begin));42 System.out.println("read using BufferedReader done");43 }44 }
我的总结
可以明显对比出缓冲流BufferedReader的方法要比Scanner的方法快很多
不使用JUint也可以在循环开始前后定义时间变量,最后相减也能得到运行所用时间
第2次实验
3. 字节流之对象流
结合使用ObjectOutputStream、ObjectInputStream与FileInputStream、FileOuputStream实现对Student对象的读写。
编写如下两个方法:
public static void writeStudent(List stuList)
public static List readStudents(String fileName)
我的代码
1 public static void writeStudent(ListstuList)2 {3 String fileName="D:\\Student.dat";4 try ( FileOutputStream fos=newFileOutputStream(fileName);5 ObjectOutputStream ois=newObjectOutputStream(fos))6 {7 ois.writeObject(stuList);8
9 }10 catch(FileNotFoundException e) {11 //TODO Auto-generated catch block
12 e.printStackTrace();13 } catch(IOException e1) {14 //TODO Auto-generated catch block
15 e1.printStackTrace();16 }17 }18 public static ListreadStudents(String fileName)19 {20 List stuList=new ArrayList<>();21 try ( FileInputStream fis=newFileInputStream(fileName);22 ObjectInputStream ois=newObjectInputStream(fis))23 {24 stuList=(List)ois.readObject();25 }26 catch(FileNotFoundException e) {27 //TODO Auto-generated catch block
28 e.printStackTrace();29 } catch(IOException e1) {30 //TODO Auto-generated catch block
31 e1.printStackTrace();32 } catch(ClassNotFoundException e) {33 //TODO Auto-generated catch block
34 e.printStackTrace();35 }36 returnstuList;37 }
5. 文件操作
编写一个程序,可以根据指定目录和文件名,搜索该目录及子目录下的所有文件,如果没有找到指定文件名,则显示无匹配,否则将所有找到的文件名与文件夹名显示出来。
编写public static void findFile(Path dir,String fileName)方法.
以dir指定的路径为根目录,在其目录与子目录下查找所有和filename
相同的文件名,一旦找到就马上输出到控制台。
我的代码
1 if (args.length == 0) args = new String[] { ".."};2 try
3 {4 File pathName = new File(args[0]);5 String[] fileNames =pathName.list();6
7 //enumerate all files in the directory
8 for (int i = 0; i < fileNames.length; i++)9 {10 File f = newFile(pathName.getPath(), fileNames[i]);11
12 //if the file is again a directory, call the main method recursively
13 if(f.isDirectory())14 {15 if(f.getName().contains(fileName)) {16 System.out.println(f.getCanonicalPath());17 main(newString[] { f.getPath() });18 }19 }20 }21 }22 catch(IOException e)23 {24 e.printStackTrace();25 }
我的总结
用了参考代码稍加修改,若文件名字包含fileName,则输出该文件的路径
6. 正则表达式
如何判断一个给定的字符串是否是10进制数字格式?尝试编程进行验证。
修改HrefMatch.java
尝试匹配网页中的数字字符串
尝试匹配网页中的图片字符串
1.
1 Scanner sc=newScanner(System.in);2 Pattern pattern=Pattern.compile("^-?[0-9]\\d*(\\.\\d+)?$");3 Matcher matcher=null;4 while(sc.hasNext())5 {6 String str=sc.next();7 matcher=pattern.matcher(str);8 System.out.println(matcher.matches());9 }10 sc.close();
2.
1 try
2 {3 //get URL string from command line or use default
4 String urlString;5 if (args.length > 0) urlString = args[0];6 else urlString = "http://cec.jmu.edu.cn";7
8 //open reader for URL
9 InputStreamReader in = new InputStreamReader(newURL(urlString).openStream());10 //InputStreamReader in = new InputStreamReader(new FileInputStream("集美大学-计算机工程学院.htm"));11 //read contents into string builder
12 StringBuilder input = newStringBuilder();13 intch;14 while ((ch = in.read()) != -1)15 input.append((char) ch);16
17 //search for all occurrences of pattern
18 String patternString = "]*)\\s*>";19 String patternImgString = "[+-]?[0-9]+";20 //String patternString = "[\u4e00-\u9fa5]";//匹配文档中的所有中文
21 Pattern pattern =Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);22 Matcher matcher =pattern.matcher(input);23
24 while(matcher.find())25 {26 int start =matcher.start();27 int end =matcher.end();28 String match =input.substring(start, end);29 System.out.println(match);30 }31 }32 catch(IOException e)33 {34 e.printStackTrace();35 }36 catch(PatternSyntaxException e)37 {38 e.printStackTrace();39 }
总结:这次实验内容较多,花费了大量的时间,总的来说IO流是java中很重要的一部分,涉及面很广,还会和今后的网络编程牵扯关系,应该好好学。正值表达式的内容较难理解