Java IO流

目录

一.文件

1.介绍

2.创建文件

3.常用文件操作

二.流(Stream)

1.IO流的原理

2.流的分类

三.文件字节流

1.FileInputStream(输入)

2.FileOutputStream(输出) 

四.文件字符流

1.FileReader(输入)

2.FileWriter(输出)

五.处理流(包装流)

1.节点流和处理流

2.BufferedReader(输入)

3.BufferedWriter(输出)

六.对象流

1.序列化和反序列化

2.ObjectOutputStream(输出)

3.ObjectInputStream(输入)

4.注意事项

七.转换流

1.介绍

2.InputStreamReader(输入)

2.OutputStreamWriter(输出)

八.打印流

1.PrintStream

2.PrintWriter

九.Properties 类

1.介绍

2.常见方法

3.读文件

4.创建和修改文件


一.文件

1.介绍

文件就是保存数据的地方。这个数据可以是文本,也可以是图片或视频。

文件在程序中是以流的形式来操作的,称之为文件流。文件流有两种:

输入流:数据从数据源(文件)到程序(内存)的路径

输出流:数据从程序(内存)到数据源(文件)的路径

这里是输入输出是相对于java程序也就是内存而言的。

2.创建文件

方法一:

//方法一:new File(String pathname) 路径
public void create01(){
    String pathname="E:\\news1.txt";
    File file = new File(pathname);
    try {
        file.createNewFile();
        System.out.println("创建成功");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

方法二:

//方法二:new File(File parent,String child)   父目录文件+子路径
public void create02(){
    File parent = new File("E:\\");
    String child="news2.txt";
    File file = new File(parent, child);
    try {
        file.createNewFile();
        System.out.println("创建成功");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

方法三:

//方法三:new File(String parent,String child) 父目录+子路径
public void create03(){
    String parent="E:\\";
    String child="news3.txt";
    File file = new File(parent, child);
    try {
        file.createNewFile();
        System.out.println("创建成功");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3.常用文件操作

获取文件相关信息:

方法说明
getName()获取文件名字

getAbsoluteFile()

获取文件绝对路径
getParent()获取文件父级目录
length()获取文件大小(字节)
exists()判断文件是否存在
isFile()判断是不是一个文件
isDirectory()判断是不是一个目录

目录的操作和文件删除:

方法说明

mkdir()

创建一级目录
mkdirs()创建多级目录
delete()删除空目录或文件

补充:目录是以文件为数据的文件,可以把目录理解成文件夹。mkdir()创建目录的最后一个父目录必须存在,其只能创建一级目录。mkdirs()可以创建一级或多级。

二.流(Stream)

JavaIO流用于处理数据传输,如读写文件,网络通讯等。Java程序中,对于数据的输入/输出操作以“流”的方式进行。

1.IO流的原理

输入input :读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中

输出 output :将程序(内存)数据输出到磁盘、光盘等存储设备中

2.流的分类

按操作数据单位不同分为:字节流(8 bit)二进制文件(如声音、视频、pdf等)、字符流(按字符)文本文件

按数据流的流向不同分为:输入流、输出流

按流的角色的不同分为:节点流、处理流(包装流)

抽象基类字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

说明:Java的IO流共涉及40多个类,其都是由上面的4个抽象基类派生的。

各个流的分类一定要弄清楚!

三.文件字节流

字节流有两个基类:InputStream(输入) 和 OutputStream(输入)。

下面介绍一下这两个基类的文件输入输出流。

1.FileInputStream(输入)

读取方式:先创建FileInputStream对象,用于读取文件;再使用FileInputStream.read()方法进行读取,read方法返回的是int类型的值,如果返回-1,说明读取完毕;最后不要忘记关闭文件流释放资源。

代码示例:

String filePath="C:\\news1.txt\\news2.txt";
int readData=0;
FileInputStream fileInputStream=null;
try {
    fileInputStream=new FileInputStream(filePath);
    while((readData=fileInputStream.read())!=-1){
        System.out.println((char)readData);
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

上述代码的效率太低,这是因为它是一个一个字节的读,太慢了,我们有没有什么办法让它一次多好几个呢?当然有,我们可以使用一个字节数组,其大小不固定,看我们需要多少,这里我用的是大小为8的:

String filePath="C:\\news1.txt\\news2.txt";
byte[] b=new byte[8];
int readLen=0;
FileInputStream fileInputStream=null;
try {
    fileInputStream=new FileInputStream(filePath);
    while((readLen=fileInputStream.read(b))!=-1){
        System.out.print(new String(b,0,readLen));
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//使用readLen的好处:如果后面的字节不足8,那么就会产生乱码。使用readLen可以得到字节的长度,不会出现乱码

2.FileOutputStream(输出) 

写入方式:先创建FileOutputStream对象,用于写入数据;再开始写入数据;最后关闭文件流。

 FileOutputStream默认是覆盖文件,也就是我们新写入的内容会覆盖掉原来的文件内容。如果想不覆盖,改为追加在文件后面的话,就加个true(详情看代码示例)

代码示例:

String filePath="C:\\news1.txt\\news2.txt";
//覆盖
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
//不覆盖
FileOutputStream fileOutputStream = new FileOutputStream(filePath,true);
//写入单个字符
fileOutputStream.write('h');
//批量写入整个byte数组
fileOutputStream.write("hello".getBytes());
//部分写入,第二个参数是从第几个开始写入,第三个参数是写进几个
fileOutputStream.write("world".getBytes(),0,3);
fileOutputStream.close();

四.文件字符流

1.FileReader(输入)

读取的过程与文件字节流差不多,这里只有一点要说,就是这是字符输入流,可别将要存放读取数据的数组设置成byte。

代码示例:

public void reader01(){
    String filePath="C:\\news1.txt\\news2.txt";
    FileReader fileReader=null;
    int data=0;
    //创建一个FileReader对象
    try {
        fileReader=new FileReader(filePath);
        while((data = fileReader.read())!=-1){
            System.out.println((char)data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fileReader!=null){
            try {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public void reader02(){
    String filePath="C:\\news1.txt\\news2.txt";
    FileReader fileReader=null;
    int dataLen=0;
    char[] ch=new char[8];
    //创建一个FileReader对象
    try {
        fileReader=new FileReader(filePath);
        while((dataLen = fileReader.read(ch))!=-1){
            System.out.println(new String(ch,0,dataLen));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fileReader!=null){
            try {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.FileWriter(输出)

写入方式也与文件字节流的输出流相似,各个方法的内容也相似。

但是要注意FileWriter使用完后一定要关闭(close)或刷新(flush),否则写入不到指定的文件。在底层,close是后flush和关闭操作组合成的。从本质上来讲,让文件无法写入的关键是:是否刷新。

代码示例:

public void writer(){
    String filePath="C:\\news1.txt\\news2.txt";
    FileWriter fileWriter=null;
    try {
        fileWriter=new FileWriter(filePath);
        //1.写入单个字符
        fileWriter.write('E');
        //2.写入指定数组
        char[] ch={'1','2'};
        fileWriter.write(ch);
        //3.写入指定数组的指定部分
        fileWriter.write("abcde".toCharArray(),1,1);
        //4.写入整个字符串
        fileWriter.write("hello");
        //5.写入字符串的指定部分
        fileWriter.write("world",0,3);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fileWriter.close();
            System.out.println("关闭文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

五.处理流(包装流)

1.节点流和处理流

节点流可以用从一个特定的数据源读写数据,如FileReader、FileWriter等。节点流是底层流,是直接与数据源相接的。

处理流(包装流)是“连接”在以存在的流之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter等。包装流相当灵活,可以使用其父类来实例化对象。处理流即可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。处理流不与数据源直接相连。

处理流的功能:

性能的提高:主要以增加缓冲的方式来提高输入输出的效率。

操作的便捷:处理流可能提供一系列便捷的方式来一次输入输出大批量的数据,使用更加灵活。

2.BufferedReader(输入)

代码示例:

String filePath="C:\\news1.txt\\news2.txt";
//创建对象
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line;
while((line = bufferedReader.readLine())!=null){
    System.out.println(line);
}
//关闭流,底层会自动调用节点流
bufferedReader.close();

用的虽然是包装流,但实际工作的是节点流

3.BufferedWriter(输出)

代码示例:

String filePath="C:\\news1.txt\\news2.txt";
//创建对象
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
//写入数据
bufferedWriter.write("114514");
bufferedWriter.newLine();       //在写入时换行
bufferedWriter.write("1919810");
//关闭流
bufferedWriter.close();

六.对象流

1.序列化和反序列化

序列化:保存数据时保存数据的值和数据类型

反序列化:恢复数据时恢复数据的值和数据类型

为了让某个类实现可序列化,该类必须实现如下两个接口之一:

Serializable(这是一个标记接口,其没有要实现的方法)

Externalizable(该接口有要实现的方法,不推荐使用)

2.ObjectOutputStream(输出)

ObjectOutputStream是序列化,将数据的值和类型写入文件

代码示例:

String filePath="C:\\news1.txt\\news2.dat";
//创建对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据
oos.writeInt(100);     //int Integer实现了Serializable
oos.writeBoolean(true);
oos.writeUTF("hello");      //String类型
oos.close();

3.ObjectInputStream(输入)

ObjectInputStream的反序列化,将文件中存储的数据读到程序中去,这里要注意,反序列话取的内容顺序要与序列化相同,如果不同,如第一个本来是int类型的,结果反序列化取了一个double类型的,数据肯定是错的。

代码示例:

String filePath="C:\\news1.txt\\news2.dat";
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
//反序列化的顺序要与序列化的顺序一致
System.out.println(objectInputStream.readInt());
System.out.println(objectInputStream.readBoolean());
System.out.println(objectInputStream.readUTF());
//关闭资源
objectInputStream.close();

4.注意事项

1)读写顺序一致;

2)要求序列化或反序列化对象,需要实现 Serializable 接口;

3)序列化的类中默认添加SerialVersionUID,为了提高版本的兼容性;

4)序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员;

5)序列化对象时,要求里面属性的类型也要实现序列化接口;

6)序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化。

七.转换流

1.介绍

当处理纯文本文件数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所有建议将字节流转化成字符流。使用转换流时可以指定编码格式,如utf-8,gbk等。

2.InputStreamReader(输入)

Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)。

代码示例:

String filePath="C:\\news1.txt\\news2.txt";
//将FileInputStream 转成InputStreamReader
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath),"gbk");
//将InputStreamReader 传入
BufferedReader br = new BufferedReader(inputStreamReader);
String s = br.readLine();
System.out.println(s);
//关闭外层流
br.close();

2.OutputStreamWriter(输出)

Writer的子类,可以将OutputStream(字节流)包装成Writer(字符流)。

代码示例:

String filePath="C:\\news1.txt\\news2.txt";
//将FileInputStream 转成InputStreamReader
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath),"gbk");
//将InputStreamReader 传入
BufferedReader br = new BufferedReader(inputStreamReader);
String s = br.readLine();
System.out.println(s);
//关闭外层流
br.close();

八.打印流

打印流只有输出流,没有输入流。

1.PrintStream

代码示例:

PrintStream out=System.out;
//默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器
out.print("嗨嗨嗨");
//关闭流
out.close();
//修改打印流输出的位置/设备
String filePath="C:\\news1.txt\\news2.txt";
System.setOut(new PrintStream(filePath));
//下面这句会输出到文件中
System.out.println("小汉堡");

2.PrintWriter

代码示例:

String filePath="C:\\news1.txt\\news2.txt";
//输出到屏幕上
PrintWriter printWriter = new PrintWriter(System.out);
//输出到文件中
PrintWriter printWriter = new PrintWriter(new FileWriter(filePath));
printWriter.print("嗨嗨嗨");
//关闭流
printWriter.close();

九.Properties 类

1.介绍

专门用于读写配置文件的集合类。配置文件的格式:键=值,这里注意:键值对不需要有空格,值不需要用引号括起来,默认类型时String

2.常见方法

方法说明
load加载配置文件的键值对到Properties对象
list将数据显示到指定设备/流对象
getProperty(key)根据键获取值
setProperty(key,value)设置键值对到Properties对象
store将Properties中的键值对存储到配置文件,在idea中,如果保存到配置文件的信息中含有中文,会存储Unicode码

3.读文件

代码示例:

//创建对象
Properties properties = new Properties();
//加载指定配置文件
properties.load(new FileReader("C:\\news1.txt\\news2.txt"));
//把k-v显示控制台
properties.list(System.out);
//根据key获取对应的值
properties.getProperty("a");

4.创建和修改文件

代码示例:

Properties properties = new Properties();
//使用setProperty时,如果name不存在,那就是创建;如果name存在,那就是修改
properties.setProperty("name","Tom");
//将k-v存储文件中,后面的null是注释,没有注释就写null
properties.store(new FileOutputStream("C:\\news1.txt\\news2.txt"),null);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值