Java流与文件作业

0. 字节流与二进制文件

我的代码

package Test;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestStu {

	public static void main(String[] args) {
		Student stus[] = new Student[3];
		stus[0] = new Student(1, "张三", 19, 65);
		stus[1] = new Student(2, "李四", 19, 75);
		stus[2] = new Student(3, "王五", 20, 85);
		try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("d:\\student.data"))) {
			for (int i = 0; i < stus.length; i++) {
				dos.writeInt(stus[i].getId());
				dos.writeUTF(stus[i].getName());
				dos.writeInt(stus[i].getAge());
				dos.writeDouble(stus[i].getGrade());
			}
		} catch (IOException e) {
			e.printStackTrace();

		}
		try (DataInputStream dis = new DataInputStream(new FileInputStream("d:\\student.data"))) {
			int id = dis.readInt();
			String name = dis.readUTF();
			int age = dis.readInt();
			double grade = dis.readDouble();
			Student stutest = new Student(id, name, age, grade);
			for (int i = 0; i < stus.length; i++)
				System.out.println(stus[i].toString());
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

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;
	}

	public String toString() {
		return getClass().getName() + "[id=" + id + ",name=" + name + ",grade=" + grade + "]";
	}
}

我的总结

1.二进制文件与文本文件的区别:
文本文件只能存储char型字符变量。二进制文件可以存储char/int/short/long/float/……各种变量值。但文本文件编辑器就可以读写。比如记事本、NotePad++、Vim等。二进制文件需要特别的解码器。
2.try...catch...finally注意事项:
如果有一个catch{}语句匹配上,其他catch{}分支就不会执行了,所以catch多个异常时要注意异常写的先后顺序,总体来说父类的异常要放在越后面。在finally{}里面出现异常, 会覆盖try{}里面的异常,导致try{}里面的异常无法被捕捉到,还会导致finally{}异常后面的代码不会被执行。
3.用try..with...resouces关闭资源:
使用 try-with-resources 语句简化了finally块中的异常处理,数据流 会在 try 执行完毕后自动被关闭,前提是,这些可关闭的资源必须实现 java.lang.AutoCloseable 接口。

1.字符流与文本文件:

我的代码

public static List<Student> readStudents(String fileName){
	List<Student> studentList = new ArrayList<>();
	String fileName="d:\\student.txt";
	        try(
	            FileInputStream fis=new FileInputStream(fileName);
	            InputStreamReader dos=new InputStreamReader(fis, "UTF-8");
	            BufferedReader br=new BufferedReader(dos))
	        {
	            String line=null;
	            while((line=br.readLine())!=null)
	            {
	                String[] track=line.split("\\s+");
	                int id=Integer.parseInt(track[0]);
	                String name=track[1];
	                int age=Integer.parseInt(track[2]);
	                double grade=Double.parseDouble(track[3]);
	                Student stu=new Student(id,name,age,grade);
	                studentList.add(stu);
	            }
	        } 
	        catch (FileNotFoundException e)
	        {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        } 
	        catch (IOException e) 
	        {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        }
	        System.out.println(studentList);
	        return studentList;
	        
}

我的总结

1.FileReader在读取文件的时候采取的是系统默认的编码格式, 系统默认编码格式为GBK与windows 文本文件默认编码格式不一致,所以必然会出现乱码. 想要指定自己的编码格式读取文件,那就在FileInputStream外面嵌套InputStream 来代替FileReader,之后指定编码格式即可. 读取文件用下面的代码: InputStreamReader inputStreamReader = new InputStreamReader( new FileInputStream(path),"UTF-8");
2.指定的编码格式要与文本的编码格式一致,否则还是会出现乱码,通过文件另存为指定一下编码格式即可

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

我的代码

TestReader部分

package Test;
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 TestReader {

		public static void main(String[] args) {
			String fileName = "d:/Test.data";
			PrintWriter pw = null;
			try {
				pw = new PrintWriter(fileName);
				Random random=new Random();
	            random.setSeed(100);
	            double sum=0,aver;
	            for (int i = 0; i < 1000_0000; i++) {
	                int r=random.nextInt(10);
	                sum+=r;
	                pw.println(r);
	            }
	            aver=sum/1000_0000;
	            System.out.format("%.5f", aver);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				pw.close();
			}
		}

	}

JUNIT部分

package Test;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
class TestFileReader {
	@Test
	void testScanner() {
		Scanner scanner = null;
		String fileName = "d:/Test.data";
		try {
			scanner = new Scanner(new File(fileName));
			while (scanner.hasNextLine()) {
				scanner.nextLine();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		System.out.println("read using Scanner done");
	}

	@Test
	void testBufferedReader() {
		BufferedReader br = null;
		String fileName = "d:/Test.data";
		try {
			br = new BufferedReader(new FileReader(new File(fileName)));
			while (br.readLine() != null) {
			}
			;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
		System.out.println("read using BufferedReader done");
	}

}

我的总结

1.JUNIT中要测试的方法前要加上@Test,才会出现小图标后面跟上时间
2.Java的随机数相关:相同种子数的Random对象,相同次数生成的随机数字是完全相同的;Random类中各方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的几率均等;

3.字节流之对象流

我的代码

public static void writeStudent(List<Student> stuList)
    {
        String fileName="d:\\student.data";
        try (   FileOutputStream fos=new FileOutputStream(fileName);
                ObjectOutputStream oos=new ObjectOutputStream(fis))
        {
            oos.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;
}   

我的总结

1.使用对象流读取数据时,不是之前Scanner等一行一行的读取,而是读入整个对象,可能是以集合或者数组的形式读入
2.当使用对象流写入或者读取对象的时候,必须保证该对象是序列化的,这样是为了保证对象能够正确的写入文件,并能够把对象正确的读回程序。

5.文件操作

我的代码

package Test;

import java.io.*;
import java.nio.file.*;

public class Main {
	// TODO Auto-generated method stub
    Path dir=Paths.get("d:\\", "testStream","36");
    findFile(dir,"test.txt");
}
public static void findFile(Path dir,String fileName)
{
    File file=dir.toFile();
    File[] files=file.listFiles();
    for(File txt:files)
    {
        if(txt.isFile())
        {
            if(txt.getName().equals(fileName))
            {
                System.out.println(txt.getAbsolutePath());
                return;
            }
        }
        else if(txt.isDirectory())
        {
            findFile(txt.toPath(),fileName);
        }
    }
}
}

我的总结

(1)采用递归形式完成,还能利用队列进行搜索
(2)Paths类获取文件或文件目录路径可以使用采用多个字符串形式,也可以使用Path.get(D:\ReviewIO\URL)这种形式。返回的Path对象完全可以代替File类用于文件IO操作。
(3)File类的方法参数很多,要使用泛型为字符类型的集合类作为数据写入指定文件中。

6.正则表达式

我的代码

(1)判断一个给定的字符串是否是10进制数字格式

package Test;

import java.util.*;
import java.util.regex.*;

public class Main {
	public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Pattern pattern=Pattern.compile("^[+-]?[0-9]+(\\.\\d+)?");
        Matcher matcher=null;
        while(sc.hasNext())
        {
            String testStr=sc.next();
            matcher=pattern.matcher(testStr);
            System.out.println(matcher.matches());
        }
        sc.close();
    }
}

我的总结

1.详细了解正则表达式的使用方法,能够灵活运用,代码中使用的“[1]?[0-9]+(\.\d+)?”花费了一段时间才写出来
2.Pattern类用于创建一个正则表达式,也可以说是创建一个匹配模式;Pattern类中的matcher(CharSequence input)会返回一个Matcher对象,Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持。
3.要想得到更丰富的正则匹配操作,那就需要将Pattern与Matcher联合使用。

(2)匹配网页中的数字字符串

package Test;

import java.io.*;
import java.net.*;
import java.util.regex.*;

/**
 * This program displays all URLs in a web page by matching a regular expression
 * that describes the <a href=...> HTML tag. Start the program as <br>
 * java HrefMatch URL
 * 
 * @version 1.01 2004-06-04
 * @author Cay Horstmann
 */
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 = "https://pintia.cn";
			 */
			String fileName = "D:\\test\\集美大学-计算机工程学院.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);

			// 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();
		}
	}
}

我的总结

1.出现了fileName (系统找不到指定的文件。)的异常,百度搜索后发现要在父目录下建立子目录,再将指定文件加入子目录,就能成功找到。
2.除了使用“-?[0-9]+”这个正则表达式来匹配数字字符串,还可以使用“-?\d+(\.\d+)?$”,效果相同。


  1. +- ↩︎

posted @ 2019-11-26 19:28  zio  阅读(242)  评论(0编辑  收藏  举报