JAVA笔记(18)--- IO流 精讲
Posted 猿头猿脑的王狗蛋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA笔记(18)--- IO流 精讲相关的知识,希望对你有一定的参考价值。
FileInputStream-FileOutputStream:
1.构造方法:
new ( "文件的 绝对路径/相对路径" ) ;
//注意构造方法的参数是字符串类型
//绝对路径为带磁盘目录的,如:C:\\java-prictice\\javaseplus\\text
//相对路径:(IDEA默认当前路径:当前模块的根)+相对路径
//通过“电脑”复制文件位置的时候,要在上边的那个路径的后面+ “\\具体文件名”,否则此路径只是代表你看到界面的上一个目录;
//把路径粘贴到构造方法里的时候,IDEA工具会自动把“ \\ ”转换为“ \\\\ ”,实际上,把“ \\\\ ”改为“ / ”也是正确的;
FileInputStream 引用文件,代表将此文件作为读的对象;
FileOutputStream 引用文件,代表将此文件作为写的对象(输出在此文件中),若此文件不存在,则会自动创建;
2.常用方法:
1)FileInputStream . read ( bytes数组 ) //读取流的字节,并将读取的字节放到byte数组里,返回读取字节个数(int)[ 若读到文件末尾,则返回-1 ]
2)FileInputStream . available ( int ) //返回流当前未读取的字节个数
3)FileInputStream . skip ( int ) //跳过几个字节不读
3.注意:
1)为方便 finally语句中对流的关闭,所以一般在try外边声明空指针引用,在try里边new流对象;
2)声明的byte数组长度不宜过长,因为内存中很难找到一条特别长的连续空间;
3)每个流不能一起(并列)关闭,避免出现异常导致有些流无法关闭;
4.拷贝文件:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//File字节流拷贝
public class FileInputStreamTest {
public static void main(String[] args) {
//声明 FileInputStream 引用为空
FileInputStream fis=null;
//声明 FileOutputStream 引用为空
FileOutputStream fos=null;
//拷贝的重要操作(抛出异常的部分)放到try-catch里
try {
//创建文件字节输入流
fis=new FileInputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debug.txt");
//创建文件字节输出流
fos=new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debugFISCopy.txt",true);
//创建长度为100的数组bytes,元素类型为byte(字节)
byte [] bytes=new byte[100];
//声明“读取字节个数”的变量
int readCount;
//读取fis的“bytes.length”个字节,同时判断是否退出循环
//循环退出条件:读取字节个数为 -1
while ((readCount=fis.read(bytes))!=-1){
//将此时bytes里装的字节写入fos对象里
fos.write(bytes,0,readCount);
}
//刷新输出流
fos.flush();
} catch (FileNotFoundException e) {//用IDEA工具生成
e.printStackTrace();
} catch (IOException e) {//用IDEA工具生成
e.printStackTrace();
} finally {//fis与fos分开关闭,避免彼此的影响
if (fis!=null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos!=null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileReader-FileWriter:
1.构造方法:
FileReader 构造方法参考 《FileInputStream-FileOutputStream》
FileWriter 构造方法:
//此流的writer方法,会将写的字符覆盖整个文本(原文件中的字符会被删除,然后录入写的字符)
FileWriter fileWriter1=new FileWriter("C:\\\\Program Files\\\\Git\\\\bin");
//此流的writer方法,会将写的字符添加到文本后面(原文件中的字符不变)
FileWriter fileWriter2=new FileWriter("C:\\\\Program Files\\\\Git\\\\bin",true);
2.常用方法:
参照 《FileInputStream-FileOutputStream》与下面的《拷贝文件》;
3.注意:
字节流拷贝文件时,数组声明为byte类型,那用字符流时,自然就声明为char类型;
字符流绑定的文件格式只能是“ . txt ” 格式;
4.拷贝文件:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//File字符流拷贝
public class FileWriteTest {
public static void main(String[] args) {
FileReader in=null;
FileWriter out=null;
try {
in=new FileReader("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debug.txt");
out=new FileWriter("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debugFWCopy.txt",true);
char [] chars=new char[3];
int readCount;
while ((readCount=in.read(chars))!=-1){
out.write(chars,0,readCount);
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (in!=null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out!=null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
BufferedReader-BufferedWriter:
1.BufferedReader,BufferedWriter,都是自带缓冲的流,换句话说,不需要提供数组,也可以拷贝文本;
2.构造方法:
BufferedReader 参数:字符输入流(FileRead)
BufferedWriter 参数:字符输出流(FileWriter)
InputStreamReader 参数:字节输入流(FileInputStream)//将字节输入流转换为字符输出流
OutputStreamWriter 参数:字节输出流(FileOutputStream)//将字节输出流转换为字符输出流
综上,可以这么写:
BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debug.txt")));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debugBRCopy.txt",true)));
3.常用方法:
BufferedReader . readLine ( ) //读取流当前行
BufferedWriter . write ( ) //写入流当前行
4.拷贝文件代码:
import java.io.*;
//Buffered字符流拷贝
public class BufferedReadTest {
public static void main(String[] args) {
BufferedReader br=null;
BufferedWriter bw=null;
try {
br=new BufferedReader(new InputStreamReader(new FileInputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debug.txt")));
bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\debugBRCopy.txt",true)));
String read;
while ((read=br.readLine())!=null){
bw.write(read);
//让文本一行一行的写出来
bw.write("\\n");
}
bw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (br!=null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bw!=null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
DataOutputStream-DataInputStream:
1.DataOutputStream,DataInputStream 都是数据专属流,这个流可以将数据连同数据的类型一并写入文件;
2.注意:
DataOutputStream 写的文件,只能用 DataInputStream 去读,并且读的时候,读的顺序必须和写的顺序一样,才可以正常取出数据;
专属流读和写的文件都不是普通文档(用记事本看不到正常信息);
3.“读写”训练:
import java.io.*;
public class DataOutputStreamTest {
public static void main(String[] args) {
DataOutputStream dos=null;
DataInputStream dis=null;
try {
dos=new DataOutputStream(new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\DOS.txt",true));
dis=new DataInputStream(new FileInputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\DOS.txt"));
byte b=100;
short s=200;
int i=300;
long l=400l;
float f=500.0f;
double d=600.0;
boolean sex=true;
char c=\'c\';
dos.writeByte(b);
dos.writeShort(s);
dos.writeInt(i);
dos.writeLong(l);
dos.writeFloat(f);
dos.writeDouble(d);
dos.writeBoolean(sex);
dos.writeChar(c);
dos.flush();
System.out.println(dis.readByte());
System.out.println(dis.readShort());
System.out.println(dis.readInt());
System.out.println(dis.readLong());
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
System.out.println(dis.readChar());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dis!=null){
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dos!=null){
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
点击查看输出结果
100
200
300
400
500.0
600.0
true
c
Process finished with exit code 0
PrintStream:
1.PrintStream 属于标准字节输出流,默认输出到控制台上;
2.举个栗子:
import java.io.PrintStream;
public class pra{
public static void main(String[] args) {
PrintStream ps=System.out;
ps.println("输出到控制台上");
}
}
运行结果:
------------------------
输出到控制台上
Process finished with exit code 0
3.改变 PrintStream 的输出方向:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class PrintStreamTest {
public static void main(String[] args) {
//向日志中导入msg字符串
Logger.log("调用了 System 的 gc() ,建议启动垃圾回收器");
Logger.log("调用了 UserSystem 的 book()");
Logger.log("用户尝试登录,验证失败");
}
}
//日志类
class Logger {
public static void log(String msg) {//获取字符串msg
//声明空引用
PrintStream printStream=null;
try {
//printStream流 绑定此文件
printStream = new PrintStream(new FileOutputStream("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\log.txt",true));
//改变System.out的输出方向(输出的东西会进入printStream流)
System.setOut(printStream);
//获取此时刻时间
Date nowTime =new Date();
//自定义时间格式
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//将nowTime转换为我们的自定义格式,然后将msg字符串拼接上,最后输出
System.out.println(sdf.format(nowTime)+" : "+msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
4.注意:标准输出流不需要手动 clsoe 流;
File 类:
1.概述:File 类与IO流四大家族无继承关系,所以File类不能完成文件的读与写;
2.构造方法:new ( " 路径 " ) ;
3.常用方法:
引用 . createNewFile ( ) //在指定位置创建一个空文件(成功就返回true,如果已存在就不创建,然后返回false)
引用 . mkdir ( ) // 在指定位置创建一个文件夹
引用 . mkdirs ( ) // 在指定位置创建一个多重文件夹
引用 . exists ( ) // 判断文件或文件夹是否存在
引用 . isFile ( ) // 判断是否是一个文件,返回 boolean
引用 . isDirectory ( ) // 判断是否是一个目录,返回 boolean
引用 . getAbsolutePath ( ) // 获取文件的绝对路径,与文件是否存在没关系
引用 . getParent ( ) // 返回此文件路径的父路径(String),如果此路径名没有指定父目录,则返回null
引用 . getName ( ) // 获取文件或文件夹的名称,不包含上级路径
引用 . length ( ) // 返回此文件大小(字节)
引用 . lastModified ( ) // 获取文件最后一次被修改的时间
引用 . listFiles ( ) // 返回当前目录下的所有子文件(返回值类型为 FIle数组)
ObjectInputStream-ObjectOutputStream:
此体系知识请参考《上边的》
结合栗子理解:
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class ObjectInputStreamTest {
public static void main(String[] args) throws Exception{//将所有异常抛出
//ObjectOutputStream 绑定Cars文件(若无则新建)
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("Cars"));
//ObjectInputStream 绑定已存在的Cars文件
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("Cars"));
//创建专门装Car的集合cars
List<Car> cars=new ArrayList<>();
//向cars集合中添加元素
cars.add(new Car(1,"大众"));
cars.add(new Car(2,"法拉利"));
cars.add(new Car(3,"丰田"));
//将集合cars写入oos绑定文件中(反序列化)
oos.writeObject(cars);
//读取ois绑定文件中的所有对象(序列化),并强转为List<Car>类型,最后将所有对象装到carsList集合中
List<Car> carsList= (List<Car>) ois.readObject();
//遍历carsList集合
for (Car car:carsList) {
System.out.println(car);
}
oos.flush();
oos.close();
ois.close();
}
}
class Car implements Serializable{
private static final long serialVersionUID = -2630683108946058933L;
private int no;
private String brand;
public Car() {
}
public Car(int no, String model) {
this.no = no;
this.brand = model;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getModel() {
return brand;
}
public void setModel(String model) {
this.brand = model;
}
@Override
public String toString() {
return "Car{" +
"no=" + no +
", model=\'" + brand + \'\\\'\' +
\'}\';
}
}
控制台输出结果:
---------------------------
Car{no=1, model=\'大众\'}
Car{no=2, model=\'法拉利\'}
Car{no=3, model=\'丰田\'}
Process finished with exit code 0
序列化 / 反序列化:
1.概述:
2.自定义的类需要实现 Serializable 接口,才支持序列化和反序列化;
3.序列化版本号:
实现了 Serializable 接口的类,系统会为其自动生成一个序列化版本号,但是最好咱们手动生成版本号,举个栗子:
import java.io.Serializable;
class Car implements Serializable{
private static final long serialVersionUID = 8342087006090942735L;
}
java虚拟机识别一个类,首先看类名,其次看序列化版本号;
4.被 transient 关键字修饰的属性不参与序列化:
private transient String name;
IO+Properties:
1.优点:
对于以后需要经常改变的数据,可以单独写到一个文件中,使用程序动态读取;将来只需要修改这个文件的内容, java代码不需要改动,不需要重新编译,服务器也不需要重启,就可以拿到动态的信息;类似这种机制的这种文件被称为配置文件;
2.当配置文件中的内容格式为:
key1=value
key2=value
我们把这种配置文件叫做属性配置文件;
3.注意:
java 规范中有要求:属性配置文件建议以 “ . properties ”结尾;这种以 ”. properties “结尾的文件在java中被称为:属性配置文件;
Properties 是专门存放属性配置文件内容的一个类;
4.栗子老师:
import java.io.FileReader;
import java.util.Properties;
public class IOProperties {
public static void main(String[] args) throws Exception{
//FileReader绑定文件
FileReader reader=new FileReader("C:\\\\java-prictice\\\\javaseplus\\\\pra\\\\IOPropertiesTest.txt");
Properties pro=new Properties();
//将FileReader绑定文件载入Pro集合
pro.load(reader);
//通过key获取value
System.out.println(pro.getProperty("username"));
System.out.println(pro.getProperty("password"));
System.out.println(pro.getProperty("data"));
System.out.println(pro.getProperty("不存在的key,会输出 null"));
}
}
运行结果:
-----------------------------
a01
123456a01
null
null
Process finished with exit code 0
随笔:
节点流:本身作为包装流的构造方法的参数;
包装流:包装流的构造方法的参数是节点流;
以上是关于JAVA笔记(18)--- IO流 精讲的主要内容,如果未能解决你的问题,请参考以下文章
高薪程序员&面试题精讲系列22之说说Java的IO流,常用哪些IO流?
java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段
Java 学习笔记 - IO篇:常见的IO流Stream以及相互关系