Java笔记-IO流
IO?
InputStream:输入流
OutputStream:输出流
之前在学Java的时候,对IO总有点似懂非懂,什么时候用输入流/输出流有些迷糊。刚刚看了个视频,觉得解释的很好:是输入,还是输出是以【内存】为主体来讲的;例如:
从硬盘中读入文件、从网络流中读取消息、读取键盘输入等等,这些情况都是从其它地方获取数据到内存,使用的是输入流;
相反,写入文件、网络通信中发送消息、输出字符到屏幕(System.out.print)等,这些是从内容输出数据到其它的地方,这是用到了输出流;
创建文件
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
|
@Test public void createFile1() throws IOException { File file = new File("d:\\f1.txt"); file.createNewFile(); }
@Test public void createFile2() throws IOException { File parFile = new File("d:\\"); File file = new File(parFile, "f2.txt"); file.createNewFile(); }
@Test public void createFile3() throws IOException { String parPath = "d:\\"; File file = new File(parPath, "f3.txt"); file.createNewFile(); }
|
获取文件信息
查看类图,可以看到提供了很多的方法,来获取文件的各种信息。

| @Test public void getFileInfo(){ File file = new File("d:\\f1.txt"); System.out.println(file.getName()); System.out.println(file.getAbsolutePath()); System.out.println("文件大小(字节)"+file.length()); System.out.println("是否存在"+file.exists()); System.out.println("是否是目录"+file.isDirectory()); System.out.println("是否是文件"+file.isFile()); }
|

值得注意的是,Java中通过mkdir(),如果填写的参数是多级目录就用mkdirs()来创建目录;
| public void newPath() throws IOException { String path = "d:\\a\\b\\c"; File file = new File(path); if(file.exists()){ System.out.println("目录已经存在"); }else{ file.mkdirs(); System.out.println("多级目录创建成功"); }
}
|

流的分类
按操作的数据单位:
字节流(InputStream\OutputStream)用于二进制文件、
字符流(Reader\Writer)用于字符文件
Java中IO流有40多个,他们都是有上面这4个抽象类派生而来的。这些派生出来的子类名称都是以父类名作为后缀。
读文件
| public void read1() throws IOException { FileInputStream fileInputStream = new FileInputStream("d:\\mytest.txt"); byte[] buf = new byte[8]; int len = 0; while ((len = fileInputStream.read(buf)) != -1) { System.out.print(new String(buf, 0, len)); } fileInputStream.close(); }
|
复制文件
| @Test public void read1() throws IOException { FileInputStream fileInputStream = new FileInputStream("d:\\a.png"); FileOutputStream fileOutputStream = new FileOutputStream("d:\\a2.png"); byte[] buf = new byte[1024]; int len = 0; while ((len = fileInputStream.read(buf)) != -1) { fileOutputStream.write(buf); } fileOutputStream.close(); fileInputStream.close(); }
|
FileReader\FileWriter
FileWriter使用后,必须要关闭(close)或者刷新(flush),否则写入不到指定的文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Test public void fileReader1() { FileReader fileReader = null; try { fileReader = new FileReader("d:\\f1.txt"); char[] buff = new char[8]; int len = 0; while ((len = fileReader.read(buff)) != -1) { System.out.println(new String(buff, 0, len)); } } catch (IOException e) { e.printStackTrace(); } finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } }
}
|
节点流\处理流
节点流:可以从一个特定的数据源读写数据
处理流:(包装流),是“连接”在已存在的流(节点流/处理流)之上,提供更强大的读写功能,BufferedReader、BufferedWriter——修饰器模式
下面这段代码,就是使用BufferedReader这个包装类,通过注入FileReader,实现读取文件;其中BufferedReader还提供了readLine()这个方法,返回读取到的一行字符串,很方便。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Test public void bufferedReader1() { BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader("d:\\f1.txt")); String line; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } }
|
对象流
序列化:在保存数据时,保存数据的值和类型;ObjectOutputStream
反序列化:在恢复数据时,恢复数据的值和类型;ObjectInputStream
要让某个类是可序列化的,这个类必须实现Serializable接口或者是Externalizable接口;
其中前者是一个标记接口没有方法,后者有方法需要实现。
注意:
- 读写顺序要一致;
- 要进行序列化的对象,它的类需要实现Serializable/Externalizable接口;
- 序列化的类中建议添加SerialVersionUID属性(private static final long 序列版本号),以提高兼容性;
- 序列化时默认将这个类的所有属性都进行序列化,除了哪些被static,transient修饰的属性;所以要求里面的属性也要实现可序列化接口;
- 序列化具备可继承性;父类实现了序列化接口,子类也可以序列化;
标准输入输出流
标准输入:System.in 键盘
编译类型-InputStream
运行类型-BufferedInputStream
标准输出:System.out 显示器
编译类型-运行类型-PrintStream
转换流
InputStreamReader 字节输入流-》字符输入流
OutputStreamWriter
打印流
只有输出流,没有输入
PrintStream
PrintWriter
Properties
专门用于读写配置文件的类;底层是HashMap;
格式:键=值
“=”连接,没有空格,值不需要用引号包起来,默认类型String
load()
list()
getProperties()
setProperties()
store(),其中如果有中文,会存储Unicode码