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+)?$”,效果相同。
- +- ↩︎