专栏首页eclipse编程哎我就不信了,Java IO有这么难吗?

哎我就不信了,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();

执行结果:

-END-

本文分享自微信公众号 - eclipse编程(eclipsecamp),作者:一颗雷布斯

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-05-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 小师妹学JavaIO之:File copy和File filter

    一个linux命令的事情,小师妹非要让我教她怎么用java来实现,哎,摊上个这么杠精的小师妹,我也是深感无力,做一个师兄真的好难。

    程序那些事
  • 不就是个短信登录API嘛,有这么复杂吗?

    早上开完站会,小李领了张新卡,要对登录功能做升级改造,在原来只支持用户名密码登录模式的基础上,新增手机号和短信验证码登录。

    帅地
  • 不就是个短信登录API嘛,有这么复杂吗?

    早上开完站会,小李领了张新卡,要对登录功能做升级改造,在原来只支持用户名密码登录模式的基础上,新增手机号和短信验证码登录。

    ThoughtWorks
  • [技巧篇] 如何在不会的情况下解释 Python 设置文件的缓冲的问题

    美好的中秋,朋友圈在享受悠闲周末的时候,刚入门 Python 的程序员小R在公司埋头加班,不知时间几何,一不小心把下周的工作捯饬完了,心情愉悦,不能自拔。

    编程文青李狗蛋
  • 小师妹学IO系列文章集合-附PDF下载

    java中最最让人激动的部分就是IO和NIO了。IO的全称是input output,是java程序跟外部世界交流的桥梁,IO指的是java.io包中的所有类,...

    程序那些事
  • 为什么业务分析师要学 PowerBI DAX - 破解乱象篇

    如果说业务分析师要基于数据回答问题,那么在当今时代选择一个重要的工具,这个工具应该是什么?

    BI佐罗
  • 微信搜索新发现:iPhone 内存不足看这里!

    还一直坚持着小内存的小伙伴,你的 iPhone 是不是每天都在提醒你内存不足,但你又无能为力呢?真是苦了你们这些小仙男、小仙女了... ? 那哎妹今天不搞事,只...

    企鹅号小编
  • 如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。

    这次的文章还是绕回了我写的第三篇原创文章《有的线程它死了,于是它变成一道面试题》中留下的几个问题:

    cxuan
  • 求解析,为什么差距这么大,难道就是因为一叶障目不见泰山了吗~~~

    WolframChina
  • 如何从零开始学习软件测试

    很多朋友想要入行软件测试,但是都不知道该怎么学。 抽个时间简单的给大家说下,对于0基础的朋友,应该怎么去学习软件测试。 学习软件测试有2条路可以选。 最省事的当...

    企鹅号小编
  • 讲几个关于程序员笑话!

    IT架构圈
  • 如何给女朋友解释什么是Linux的五种IO模型?

    周日午后,刚刚放下手里的电话,正在给刚刚的面试者写评价。刚刚写到『对Linux的基本IO模型理解不深』这句的时候,女朋友突然出现。

    Java团长
  • Java小白翻身教程-链表结构与编译大法(1)

    咳咳,我是小白,没错,主线剧情又回来了。现在我遇到麻烦了,老板要我设计一个类,可以用来保存多个客户的资料。

    剽悍一小兔
  • 区块链?黑人问号?NO.1

    # 区块链的大白话 我是小蕉。 从前的从前啊,有一个桃花屯,屯里住着一群跟小布小青这样的种田青年。屯里出现了这么一件事,每年的收成都是几千斤几千斤这样,每次出去...

    大蕉
  • Java视频分享

    互联网老辛
  • 淘宝面试回来,想对程序员们谈谈

    因为我是一个不管做什么事情都喜欢进行总结的一个人。所以对于在上周去淘宝面试的经历,现在面试回来总结,我想对所有程序员们谈谈。

    烂猪皮
  • 淘宝面试回来,想对程序员们谈谈

    因为我是一个不管做什么事情都喜欢进行总结的一个人。所以对于在上周去淘宝面试的经历,现在面试回来总结,我想对所有程序员们谈谈。

    AI乔治
  • 尽管Java8时间库有所进步,但总感觉Low了点,有同感吗?

    最近有网友表示,在自己公司和项目中,实际上时间库应用不算太多,用到也是非常简单的一些应用场景,一般情况下连Java8的时间库都很少用到,今天为了写个时间查询,把...

    业余草
  • 用区块链解决桃花屯的粮食问题No.49

    我是小蕉。 从前的从前啊,有一个桃花屯,屯里住着一群跟小布小青这样的种田青年。屯里出现了这么一件事,每年的收成都是几千斤几千斤这样,每次出去卖一趟粮食,我了个乖...

    大蕉

扫码关注云+社区

领取腾讯云代金券