Java黑马程序员_IO

IO的基础知识

  • IO流是什么
    • 读取和存储数据的解决方案

IO流的方向

1701072258506.png

操作文件类型

image.png
字节流:操作所有文件
字符流:操作txt纯文本文件:txt,md

IO学习

字节流

输出数据

public static void main(String[] args) throws IOException {  
    //1. 输出文件  
    FileOutputStream f = new FileOutputStream("E://05输出//123.txt");  
  
    //2. 写入  
    f.write(97);  //output:a
  
    //3. 关闭通道  
    f.close();  
}
  1. 创建字节输出流对象
    1. 细节1:字符串路径或者File对象都可以
    2. 细节2:如果文件不存在会创建一个新的文件,要保证父路径存在
    3. 细节3:如果文件已经存在。会被清空重写
  2. 写入数据
    1. 写入的数字是对应ASCII码
  3. 释放资源
    1. 解除了资源的占用
Write 的使用方法

image.png

字节写入的三种方式
  1. 直接写入f.write(97)
  2. 通过字节数组写入
byte[] bytes = {97, 98, 99, 100};  
f.write(bytes);
  1. 写入字节数组的一部分
/*
off:开始的位置
len:个数
*/
byte[] bytes = {97, 98, 99, 100};  
f.write(bytes,1,2);
换行和续写

原理:

  • 使用一个String字符串,使用其getbytes()得到字节数组,然后再输入到f.write()
    换行:
String wrap = "\r\n";
byte[] bytes1 = wrap.getBytes();
fos.write(bytes1);

续写:当你使用FileOutputStream的时候,第二个参数设置为true即可以续写

FileOutputStream fos = new FileOutputStream("E://05输出//123.txt",true);

输入数据

  • 因为是字节,所以输入到java只有一个字符
int b = f.read();
sout((char)b); ->转换为字符
如何在java上连续显示字符
public static void main(String[] args) throws IOException {  
    FileInputStream fis = new FileInputStream("D:\\03存储\\BaiduSyncdisk\\study\\java\\String\\String001\\a.txt");  
    int b;  
    while((b = fis.read()) != -1){  
        System.out.print((char)b);  
    }  
    fis.close();  
}

拷贝数据

第一种方案:边写边读

public static void main(String[] args) throws IOException {  
    FileInputStream fis = new FileInputStream("D:\\03存储\\onedrive\\桌面\\123.txt"); //读  
    FileOutputStream fos = new FileOutputStream("D:\\03存储\\onedrive\\桌面\\论文阅读\\321.txt");//写  
  
    int b;  
  
    while((b = fis.read()) != -1){  
        fos.write(b);  
    }  
    //哪一个方法先使用 就最后 关闭  
    fos.close();  
    fis.close();  
}

第二种方案:使用read读取的时候,创建一个数组固定接受字节 read(bytes)->一次性接受bytes个字节读取

public static void main(String[] args) throws IOException {  
    FileInputStream fis = new FileInputStream("D:\\03存储\\onedrive\\桌面\\123.txt"); //读  
    FileOutputStream fos = new FileOutputStream("D:\\03存储\\onedrive\\桌面\\论文阅读\\321.txt");//写  
  
    int b;  
    byte[] bytes = new byte[2];//使用数组读取 加快速度  
    while((b = fis.read(bytes)) != -1){  //当阅读到最后一个字符后会显示-1 即停止阅读
        String str = new String(bytes);  
        System.out.println(str);  
        fos.write(b);  
    }  
    //哪一个方法先使用 就最后 关闭  
    fos.close();  
    fis.close();  
}

小科普 如何获取一个程序的运行时间

//使用开始时间和结束时间
long start = System.currentTimeMills();
...
long end = System.currentTimeMills();
end - start


字符集详解

计算机存储规则

在计算机中,任意数据都是以二进制存储的
当存储英文,1个字节就够了
一般来说存储中文,需要 3 个字节,因为使用的都是 Unicode

ASCII字符集

image.png
image.png

GBK字符集

image.png

image.png

Unicode 万国码

UTF-8不是字符集 是一种编码方式
image.png
image.png

中文:3个字节
英文:1个字节

image.png

为什么会有乱码

  1. 读取数据的时候未完整读取整个汉字
  2. 编码和解码的方式不统一 (最重要的)

如何不产生乱码

1,不要用字节流读取文本文件
2,编码解码时使用同一个码表,同一个编码方式

为什么拷贝不会产生乱码

因为拷贝是一个字节一个字节进行输入的,不会产生损失

编码和解码代码实现

image.png

public static void main(String[] args) throws UnsupportedEncodingException {  
    //1. 编码  
    String str = "ai你哟";  
    byte[] bytes = str.getBytes();  
    System.out.println(Arrays.toString(bytes));  
    //2. 解码  
    String s = new String

bytes);  
    System.out.println(s);  
    //使用错误的编码方式  
    String s1 = new String(bytes, "GBK");  
    System.out.println(s1);  
  
    }

字符流

  • 字符流
    • 底层是字节流
      image.png

字符流的体系

READ

image.png
空参read读取

public static void main(String[] args) throws IOException {  
    FileReader fr = new FileReader("D:\\03存储\\onedrive\\桌面\\1.txt");  
  
    int ch;  
  
    while((ch = fr.read()) != -1){  
        System.out.print((char)ch);  
    }  
  
    fr.close();  
}

带参read读取

public static void main(String[] args) throws IOException {  
    FileReader fr = new FileReader("D:\\03存储\\onedrive\\桌面\\1.txt");  
    char[] chars = new char[2];  
  
    int len;  
  
    while((len = fr.read(chars)) != -1){  
        System.out.print(new String(chars,0,len));  
    }  
  
    fr.close();  
}

有参read和无参read有什么区别吗?

无参:读取数据->解码(转换为十进制)
有参:读取数据->解码->强制类型转换(得到的结果是字符的长度,读取的内容已经放置在后面的数组中)

FileWriter

构造方法

image.png

成员方法

image.png

public static void main(String[] args) throws IOException {  
    FileWriter fw = new FileWriter("D:\\03存储\\onedrive\\桌面\\1.txt",true);  
    char[] chars = {'为','什','么','显','示','错','误'};  
    fw.write(chars);  //可以数组也可以直接以String类型输入
    fw.close();  
}

tips

如果创建了一个相同名字的文件,则之前的文件内容会被清空

缓冲流

image.png

字节缓冲流

  • 自带 8192 的缓冲区
    代码如下所示:
    image.png

字节缓冲流提高效率的原理

image.png
因为在内存中处理速度非常快,所以无论是字节还是字节数组,传输数据都很快

字符缓冲流

对于字符流缓冲并不明显,但是有两个特有的方法

  1. BufferedReader:readLine()
    • 读取一行的数据
  2. BufferedWriter:newLine()
    • 写入的时候可以换一行写入

newLine():

image.png

readLine():

image.png

转换流

  • 字节流和字符流之间的桥梁
    作用:
  1. 指定字符集读写(已淘汰)
  2. 字节流想要使用字符流中的方法

可以读取不同类型的文本,比如GBK

public static void main(String[] args) throws IOException {  
    InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\03存储\\onedrive\\桌面\\gbkfile.txt"),"GBK");  
	  
    int ch;  
  
    while ((ch = isr.read()) != -1){  
        System.out.print((char)ch);  
    }  
  
  
}

一样的效果:

FileReader gbk = new FileReader("D:\\03存储\\onedrive\\桌面\\gbkfile.txt", Charset.forName("gbk"));

写出不同的编码方式
gbk读取,utf-8写入

public static void main(String[] args) throws IOException {  
    InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\01代码\\java001\\demodemo1\\a.txt"), "GBK");  
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\01代码\\java001\\demodemo1\\b.txt"), "UTF-8");  
    int ch;  
    while ((ch = isr.read()) != -1) {  
        osw.write(ch);  
    }  
    osw.close();  
    isr.close();  
}

序列化流 ObjectOutputStream

  • 把java中的对象写到本地文件
  • 使用对象输出流保存会出现NotSerializableException异常
    • 让javabean类实现Serializable接口
      代码:
public static void main(String[] args) throws IOException {  
    student s1 = new student("zhangsan", 23);  
  
    //创建序列化流  
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\03存储\\onedrive\\桌面\\新建 文本文档.txt"));  
  
  
    oos.writeObject(s1);  
  
    oos.close();  
}

反序列化流 ObjectInputStream

public static void main(String[] args) throws IOException, ClassNotFoundException {  
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\03存储\\onedrive\\桌面\\新建 文本文档.txt"));  
  
    Object object = (Student)ois.readObject();  
  
    System.out.println(object);  
    ois.close();  
}

序列化和反序列化流的细节

  • 当你修改代码类后,读取的之前类会出现错误
    • 解决方案:写一个相同的版本号
      需要在写完所有的类最后写版本号

设置Serializable

  1. 在设置中搜索Serializable
    1701785360328.png
//添加的版本号:
@Serial  
private static final long serialVersionUID = -5806700070317353843L;

如果在序列化的过程中不想把某个元素序列化怎么办?

添加一个瞬态关键字:transient,那么在读取的过程中这个address就是null,原来的值会被隐藏
image.png

如何解决添加多个对象后读取不知道有多少个对象?

解决问题:
添加多个对象后,把对象封装在集合中,然后读取时读取的是集合,这样全部就可以读取出来了。

image.png

image.png

序列化作业

输入对象到文件

public static void main(String[] args) throws IOException {  
    Student s1 = new Student("zhangsan", 23, "南京");  
    Student s2 = new Student("wangwu", 21, "北京");  
    Student s3 = new Student("lisi", 14, "东京");  
  
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\03存储\\onedrive\\桌面\\新建 文本文档.txt"));  
  
    ArrayList<Student> students = new ArrayList<>();  
  
    Collections.addAll(students,s1,s2,s3);  
  
    oos.writeObject(students);  
  
    oos.close();  
  
  
}

读取对象到java

public static void main(String[] args) throws IOException, ClassNotFoundException {  
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\03存储\\onedrive\\桌面\\新建 文本文档.txt"));  
  
    ArrayList<Student> ss = (ArrayList<Student>)ois.readObject();  
  
    ss.stream()  
            .forEach(s -> System.out.println(s));  
}

打印流

打印流只有输出流
特点:
image.png

字节打印流

image.png

示例:

public static void main(String[] args) throws FileNotFoundException {  
    PrintStream ps = new PrintStream(new FileOutputStream  
            ("D:\\03存储\\onedrive\\桌面\\新建 文本文档.txt"),true, Charset.forName("utf-8"));  
  
  
    ps.println("hello world");  
    ps.print(98);  
    ps.printf("哈哈哈");  
    ps.close();  
}

字符打印流

字符打印流有缓冲区,想要自动刷新需要开启
image.png

public static void main(String[] args) throws IOException {  
    PrintWriter pw = new PrintWriter(new FileWriter("E:\\01代码\\java001\\demodemo1\\a.txt"),true);  
  
    pw.println("hello worldhahahhahahhahhahah");  
  
  
    pw.print("hahahha");  
          
  
    pw.close();  
}

打印流什么时候使用

image.png

  • 字节打印流
  • 字符打印流
    特点:
  • 打印流不能操作数据源,只能操作目的地
    • 也就是说只能输入,无法修改
  • 字节打印流
    • 默认自动刷新
  • 字符打印流
    • 自动刷新需要开启

我们在日常输出的时候就会使用打印流进行输出

public static void main(String[] args) {  
    PrintStream out = System.out;  
  
    out.println("hello world");  
  
  
  //  out.close();  
  
    System.out  
            .println("helo world");  
}

解压缩流、压缩流

常用工具包

Commons-io

  1. 创建一个文件夹lib专门存放第三方java包
  2. 把jar赋值到lib文件夹
  3. 右键点击jar选择add as library
  4. 在类中导入包
    image.png

image.png

public static void main(String[] args) throws IOException {  
    File src = new File("E:\\01代码\\java001\\demodemo1\\a.txt");  
    File dest = new File("E:\\01代码\\java001\\demodemo1\\b.txt");  
    FileUtils.copyFile(src, dest);  
}

hutool

public static void main(String[] args) {  
    File file = FileUtil.file("D:\\test\\1.txt");  
    //touch 根据参数直接创建文件  
    System.out.println(FileUtil.touch(file));  
  
    ArrayList<String> list = new ArrayList<>();  
  
    Collections.addAll(list, "1", "2", "3","4","5","add");  
    //将集合写入文件  
    File file1 = FileUtil.writeLines(list, "D:\\test\\1.txt",  "utf-8");  
    //追加写入文件  
    FileUtil.appendLines(list, "D:\\test\\1.txt",  "utf-8");  
    System.out.println(file1);  
    //读取文件并且写入集合中  
    ArrayList<String> list1 = FileUtil.readLines("D:\\test\\1.txt", "utf-8", new ArrayList<String>());  
    List<String> list2 = FileUtil.readLines("D:\\test\\1.txt", "utf-8");  
  
    System.out.println(list2);  
  
}
  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值