哎我就不信了,Java IO有这么难吗?

1. IO流

1.1 IO流简介

I 是 input,表示输入。o 是output,表示输出。流指的就是数据的传输。

Java IO 的字面意思:通过 java 编程语言实现数据的输入和输出。在这里指的就是文件的读和写操作。

那么,关于读,数据从哪里来?关于写,数据写到那里去?

:将数据从硬盘加载到内存中,例如通过 java 程序查看 txt 文档。

:将数据从内存写入到硬盘中,例如通过 java 程序给 txt 文档添加几个字符。

所以呢,读写操作就是数据在内存和硬盘之间的传输。

1.2 IO流分类

1)按照数据的流向

  • 输入流:其实就是文件的读操作
  • 输出流:其实就是文件的写操作

2)按照数据的传输类型

字节流字符流
字节输入流字符输入流
字节输出流字符输出流

1.3 IO流的常用场景

  • 文件上传
  • 文件下载
  • 复制文件

注意:如果我们操作的是图片、视频等二进制文件,优先使用字节流。如果操作的是文本文件,优先使用字符流。如果不知道文件的类型,优先使用字节流。

2. 文件操作:File类

无论是文件的读操作还是文件的写操作归根结底都是和文件打交道,所以呢在学习 java io 之前我们要先学习如何处理文件。

File 类是 java 中处理文件的核心类,这里讲解其中一些常见的方法。

1)创建文件

//我要在D盘eclipse目录下创建一个hello.txt的文件
File file = new File("D:\\eclipse\\hello.txt");
//创建文件
file.createNewFile();

2)创建文件夹

//在D盘eclipse文件夹下创建一个名为idea的文件夹
File file = new File("D:\\eclipse\\idea");
//创建文件夹
file.mkdir();

3)创建多级文件夹

//在D盘eclipse文件夹下创建多级文件夹:\hello1\hello2
File file = new File("D:\\eclipse\\hello1\\hello2");
//创建文件夹
file.mkdirs();

4)判断该路径下是不是文件?

File file = new File("D:\\eclipse\\hello.txt");
//判断该路径下是不是文件?
file.isFile();//true

5)判断该路径下是不是文件夹?

File file = new File("D:\\eclipse\\hello");
//判断该路径下是不是文件夹?
file.isDirectory();//true

6)判断该路径下的文件或者文件夹是否存在?

File file = new File("D:\\eclipse\\hello.txt");
//判断该路径下的文件或者文件夹是否存在?
System.out.println(file.exists());

7)删除文件/文件夹

File file = new File("D:\\eclipse\\hello.txt");
//删除文件或者文件夹
file.delete();

3. 字节流

3.1 字节输出流

//创建字节输出流的类
FileOutputStream(String pathName)

字节输出流使用步骤:

  1. 创建字节输出流对象,参数是输出到硬盘的位置。
  2. 调用写数据的方法
  3. 释放资源(切记)

下面讲解字节输出流常用方法:

1)一次写一个字节数据 write(int byte)

//创建字节输出流对象,将数据写入到指定文件里面
FileOutputStream outputStream = new FileOutputStream("D:\\eclipse\\hello.txt");
//一次写入一个字节的数据,97代表 a
outputStream.write(97);
//释放资源
outputStream.close();

执行结果:

2)一次写一个字节数组数据 write(byte[] bytes)

//创建字节输出流对象,将数据写入到指定文件里面
FileOutputStream outputStream = new FileOutputStream("D:\\eclipse\\hello.txt");
//一次写入一个字节数组的数据
String str="helloworld"
byte[] bytes = str.getBytes();
outputStream.write(bytes);
//释放资源
outputStream.close();

执行结果:

3)根据指定长度写字节数组的长度 write(byte[] bytes, int from, int len)

//创建字节输出流对象,将数据写入到指定文件里面
FileOutputStream outputStream = new FileOutputStream("D:\\eclipse\\hello.txt");
//写入指定长度的字节数组的数据
String str="helloworld"
byte[] bytes = str.getBytes();
//只要前两个字节
outputStream.write(bytes,0,2);
//释放资源
outputStream.close();

执行结果:

4)写入数据换行处理

不同操作系统的处理方式:

  • windows系统:\r\n
  • linux系统:\n
  • mac系统:\r

这里以windows系统为例:

//创建字节输出流对象,将数据写入到指定文件里面
FileOutputStream outputStream = new FileOutputStream("D:\\eclipse\\hello.txt");
String str="hello";
byte[] bytes = str.getBytes();
//遍历字节数组的数据
for (byte b : bytes) {
    outputStream.write(b);
    //换行
    outputStream.write("\r\n".getBytes());
}
//释放资源
outputStream.close();

执行结果:

3.2 字节输入流

//创建字节输入流的类
FileInputStream(String pathName)

字节输入流使用步骤:

  1. 创建字节输入流对象
  2. 调用读数据的方法
  3. 释放资源(切记)

下面讲解字节输入流常用的方法:

1)一次读一个字节的数据

//创建字节输入流对象,获取指定位置的文件
FileInputStream inputStream = new FileInputStream("D:\\eclipse\\hello.txt");
int charStr ;
//inputStream.read() 读数据
//charStr = inputStream.read() 将读到的数据赋值给charStr
//charStr != -1 判断读取到的数据是否为空
while (( charStr = inputStream.read())!=-1){
    System.out.print((char)charStr);
}
//释放资源
inputStream.close();

执行结果:

2)一次读一个字节数组的数据

//创建字节输入流对象,获取指定位置的文件
FileInputStream inputStream = new FileInputStream("D:\\eclipse\\hello.txt");
int charStr ;
byte[] bys = new byte[1024];
//inputStream.read(bys) 一次读一个字节数组的数据
//charStr = inputStream.read(bys) 将读到的数据赋值给charStr
//charStr != -1 判断读取到的数据是否为空
while (( charStr = inputStream.read(bys))!=-1){
    System.out.print(new String(bys,0,charStr));
}
//释放资源
inputStream.close();

执行结果:

3.3 字节流应用:复制文件

思考:想一下,你要复制文件你是不是得知道这个文件在哪里?拿到这个文件后是不是要先读取文件的内容?读的同时再把文件的内容写入到另一个文件里?

步骤:

  1. 创建字节输入流对象,读文件内容
  2. 创建字节输出流对象,写文件内容
  3. 一边读一边写
  4. 释放资源(切记)
//创建字节输入流对象,我从哪个文件复制?就是文件初始地
FileInputStream fileFrom = new FileInputStream("D:\\eclipse\\hello.txt");
//创建字节输出流对象,我要复制到哪个文件里面?就是文件目的地
FileOutputStream fileTo = new FileOutputStream("D:\\eclipse\\world.txt");
//读写数据,(一次读取一个字节数组,一次写入一个字节数组)
byte[] bytes = new byte[1024];
int len;
while ((len=fileFrom.read(bytes))!=-1) {
    fileTo.write(bytes,0,len);
}
//释放资源
fileFrom.close();
fileTo.close();

执行结果:
多了个world.txt文件,并且里面的内容和hello.txt内容一样

3.4 字节缓冲流

3.4.1 缓冲流介绍

就是当我们读取数据量特别大的文件时,读取的速度会超级慢,非常影响我们的心情。所以呢Java为我们提高了一套缓冲流机制,它可以大大的提高文件的读写速率。

3.4.2 字节缓冲流

  • BufferedOutputStream:字节缓冲输出流

  • BufferedInputStream:字节缓冲输入流

它们的内部有一个缓冲区,通过缓冲区读写,大大提高IO流的读写速度。

1)字节缓冲输出流

FileOutputStream fos=new FileOutputStream("D:\\eclipse\\hello.txt");
//字节缓冲输出流
BufferedOutputStream bos=new BufferedOutputStream(fos);
//写数据 98表示b
fos.write(98);
//释放资源
bos.close();

2)字节缓冲输入流

FileInputStream fis=new FileInputStream("D:\\eclipse\\hello.txt");
//创建字节缓冲输入流
BufferedInputStream bis=new BufferedInputStream(fis);
int len;
while((len=bis.read())!=-1){
    System.out.println((char)len);
}
//释放资源
bis.close();

3)使用字节缓冲流复制大文件

//我要复制的文件来自哪里?
FileInputStream fis=new FileInputStream("D:\\eclipse\\oracle.zip");
//创建字节输入缓冲流
BufferedInputStream bis=new BufferedInputStream(fis);
//我要复制到哪里去?
FileOutputStream fos=new FileOutputStream("D:\\eclipse\\idea.zip");
//创建字节输出缓冲流
BufferedOutputStream bos=new BufferedOutputStream(fos);
int len=0;
byte[] ch=new byte[1024];
//复制文件 边读边写
while((len=bis.read(ch))!=-1){
    bos.write(ch,0,len);
}
//释放资源
bos.close();
bis.close();

4. 字符流

在说起字符流之前先说一下编码与解码。

编码:GBK、UTF-8等,你就把它理解为一种数据格式,数据可以从一个格式转换为另一种格式。

乱码:编码与解码不一致,就会导致乱码。例如一个文档你用 UTF-8 编码,但是用 GBK 解码,就会出现字符与码值不匹配的情况,从而导致乱码。如下所示:

String tips="我爱你中国";
//使用指定的字符集将该String编码为字节数据
byte[] bys = tips.getBytes("GBK");
//通过指定的字符集解码指定的字节数组来创建字符串
String ss = new String(bys,"UTF-8");
System.out.println(":"+ss);

执行结果:


是不是一脸懵逼?这都是什么玩意?

因为使用字节流操作字符时,可能会因为中文字符导致乱码的情况,所以java就提供了字符流。

字符流:在字节流的基础上加上编码(GBK、UTF-8等),形成新的数据流。字符流 = 字节流 + 编码

字符流与字节流的区别:字节流支持声音、视频、图片、文本等所有文件类型,而字符流只支持文本文件。

4.1 字符输出流

//创建字符输出流的类
FileWriter(String pathName)

字符输出流使用步骤:

  1. 创建字符输出流对象
  2. 调用写数据的方法
  3. 释放资源(切记)
//创建字符输出流,将数据写入到指定位置的文件里面
FileWriter fileWriter = new FileWriter(new File("D:\\eclipse\\hello.txt"));
//写入数据
fileWriter.write("禾下乘凉梦一定会实现!");
//释放资源
fileWriter.close();

执行结果:

4.2 字符输入流

//创建字符输入流的类
FileReader(String pathName)

字符输入流使用步骤:

  1. 创建字符输入流对象
  2. 调用写数据的方法
  3. 释放资源(切记)
//创建字符输入流
FileReader fileReader = new FileReader(new File("D:\\eclipse\\hello.txt"));
char[] bytes = new char[1024];
int len;
//读取数据
while ((len = fileReader.read(bytes)) != -1) {
    System.out.println(new String(bytes, 0, len));
}
//释放资源
fileReader.close();

执行结果:

4.3 字符缓冲流

字符缓冲流:如果一个文件里面的字符太多,文件太大,可以用它来提高效率。

  • BufferedReader:字符缓冲输入流
  • BufferedWriter:字符缓冲输出流

1)字符缓冲输出流

//创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\eclipse\\haha.txt"));
bw.write("我爱你中国");
//自动换行方法,会自适应不同的操作系统
bw.newLine();
bw.write("哈哈哈哈哈");
//释放资源
bw.close();

执行结果:

2)字符缓冲输入流

//创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("D:\\eclipse\\other.txt"));
//读取文件
String value;
//每次读一行数据,以字符串形式返回这一行的数据
while ((value = br.readLine()) != null) {
    System.out.println(value);
}
br.close();

执行结果:

3)字符缓冲流复制文件

BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\eclipse\\student.txt"));
BufferedReader br=new BufferedReader(new FileReader("D:\\eclipse\\teacher.txt"));
String value="";
while((value=br.readLine())!=null) {
  bw.write(value);
  bw.newLine();
}
bw.close();
br.close();

4.4 转换流

将字节流转换成字符流,使用指定的编码来读取或写入数据流。

  • InputStreamReader: 将字节输入流转换成字符输入流
  • OutputStreamWriter:将字节输出流转换成字符输出流

1)字节输入流转换成字符输入流

InputStreamReader isr = new InputStreamReader(new
FileInputStream("D:\\eclipse\\haha.txt"),"GBK");
//一次读取一个字符数据
int str;
while ((str=isr.read())!=-1) {
System.out.print((char)str);
}
isr.close();

2)字节输出流转换成字符输出流

OutputStreamWriter osw = new OutputStreamWriter(new
FileOutputStream("D:\\eclipse\\haha.txt"),"GBK");
osw.write("中国加油"); 
osw.close();

5. Properties介绍

Properties介绍:

  • Properties 是一个 Map 体系的集合类
  • Properties 可以保存/加载数据
  • Properties 属性列表中的键值对都是一个字符串

1)Map集合

Properties properties = new Properties();
properties.setProperty("name", "jay");
properties.setProperty("age", "18");
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
    System.out.println(key);
    String value = properties.getProperty(key);
    System.out.println(key + "," + value);
}

执行结果:

2)从数据流中加载数据

Properties prop = new Properties();
FileReader fileReader = new FileReader("D:\\resources\\jdbc.properties");
prop.load(fileReader);
System.out.println(prop);
System.out.println(prop.getProperty("username"));
System.out.println(prop.getProperty("password"));
System.out.println(prop.getProperty("driver"));
fileReader.close();

执行结果:

6. 对象序列化&&反序列化

6.1 对象序列化

对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象。

对象序列化流: ObjectOutputStream

注意:一个对象要想被序列化,该对象所属的类必须实现 Serializable 接口

下面是对象序列化的示例代码:

用户类:

public class User implements Serializable {

    private String username;

    private int age;

    public User(String username, int age) {
        this.username = username;
        this.age = age;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}

序列化方法:

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\resources\\user.txt"));
//创建对象
User user = new User("zhangsan",12);
//将指定的对象写入ObjectOutputStream
oos.writeObject(user);
//释放资源
oos.close();

6.2 对象反序列化

对象反序列化:就是将文件转化为对象。说白了就是读数据,然后再转化为对象。

对象反序列化流: ObjectInputStream

示例代码:

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\resources\\user.txt"));
//Object readObject():从ObjectInputStream读取一个对象
Object object = ois.readObject();
User user = (User) object;
System.out.println(user.getUsername() + "," + user.getAge());
//释放资源
ois.close();

执行结果:

微信公众号:eclipse编程。专注于编程技术分享,坚持终身学习。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值