千锋教育-2020年最新版 Java基础-IO框架
Source
流的分类 按方向【重点】
输入流 :将存储设备
中的内容读入到内存
中。
输出流 :将内存
中的内容写入到存储设备
中。
按单位
字节流 :以字节为单位,可以读写所有数据。
字符流 :以字符为单位,只能读写文本数据。
按功能
字节流 :具有实际传输数据的读写功能。
过滤流 :在节点流的基础之上增强功能。
字节流
字节流的父类(抽象类)
InputStream 字节输入流
public int read(){}
public int read(byte[] b){}
public int read(byte[] b,int off,int len){}
OutputStream 字节输出流
public void write(int n){}
public void write(byte[] b){}
public void write(byte[] b,int off,int len){}
字节流的子类 文件字节流
FileInputStream
public int read()
//从输入流中读取一个字节数据,返回读到的字节数据,如果达到文件末尾,返回-1。
public int read(byte[] b)
//从输入流中读取字节数组长度的字节数据存入数组中,返回实际读到的字节数;如果达到文件的尾部,则返回-1。
FileOutputStream
public void write(int b)
//将指定字节写入输出流。
public void write(bute[] b)
//一次写多个字节,将b数组中所有字节,写入输出流。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Demo1 { public static void main (String[] args) throws IOException { FileInputStream fileInputStream=new FileInputStream("d:\\aaa.txt" ); int data=fileInputStream.read(); System.out.println((char )data); while ((data=fileInputStream.read())!=-1 ) { System.out.print((char )data); } byte [] b=new byte [1024 ]; if ((data=fileInputStream.read(b))!=-1 ) { System.out.println(new String(b,0 ,data)); } fileInputStream.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Demo2 { public static void main (String[] args) throws IOException { FileOutputStream fileOutputStream=new FileOutputStream("d:\\bbb.txt" ); fileOutputStream.write(97 ); fileOutputStream.write('b' ); fileOutputStream.write('c' ); fileOutputStream.write(new String("helloworld" ).getBytes()); fileOutputStream.close(); } }
文件字节流小案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Demo3 { public static void main (String[] args) throws IOException { FileInputStream fileInputStream=new FileInputStream("d:\\MrG1.jpg" ); FileOutputStream fileOutputStream=new FileOutputStream("d:\\MrG2.jpg" ); int count; byte [] b=new byte [1024 ]; while ((count=fileInputStream.read(b))!=-1 ) { fileOutputStream.write(b, 0 , count); } System.out.println("复制成功" ); fileInputStream.close(); fileOutputStream.close(); } }
字节缓冲流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class Demo4 { public static void main (String[] args) throws IOException { FileInputStream fileInputStream=new FileInputStream("d:\\aaa.txt" ); BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream); int data; while ((data=bufferedInputStream.read())!=-1 ) { System.out.print((char )data); } int count; byte [] buf=new byte [1024 ]; while ((count=bufferedInputStream.read(b,0 ,b.length))!=-1 ) { System.out.println(new String(buf,0 ,count)); } bufferedInputStream.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Demo5 { public static void main (String[] args) throws IOException { FileOutputStream fileOutputStream=new FileOutputStream("d:\\buf.txt" ); BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(fileOutputStream); bufferedOutputStream.write("helloworld" .getBytes()); bufferedOutputStream.flush(); bufferedOutputStream.close(); } }
对象流
序列化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Student { private String name; private int age; public Student (String name, int age) { super (); this .name = name; this .age = age; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = name; } @Override public String toString () { return "Student [name=" + name + ", age=" + age + "]" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Demo6 { public static void main (String[] args) throws IOException { FileOutputStream fileOutputStream=new FileOutputStream("d:\\stu.bin" ); ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream); Student tang=new Student("唐瑞" , 21 ); objectOutputStream.writeObject(tang); objectOutputStream.close(); System.out.println("序列化完毕" ); } }
注 :执行上述代码后IDE会抛出java.io.NotSerializableException
,意思是Student类不能被序列化,需要实现Serializable接口。
1 2 public class Student implements Serializable { }
Serializable其实是一个标志接口,用来标志该类是否可以被序列化。我们进到该接口的源码可以发现里面不含任何属性和抽象方法。
1 public interface Serializable { }
反序列化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Demo7 { public static void main (String[] args) throws IOException, ClassNotFoundException { FileInputStream fileInputStream=new FileInputStream("d:\\stu.bin" ); ObjectInputStream objectInputStream=new ObjectInputStream(fileInputStream); Student student=(Student) objectInputStream.readObject(); objectInputStream.close(); System.out.println("执行完毕" ); System.out.println(student.toString()); } }
序列化和反序列化注意事项
序列化类必须实现Serializable接口,前文已经说过。
序列化类中的对象属性也要求实现Serializable接口。也就是说如果Student类中有一个Grad类型的属性private Grad info;
那么Grad这个类也要实现Serializable接口。
序列化类中可以添加序列化版本号ID,以保证序列化的类和被序列化的类是同一个类。在上面的代码中我并没有添加序列号版本,虽然IDE没有报错,但是会显示一个警告,提示我添加序列化版本号(串行版本标识)。我们可以在Student类中添加:
1 private static final long serialVersionUID = 66666L ;
此时再运行Demo7就会报一个无效类的异常:
1 java.io.InvalidClassException: local class incompatible: stream classdesc serialVersionUID = -3126921853274410929, local class serialVersionUID = 666660
意思就是两个类的serialVersionUID不一样。可以看到之前虽然没有显式添加序列版本号,但它已经自动生成了一个。我们再运行一下Demo6序列化,再运行Demo7反序列化就可以正常执行了。
使用transient(短暂的)修饰属性,可以避免该属性被序列化。用它来修饰age:
1 private transient int age;
把tang这个对象序列化后再反序列化,这个对象的age属性就变成了0。
静态属性不能被序列化。
可以利用集合来序列化多个对象:
1 2 3 4 5 ArrayList<Student> arrayList=new ArrayList<Student>(); arrayList.add(s1); arrayList.add(s2); arrayList.add(s3); objectOutputStream.writeObject(arrayList);
1 ArrayList<Student> list=(ArrayList<Student>)objectInputStream.readObject();
编码方式
IOS-8859-1
收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。采用1个字节来表示,最多只能表示256个字符。
UTF-8
针对Unicode码表的可变长度字符编码。国际上使用的编码,也称为“万国码”,收录了几乎所有国家的常用字符。采用1至3个字节来表示一个字符。
GB2312
简体中文,采用1个或2个字节来表示字符,95年之前所采用的编码。
GBK
简体中文的扩充,GB2312的升级版本。
BIG5
台湾,繁体中文。
当编码方式和解码方式不一致时,会出现乱码。 假如Demo1中的文件内容不是字母而是“我爱中国 ”这样的汉字,那么读取出来的信息就是乱码。因为字节流按字节输入输出,而这四个汉字占了12个字节,把一个汉字按一个一个字节读入自然会出现问题,这时就需要使用字符流。
字符流
字符流的父类(抽象类) :
Reader: 字符输入流
public int read()
从流中读取单个字符,用整型来返回读取的字符;当读到流底部时返回-1。
public int read(char[] c)
从流中读取字符保存到c数组中,返回读取的字符个数,当读到流底部时返回-1。
public int read(char[] cbuf,int off,int len){}
抽象方法。
Writer: 字符输出流
public void write(int n)
写入单个字符,只能写入包含16位低阶字节的整型数值,16位高阶字节将会被忽略。
public void write(String str)
写入一个字符串。
public void write(char[] cbuf)
写入一个字符数组。
字符流的子类
FileReader:
public int read()
继承自InputStreamReader类。读取单个字符,返回读取的字符,当读到流底部时返回-1。
public int read(char[] c)
继承自Reader类。
public int read(char[] cbuf,int offset,int length)
继承自InputStreamReader类。从流中读取部分字符到cbuf中指定位置,返回读取到的字符个数,当读到流底部时返回-1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Demo1 { public static void main (String[] args) throws IOException { FileReader fileReader=new FileReader("d:\\cbuf.txt" ); int data; while ((data=fileReader.read())!=-1 ) { System.out.print((char )data); } fileReader.close(); } }
这里记录我遇到的一个问题 :
上述代码执行后理应是正常输出一段文字,但我这里出现了文字乱码。猜测是编码出现了问题,于是查看本地文本的保存格式为UTF-8,感觉也没错,于是打开JDK API查看FileReader类的描述:
Convenience class for reading character files. The constructors of this class assume that the default character encoding and the default byte-buffer size are appropriate. To specify these values yourself, construct an InputStreamReader on a FileInputStream.
大意就是该类的构造方法有一个默认的字符编码格式和一个默认字节缓冲区,并没有指明这个编码格式就是UTF-8。于是查看系统默认编码,打开CMD输入chcp,得到一个值为936的活动编码页,通过查询得知该代码页所对应的国家(地区)或语言为:中国 - 简体中文(GB2312)。这与本地所保存的文本编码UTF-8不一致,所以导致了文字乱码的出现。而要指定编码格式需要创建一个InputStreamReader或FileInputStream对象使用其构造方法。
以下是我在本地能正常运行的代码:
1 2 3 4 5 6 7 8 9 10 11 public class Demo1 { public static void main (String[] args) throws IOException { InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream("d:\\cbuf.txt" ),"UTF-8" ); int data; while ((data=inputStreamReader.read())!=-1 ) { System.out.print((char )data); } inputStreamReader.close(); } }
FileWriter:
public void write(int c)
继承自OutputStreamWriter类,写入一个字符。
public void write(String str)
继承自Writer类。
public void Write(char[] cbuf)
继承自Writer类。
1 2 3 4 5 6 7 8 9 10 11 public class Demo2 { public static void main (String[] args) throws IOException { FileWriter fileWriter=new FileWriter("d:\\w.txt" ); fileWriter.write("给自己一个希望。" ); fileWriter.close(); System.out.println("执行完毕" ); } }
字符流小案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Demo3 { public static void main (String[] args) throws IOException { InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream("d:\\w.txt" )); FileWriter fileWriter=new FileWriter("d:\\w2.txt" ); int data=0 ; while ((data=inputStreamReader.read())!=-1 ) { fileWriter.write(data); } inputStreamReader.close(); fileWriter.close(); System.out.println("执行完毕" ); } }
字符缓冲流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Demo4 { public static void main (String[] args) throws IOException { InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream("d:\\cbuf.txt" ),"UTF-8" ); BufferedReader bufferedReader=new BufferedReader(inputStreamReader); char [] cbuf=new char [1024 ]; int count; while ((count=bufferedReader.read(cbuf))!=-1 ) { System.out.println(new String(cbuf,0 ,count)); } String line; while ((line=bufferedReader.readLine())!=null ) { System.out.println(line); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Demo5 { public static void main (String[] args) throws IOException { BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("d:\\w3.txt" )); bufferedWriter.write("真有人看这篇博客吗?" ); bufferedWriter.newLine(); bufferedWriter.write("不会吧不会吧!!" ); bufferedWriter.close(); System.out.println("执行完毕" ); } }
打印流
PrintWriter:
封装了print()/println()方法,支持写入后换行。
支持数据原样打印。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Demo6 { public static void main (String[] args) throws FileNotFoundException { PrintWriter printWriter=new PrintWriter("d:\\p.txt" ); printWriter.println(97 ); printWriter.println('b' ); printWriter.println(3.14 ); printWriter.println(true ); printWriter.close(); System.out.println("执行完毕" ); } }
转换流
1 2 3 4 5 6 7 8 9 10 11 12 public class Demo7 { public static void main (String[] args) throws IOException { OutputStreamWriter outputStreamWriter=new OutputStreamWriter(new FileOutputStream("d:\\info.txt" )); outputStreamWriter.write("知道的越多,不明白的也就更多,学海无涯。" ); outputStreamWriter.close(); System.out.println("执行完毕" ); } }
File类
概念 :代表物理盘符中的一个文件 或者文件夹 。
方法 :
public boolean CreateNewFile()
当且仅当指定的文件名不存在时创建一个指定的新的、空的文件。创建成功返回true,如果指定文件名已存在返回false。
public boolean mkdir()
创建一个指定路径名的文件夹。当且仅当文件夹被创建时返回true,否则返回false。
public boolean delete()
删除一个指定的文件或文件夹,文件夹必须为空才能被删除。当且仅当指定的文件或文件夹被删除时返回true,否则返回false。
public boolean exists()
检查指定的文件或文件夹是否存在。当且仅当指定的文件或者文件夹存在时返回true,否则返回false。
public File[] listFiles()
列出目录中的所有内容,返回一个指定路径名中的文件数组,如果指定的路径名不代表一个文件夹(目录)就返回null。
public boolean renameTo(File dest)
重命名一个路径名所指定的文件。当且仅当修改操作成功时返回true,否则返回false。
文件操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class Demo1 { public static void main (String[] args) throws IOException, InterruptedException { separator(); fileOp(); } public static void separator () { System.out.println("路径分隔符:" +File.pathSeparator); System.out.println("名称分隔符:" +File.separator); } public static void fileOp () throws IOException, InterruptedException { File file=new File("d:\\file.txt" ); if (!file.exists()) { boolean flag=file.createNewFile(); System.out.println("创建状态:" +flag); } file.deleteOnExit(); Thread.sleep(5000 ); System.out.println("文件绝对路径:" +file.getAbsolutePath()); System.out.println("获取路径:" +file.getPath()); System.out.println("获取父目录:" +file.getParent()); System.out.println("获取文件名称:" +file.getName()); System.out.println("获取文件长度:" +file.length()); System.out.println("获取文件创建时间:" +new Date(file.lastModified()).toLocaleString()); System.out.println("是否可写:" +file.canWrite()); System.out.println("是否可读:" +file.canRead()); System.out.println("是否隐藏:" +file.isHidden()); System.out.println("是否是文件:" +file.isFile()); System.out.println("是否是文件夹:" +file.isDirectory()); } }
文件夹操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class Demo2 { public static void main (String[] args) { directorOp(); } public static void directorOp () { File dir=new File("d:\\aaa\\bbb\\ccc" ); if (!dir.exists()) { boolean flag=dir.mkdirs(); System.out.println("创建结果:" +flag); } dir.deleteOnExit(); System.out.println("获取绝对路径:" +dir.getAbsolutePath()); System.out.println("获取路径:" +dir.getPath()); System.out.println("获取父目录:" +dir.getParent()); System.out.println("获取创建时间:" +new Date(dir.lastModified()).toLocaleString()); System.out.println("文件夹名称:" +dir.getName()); System.out.println("是否隐藏:" +dir.isHidden()); System.out.println("是否是文件:" +dir.isFile()); File dir2=new File("d:\\" ); String[] files=dir2.list(); for (String string : files) { System.out.println(string); } } }
文件过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void directorOp () { File[] files1=dir2.listFiles(new FileFilter() { @Override public boolean accept (File pathname) { if (pathname.getName().endsWith(".txt" )) { return true ; } return false ; } }); for (File file : files1) { System.out.println(file.getName()); } }
文件操作小案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public class Demo3 { public static void main (String[] args) { } public static void listDer (File dir) { File[] files=dir.listFiles(); if (files!=null &&files.length>0 ) { for (File file : files) { if (file.isDirectory()) { listDer(file); }else { System.out.println(file.getName()); } } } } public static void deleteDir (File dir) { File[] files=dir.listFiles(); if (files!=null &&files.length>0 ) { for (File file : files) { if (file.isDirectory()) { deleteDir(file); }else { file.delete(); } } } dir.delete(); } }
补充:Properties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class Demo1 { public static void main (String[] args) throws IOException { Properties properties=new Properties(); properties.setProperty("username" , "tangrui" ); properties.setProperty("age" , "21" ); System.out.println(properties.toString()); Set<String> set=properties.stringPropertyNames(); for (String string : set) { System.out.println(string+" " +properties.getProperty(string)); } PrintWriter printWriter=new PrintWriter("d:\\print.txt" ); properties.list(printWriter); printWriter.close(); FileOutputStream fileOutputStream=new FileOutputStream("d:\\s.properties" ); properties.store(fileOutputStream, "NOTES" ); fileOutputStream.close(); Properties properties2=new Properties(); FileInputStream fileInputStream=new FileInputStream("d:\\s.properties" ); properties2.load(fileInputStream); fileInputStream.close(); System.out.println(properties2.toString()); } }