zoukankan      html  css  js  c++  java
  • Java第09次实验(流与文件)

    第一次实验

    0. 字节流与二进制文件

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

    • 二进制文件与文本文件的区别
    • try...catch...finally注意事项

    2.使用try..with...resouces关闭资源

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

    我的代码

    package homework;
    
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    class Student {
           private int id;
           private String name;
           private int age;
           private double grade;    
           public Student(){
               
           }
           public Student(int id, String name, int age, double grade) {
              this.id = id;
              this.setName(name);
              this.setAge(age);
              this.setGrade(grade);
          }
          public int getId() {
              return id;
          }
          public void setId(int id) {
              this.id = id;
          }
          public String getName() {
              return name;
          }
          public void setName(String name) {
              if (name.length()>10){
                  throw new IllegalArgumentException("name's length should <=10 "+name.length());
              }
              this.name = name;
          }
          public int getAge() {
              return age;
          }
          public void setAge(int age) {
              if (age<=0){
                  throw new IllegalArgumentException("age should >0 "+age);
              }
              this.age = age;
          }
          public double getGrade() {
              return grade;
          }
          public void setGrade(double grade) {
              if (grade<0 || grade >100){
                  throw new IllegalArgumentException("grade should be in [0,100] "+grade);
              }
              this.grade = grade;
          }
          @Override
          public String toString() {
              return "Student [id=" + id + ", name=" + name + ", age=" + age + ", grade=" + grade + "]";
          }
          
      }
       public class Main {
              public static void main(String[] args)
              {
                  
                  String fileName="d:\student.data";
                  try(DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName)))
                  {
                      Student[] stu=new Student[3];
                      stu[0]=new Student(1,"zhangsan",19,65.0);
                      stu[1]=new Student(2,"lisi",19,75.0);
                      stu[2]=new Student(3,"wangwu",20,85.0);
                      for(Student stu1:stu) {
                          dos.writeInt(stu1.getId());
                          dos.writeUTF(stu1.getName());
                          dos.writeInt(stu1.getAge());
                          dos.writeDouble(stu1.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(dis!=null) {
                          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 (IOException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
               
                 }
                 
            }
       }
    
    

    我的总结

    二进制文件与文本文件的区别:
    广义上的二进制文件包括文本文件,这里讨论的是狭义上的二进制文件与文本文件的比较:
    1. 能存储的数据类型不同:文本文件只能存储char型字符变量。二进制文件可以存储char/int/short/long/float/……各种变量值。
    2. 每条数据的长度不同:文本文件每条数据通常是固定长度的。以ASCII为例,每条数据(每个字符)都是1个字节。二进制文件每条数据不固定。如short占两个字节,int占四个字节,float占8个字节。
    3. 读取的软件不同:文本文件编辑器就可以读写。比如记事本、NotePad++、Vim等。二进制文件需要特别的解码器。比如bmp文件需要图像查看器,rmvb需要播放器。
    4. 操作系统对换行符('
    ')的处理不同(不重要):文本文件,操作系统会对'
    '进行一些隐式变换,因此文本文件直接跨平台使用会出问题。在Windows下,写入'
    '时,操作系统会隐式的将'
    '转换为"
    ",再写入到文件中;读的时候,会把“
    ”隐式转化为'
    ',再读到变量中。在Linux下,写入'
    '时,操作系统不做隐式变换。
    

    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对象写入文本文件,基础代码见后。注意:缓冲区问题。

    4.使用ObjectInputStream/ObjectOutputStream读写学生对象。

    我的代码

    package homework;
    
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class Main {
              public static void main(String[] args) throws IOException
              {
                  String FileName="D:\TSBrowserDownloads\Students.txt";
                  BufferedReader br = null;
                  try {
                      br = new BufferedReader(new InputStreamReader(new FileInputStream(FileName),"UTF-8"));
                      String line = null;
                      while((line=br.readLine())!=null)
                         System.out.println(line);
                 } finally{
                     if (br!=null){
                         br.close();
                     }
                 }
             }
     
         }
    

    我的总结

    1.在编译过程中总是会出现很多错误,首先是头文件的问题,还有就是一些错误的提示,不知道怎么去改正,这方面学习的不好,通过同学才明白。
    2.还有就是做题中会用到的一些知识点。
    
    

    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进行标注。

    我的代码

     package homework;
    
    public class test {
         @Test
              public void test() {
              String FILENAME = "test.txt";
              long begin = System.currentTimeMillis();
              Scanner scanner=null;
              try {
                  scanner = new Scanner(new File(FILENAME));
                  while(scanner.hasNextLine()){//只是读出每一行,不做任何处理
                     scanner.nextLine();
                 }
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             }finally{
                 scanner.close();
             }
           long end = System.currentTimeMillis();
            System.out.println("last "+(end-begin));
             System.out.println("read using Scanner done");
         }
         @Test
         public void Bufftest() {
             String FILENAME = "test.txt";
             long begin = System.currentTimeMillis();
             BufferedReader br = null;
             try {
                  br = new BufferedReader(new FileReader(new File(FILENAME)));
                 while(br.readLine()!=null){};//只是读出,不进行任何处理
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             } catch (IOException e) {
                e.printStackTrace();
            }finally{
                try {
                     br.close();
                 } catch (IOException e) {
                     e.printStackTrace();           }
            }
            long end = System.currentTimeMillis();
             System.out.println("last "+(end-begin));
             System.out.println("read using BufferedReader done");
         }
    }
    

    我的总结

    总体来说使用Scanner读取文本文件要比用BufferedReader更容易,而且,Scanner具有比BufferedReader更多的方法。
    

    思考题:
    为什么以下代码生成的文件大小是0,而只有当count=16384(两倍的默认缓冲区大小)才可以真正写入到文件?

    String fileName = "d:/Test.data";
    int count = 16383;
    PrintWriter pw = null;
    try {
    pw = new PrintWriter(fileName);

    for (int i = 0; i < count; i++) {
        pw.print(1);
    }
    

    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }finally{
    //pw.close();
    }

    答:

    第二次实验

    3. 字节流之对象流

    结合使用ObjectOutputStream、ObjectInputStream与FileInputStream、FileOuputStream实现对Student对象的读写。
    编写如下两个方法:

    • public static void writeStudent(List stuList)
    • public static List readStudents(String fileName)
      进阶:
      使用wxMEdit打开ObjectOutputStream所生成的文件格式,尝试修改文件,并通过代码读取文件进行验证。

    我的代码

    public static void writeStudent(List<Student> stuList)
     2     {
     3         String fileName="D:\Student.dat";
     4         try (   FileOutputStream fos=new FileOutputStream(fileName);
     5                 ObjectOutputStream ois=new ObjectOutputStream(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 List<Student> readStudents(String fileName)
    19     {
    20         List<Student> stuList=new ArrayList<>();
    21         try (   FileInputStream fis=new FileInputStream(fileName);
    22                 ObjectInputStream ois=new ObjectInputStream(fis))
    23         {
    24             stuList=(List<Student>)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         return stuList;
    37     }   
    

    我的总结

    1.ObjectOutputStream的使用
    - ObjectOutputStream是一个高级流, 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
    2.ObjectInputStream的使用
    - ObjectInputStream也是一个高级流,对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
    3.ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。ObjectOutputStream用于序列化对象,ObjectInputStream 用于恢复那些以前序列化的对象(反序列化)。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。
    

    4. 选做:RandomAccessFile

    像操作数组一样操作文件内容。
    将以上的对大量Student对象的读写使用RandomAceessFile。
    特别考核:你觉得使用RandomAccessFile读写文件与使用字节流、字符流、缓冲流相比较各有何优缺点。

    我的代码

    
    

    我的总结

    
    

    5. 文件操作

    1.编写一个程序,可以根据指定目录和文件名,搜索该目录及子目录下的所有文件,如果没有找到指定文件名,则显示无匹配,否则将所有找到的文件名与文件夹名显示出来。

    编写public static void findFile(Path dir,String fileName)方法.
    以dir指定的路径为根目录,在其目录与子目录下查找所有和filename
    相同的文件名,一旦找到就马上输出到控制台。
    提示:
    1.使用递归或队列。建议使用队列完成。
    2.使用图形界面:

    • GUI下可使用JFileChooser控件实现选取目录。控制台下手动指定目录名。
      参考代码(参考代码 目录中):

    • 一个简单的包括菜单的GUI小程序.rar(包含JFileChooser的用法)

    • FindDirectories.java (用于查找文件)
      进阶(选做):
      自己编写的文件搜索方法基本上有很大缺陷,如不能正确处理符号链接。
      考核点:查询资料,尝试使用Files.walkFileTree方法进行文件搜索。

    我的代码

    if (args.length == 0) args = new String[] { ".." };
           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 the file is again a directory, call the main method recursively             if (f.isDirectory())
                 {
                     if(f.getName().contains(fileName)) {
                         System.out.println(f.getCanonicalPath());
                         main(new String[] { f.getPath() });
                     }          
                 }
              }
           }
           catch (IOException e)
           {
              e.printStackTrace();
           }
    

    我的总结

    1,Files.walkFileTree的原理介绍
    原型:static Path Files.walkFileTree(Path start, FileVisitor<? super Path> visitor);
    ii. 表示从start代表的节点开始遍历文件系统;
    iii. 其中visitor是遍历过程中的行为控制器;
    4) 遍历行为控制器——FileVisitor:
    i. 它是一个接口,里面定义了4个方法用来指定当你访问一个节点之前、之中、之后、失败时应该采取什么行动;
    
    

    6. 正则表达式

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

    • 尝试匹配网页中的数字字符串
    • 尝试匹配网页中的图片字符串
      1、2为一考核点。

    我的代码

    test
            {
               // get URL string from command line or use default
               String urlString;
               if (args.length > 0) urlString = args[0];
              else urlString = "http://cec.jmu.edu.cn";
     
               // open reader for URL
              InputStreamReader in = new InputStreamReader(new URL(urlString).openStream());
         //InputStreamReader in = new InputStreamReader(new FileInputStream("集美大学-计算机工程学院.htm"));
              // read contents into string builder
              StringBuilder input = new StringBuilder();
              int ch;
              while ((ch = in.read()) != -1)
                 input.append((char) ch);
     
              // search for all occurrences of pattern
              String patternString = "<a\s+href\s*=\s*("[^"]*"|[^\s>]*)\s*>";
          String patternImgString = "[+-]?[0-9]+";
         //String patternString = "[u4e00-u9fa5]";     //匹配文档中的所有中文
              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();
           }
    
    

    我的总结

    正则表达式是什么:正则表达式(regular expression)是一个描述字符模式的对象。JavaScript的RegExp类表示正则表达式,String和RegExp都定义了方法。
    
  • 相关阅读:
    根据EsLint配置WebStorm格式化代码风格
    Vue中使用vant-UI实现移动端自定义省市区三级联动
    Vue中使用Element-UI实现表格跨页多选
    Vue中使用iview-UI实现切换Tab页网络请求优化
    Vue中使用iview-UI按需引入Select组件下拉框无法生效问题
    Vue中使用iview-UI表格样式修改和使用自定义模板数据渲染相关
    Vue中使用Element-UI表单验证相关问题及解决
    Vue 3.0 多页面项目之商家平台练习
    五 创建道路模型(2 道路的挖填方量计算及条件部件)
    五 创建道路模型(1 道路三要素)
  • 原文地址:https://www.cnblogs.com/20000519yxn/p/11938975.html
Copyright © 2011-2022 走看看