• Java MOOC-互评作业-流与文件


    0. 字节流与二进制文件

    任务1:使用DataOutputStream与FileOutputStream将Student对象写入二进制文件student.data
    

    我的代码

    public class Main {
        public static void main(String[] args)
        {
            String fileName="e://student.data";
            int length=3;
            Student[] students=new Student[length];
            students[0]=new Student(1,"张三",19,65);
            students[1]=new Student(2,"李四",19,75);
            students[2]=new Student(3,"王五",20,85);
            Student stu1=new Student();
            try(DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName)))
            {
            	for (int i = 0; i < length; i++) {
    				dos.writeInt(students[i].getId());
    				dos.writeUTF(students[i].getName());
    				dos.writeInt(students[i].getAge());
    				dos.writeDouble(students[i].getGrade());
    			}
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try(DataInputStream dis=new DataInputStream(new FileInputStream(fileName)))
            {
            	while(true) {
            		int id=dis.readInt();
                    String name=dis.readUTF();
                    int age=dis.readInt();
                    double grade=dis.readDouble();
                    Student stu=new Student(id,name,age,grade);
                    System.out.println(stu);
            	}
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block  
                e.printStackTrace();
            } catch(EOFException e) {
            	//已经从流中读完
            }catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }
    

    我的总结


    Q1:	二进制文件与文本文件的区别
    A1:	这两者只是在编码层次上有差异。文本文件编码基于字符定长,译码容易些;二进制文件编码是变长的,所以它灵活,存储利用率要高些,译码难一些
    Q2:	try...catch...finally注意事项
    A2:	捕获多个异常时,如有多个catch块并有继承关系的情况下必须先写子类后写父类(即先捕获小异常再捕获大异常),若写反在编译时就会报错使用。以及执行顺序,先执行try如果未发生异常,继续执行最后执行finally,否者跳过try执行catch最后执行finally.
    Q3:	try..with...resouces关闭资源
    A3:	在Java7中增强了try语句的功能,它允许在try关键字后紧跟一对圆括号,圆括号可以声明、初始化一个或多个资源,此处的资源指的是那些必须在程序结束时显示关闭的资源,try语句在该语句结束时自动关闭这些资源。这些资源实现类必须实现AutoCloseable或Closeable接口,实现这两个接口就必须实现close()方法。
    

    任务2:使用DataInputStream与FileInputStream从student.data中读取学生信息并组装成对象
    

    我的代码

            try(DataInputStream dis=new DataInputStream(new FileInputStream(fileName)))
            {
            	while(true) {
            		int id=dis.readInt();
                    String name=dis.readUTF();
                    int age=dis.readInt();
                    double grade=dis.readDouble();
                    Student stu=new Student(id,name,age,grade);
                    System.out.println(stu);
            	}
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block  
                e.printStackTrace();
            } catch(EOFException e) {
            	//已经从流中读完
            }catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    

    1. 字符流与文本文件:使用 PrintWriter(写),BufferedReader(读)

    任务
    1.	使用BufferedReader从编码为UTF-8的文本文件中读出学生信息,并组装成对象然后输出。
    •	中文乱码问题(FileReader使用系统默认编码方式读取文件,会产生乱码,可使用InputStreamReader解决)
    •	String的split方法使用\s+可以使用多个空格作为分隔符。
    •	进阶:修改Students.txt文件,在正确的数据行中间增加一些错误行(如,每行只有3个数据,或者应该是数字的地方放入其他字符),修改自己的程序,让起可以处理出错的行(报错但可以继续运                    行)。
    2.	编写public static ListreadStudents(String fileName);从fileName指定的文本文件中读取所有学生,并将其放入到一个List中
    3.	使用PrintWriter将Student对象写入文本文件,基础代码见后。注意:缓冲区问题。
    

    任务123我的代码

    package iostream;
    
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.io.UnsupportedEncodingException;
    import java.util.ArrayList;
    import java.util.List;
    
    public class PrintRead {
    
    	public static void main(String[] args) {
    		String fileName = "e:/Students.txt";
    		String inFileName = "e:/inStudents.txt";
    		System.out.println(PrintRead.readStudents(fileName));
    		try (PrintWriter pw = new PrintWriter(inFileName)) {
    			pw.print("张三 ");
    			pw.print(" 201821123333");
    		} catch (FileNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    	public static List<Student> readStudents(String fileName) {
    		List<Student> studentList = new ArrayList<>();
    		try (FileInputStream fis = new FileInputStream(fileName);
    				InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
    				BufferedReader br = new BufferedReader(isr);) {
    			String line = null;
    			while ((line = br.readLine()) != null) {
    				String[] student = line.split("\s+");// split方法\s+多个空格作为分隔符
    				int id = Integer.parseInt(student[0]);
    				String name = student[1];
    				int age = Integer.parseInt(student[2]);
    				double grade = Double.parseDouble(student[3]);
    				Student stu = new Student(id, name, age, grade);
    				studentList.add(stu);
    			}
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return studentList;
    
    	}
    
    }
    
    任务4:使用ObjectInputStream/ObjectOutputStream读写学生对象。
    

    我的代码

    try(
    		FileOutputStream fos=new FileOutputStream(fileName);
    	    ObjectOutputStream oos=new ObjectOutputStream(fos)
    	)
    	{
    	    Student ts=new Student(1,"张三",19,65);
    	    oos.writeObject(ts);
    	}
    	catch (Exception e) {
    	    // TODO Auto-generated catch block
    	    e.printStackTrace();
    	}
    	try(
    	    FileInputStream fis=new FileInputStream(fileName);
    	    ObjectInputStream ois=new ObjectInputStream(fis))
    	{
    	    Student newStudent =(Student)ois.readObject();
    	    System.out.println(newStudent);
    	} catch (IOException e) {
    	    // TODO Auto-generated catch block
    	    e.printStackTrace();
    	} catch (ClassNotFoundException e) {
    	    // TODO Auto-generated catch block
    	    e.printStackTrace();
    	}
    

    我的总结

    Q1:中文乱码问题
    A1:FileReader使用系统默认编码方式读取文件,会产生乱码,可使用InputStreamReader解决,在创建时可以设置编码格式比如GBK,UTF-8
    Q2:写入文件后,打开为空白文件
    A2:文件写入存在缓冲区,先将数据写入缓冲区,效率高,但是如果没有强制将缓冲区内容写入,或者缓冲区未满,或者正常关闭流,并不会真正写入文件,可以使用writer.flush();writer.close()写入文件
    

    2. 缓冲流(结合使用JUint进行测试)

    任务:使用PrintWriter往文件里写入1千万行随机整数,范围在[0,10]。随机数种子设置为100.
    然后从文件将每行读取出来转换成整数后相加。然后依次输出“个数 和 平均值(保留5位小数)”。
    

    我的代码

    package iostream;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Random;
    import java.util.Scanner;
    
    
    public class BufferedScanner {
    
    	/**
    	 * @param args
    	 * @throws Exception 
    	 */
    	public static void main(String[] args)  {
    		String FILENAME = "e:\test.txt";
    		
    		//write using PrintWriter
    		try (PrintWriter pw = new PrintWriter(FILENAME)){
                Random random=new Random(100);
                for (int i = 0; i < 1000_0000; i++) {
                    int r=random.nextInt(11);
                    pw.println(r);
                }
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		}
    		
    		
    		System.out.println("write  using PrintWriter done");
    		
    		
    	}
    
    }
    
    class Test {
    	String FILENAME = "e:\test.txt";
    	
    	@org.junit.jupiter.api.Test
    	void testBuffered() {
    		//read using BufferedReader
    		int sum=0;
    		int count=0;
    		try (BufferedReader br = new BufferedReader(new FileReader(new File(FILENAME)))){
    			String str;
    			int r;
    			while((str=br.readLine())!=null){
    				r=Integer.parseInt(str);
    				sum+=r;
    				count++;
    			};
    			
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		System.out.format("%d %d %.5f", count,sum,1.0*sum/count);
    		System.out.println("read using BufferedReader done");
    	}
    	@org.junit.jupiter.api.Test
    	void testScanner() {
    		//read using Scanner
    		int sum=0;
    		int count=0;
    		int r;
    		try (Scanner scanner=new Scanner(new File(FILENAME))){
    			String str;
    			while(scanner.hasNextLine()){
    				str=scanner.nextLine();
    				r=Integer.parseInt(str);
    				sum+=r;
    				count++;
    			}
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		}
    		System.out.format("%d %d %.5f", count,sum,1.0*sum/count);
    		System.out.println("read using Scanner done");
    		
    
    	}
    }
    

    我的总结

    Q1:使用junit对比BufferedReader与Scanner读文件的效率
    A1:显而易见用BufferedReader更快,因为BufferedReader采用缓存方式可以有效减少I/O操作次数,进而节省时间
    Q2:Scanner的hasNextXXX方法应与相对应的nextXXX方法配合使用,否则容易出错。
    Q3:为什么读取出文件后数据量从1000_0000减少的一半变成了500_0000。
    A3:因为在while循环中如果采用br.readLine()!=null,文件会指向下一位,如果这时候再在循环直调用readLine,会跳行读取所以减少一半,应该while中写成(str=br.readLine())!=null
    

    3. 字节流之对象流

    任务:结合使用ObjectOutputStream、ObjectInputStream与FileInputStream、FileOuputStream实现对Student对象的读写。
    编写如下两个方法:
    •	public static void writeStudent(List stuList)
    •	public static List readStudents(String fileName)
    

    我的代码

    public class PrintRead {
    
    	public static void main(String[] args) {
    		String fileName = "e:/Students.txt";
    		List<Student> stuList=new ArrayList<>();
    		stuList.add(new Student(1,"张三",19,65));
    		stuList.add(new Student(2,"李四",19,75));
    		stuList.add(new Student(3,"王五",20,85));
    		PrintRead.writeStudent(stuList);
    		System.out.println(PrintRead.readStudents(fileName));
    	}
    
    	public static void writeStudent(List<Student> stuList) {
    		String fileName = "e:/Students.txt";
    		try (FileOutputStream fos = new FileOutputStream(fileName);
    				ObjectOutputStream ois = new ObjectOutputStream(fos)) {
    			ois.writeObject(stuList);
    
    		} catch (FileNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
    	}
    
    	public static List<Student> readStudents(String fileName) {
    		List<Student> stuList = new ArrayList<>();
    		try (FileInputStream fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis)) {
    			stuList = (List<Student>) ois.readObject();
    		} catch (FileNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		} catch (ClassNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return stuList;
    	}
    }
    

    我的总结

    Q1:java.io.NotSerializableException: iostream.Student出现异常
    A1:要将对象写入文件,必须实现序列化接口,对象---->流数据    序列化流 (ObjectOutputStream)
    •	(1)必须序列化之后才可以反序列化
    •	(2)自定义类要实现序列化功能,必须实现接口Serializable(标记接口),如果没有实现就会报这个错误NotSerializableException。
    

    5. 文件操作

    任务:编写一个程序,可以根据指定目录和文件名,搜索该目录及子目录下的所有文件,如果没有找到指定文件名,则显示无匹配,否则将所有找到的文件名与文件夹名显示出来。
    1.	编写public static void findFile(Path dir,String fileName)方法.
    以dir指定的路径为根目录,在其目录与子目录下查找所有和filename相同的文件名,一旦找到就马上输出到控制台。
    

    我的代码

    public class FindDirectories {
    	public static void main(String[] args) {
    		// if no arguments provided, start at the parent directory
    		String fileName = "test.txt";
    		if (args.length == 0)
    			args = new String[] { "E:\算法程序设计" };
    
    		try {
    			File pathName = new File(args[0]);
    			String[] fileNames = pathName.list();
    
    			// enumerate all files in the directory
    			for (int i = 0; i < fileNames.length; i++) {
    				File f = new File(pathName.getPath(), fileNames[i]);
    
    				if (f.isFile()) {
    	                if(f.getName().equals(fileName))
    	                {
    	                    System.out.println(f.getAbsolutePath());
    	                    flag=true;
    	                }
    				}
    				// if the file is again a directory, call the main method recursively
    				else if (f.isDirectory()) {
    					if (f.getName().equals(fileName))
    					{
    						System.out.println(f.getCanonicalPath());
    						flag=true;
    					}
    					
    					main(new String[] { f.getPath() });//递归
    				}
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    我的总结

    实现方法主要时通过递归,通过if语句判断当前文件是单个文件或者存在子文件,然后如果存在子文件则递归再次调用,在其子目录下查找所有和filename相同的文件名,一旦找到就马上输出到控制台。
    

    6. 正则表达式

    1.	如何判断一个给定的字符串是否是10进制数字格式?尝试编程进行验证。
    2.	修改HrefMatch.java
    •	尝试匹配网页中的数字字符串
    •	尝试匹配网页中的图片字符串
    

    我的代码

    public class HrefMatch
    {
       public static void main(String[] args)
       {
          try
          {
             // get URL string from command line or use default
            /* String urlString;
             if (args.length > 0) urlString = args[0];
             else urlString = "http://java.sun.com";*/
             String fileName="e:\集美大学-计算机工程学院.htm";
             // open reader for URL
            //InputStreamReader in = new InputStreamReader(new URL(urlString).openStream());
             InputStreamReader in = new InputStreamReader(new FileInputStream(fileName));
             // read contents into string builder
             StringBuilder input = new StringBuilder();
             int ch;
             while ((ch = in.read()) != -1)
                input.append((char) ch);
    
             String patternString = "[+-]?[0-9]+(\.\d+)?";
             Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
             Matcher matcher = pattern.matcher(input);
    
             while (matcher.find())
             {
                int start = matcher.start();
                int end = matcher.end();
                String match = input.substring(start, end);
                System.out.println(match);
             }
          }
          catch (IOException e)
          {
             e.printStackTrace();
          }
          catch (PatternSyntaxException e)
          {
             e.printStackTrace();
          }
       }
    }
    
  • 相关阅读:
    Atitit.获得向上向下左的右的邻居的方法 软键盘的设计..
    Atitit.css 规范 bem 项目中 CSS 的组织和管理
    Atitit.css 规范 bem  项目中 CSS 的组织和管理
    Atitit.android js 的键盘按键检测Back键Home键和Menu键事件
    Atitit.android js 的键盘按键检测Back键Home键和Menu键事件
    Atitit.java相比c#.net的优点 优缺点  v2 q330
    Atitit.java相比c#.net的优点 优缺点  v2 q330
    Atitit.android  jsbridge v1新特性
    Atitit.android  jsbridge v1新特性
    Atitit. Toast alert loading js控件   atiToast v2新特性
  • 原文地址:https://www.cnblogs.com/zwtcyt/p/11938909.html
Copyright © 2020-2023  润新知