菜鸟之路Day15一一IO流(一)

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: - **初识IO流**:解释了什么是IO流及其作用,按方向和文件类型分类。- **字节输出流**:详细讲解了`FileOutputStream`的用法,包括创建对象、写数据和释放资源。- **字节输入流**:介绍了`FileInputStream`的基本操作,如读取数据和文件拷贝。- **异常处理**:简要说明了如何处理IO异常。- **字符集与乱码问题**:解释了字符集的概念及常见乱码原因。- **字符输入/输出流**:介绍了`FileReader`和`FileWriter`的使用场景和步骤。

菜鸟之路Day15一一IO流(一)

作者:blue

时间:2025.2.8

0.概述

文章内容,学习自黑马程序员BV1yW4y1Y7Ms

1.初识IO流

1.1.什么是IO流?

答:存储和读取数据的解决方案

1.2.IO流的作用

答:用于读写数据(本地文件,网络)

1.3.IO流的分类

按流的方向分

image-20250208102038959.png

按操作文件的类型分
image-20250208102146264.png

2.IO流的体系结构

image-20250208102736771.png

3.字节输出流的基本用法

FileOutputStream :操作本地文件的字节输出流,可以把程序中的数据写到本地文件中

书写步骤:

①创建字节输出流对象

​ 细节1:参数是字符串表示的路径或者File对象都是可以的

​ 细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的

​ 细节3:如果文件已经存在,则会清空文件

②写数据

​ 细节:write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符

③释放资源

​ 细节:每次使用完流之后都要释放资源

package IOStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamDemo1 {
   
    public static void main(String[] args) throws IOException {
   
        FileOutputStream fos = new FileOutputStream("src\\IOStream\\a.txt");//①创建字节输出流对象
        fos.write(97);//②写数据
        fos.close();//③释放资源
    }
}

写出数据的三种方式

public class FileOutputStreamDemo2 {
   
    public static void main(String[] args) throws IOException {
   
        /*
        * void write(int b) 一次写一个字节数据
        * void write(byte[] b) 一次写一个字节数组数据
        *
        * void write(byte[] b,int off,int len) 一次写一个字节数组的部分数据
        * 参数一:数组
        * 参数二:起始索引 0
        * 参数三:个数 3
        * */
        FileOutputStream fos = new FileOutputStream("src\\IOStream\\a.txt");

        byte[] b = {
   97,98,99,100,101};
        fos.write(b,1,2);
    }
}

换行和续写

public class FileOutputStreamDemo3 {
   
    public static void main(String[] args) throws IOException {
   
        /*
        * 换行符:
        *   windows:\r\n
        *   Linux:\n
        *   Mac:\r
        * 续写:
        *   打开续写开关即可,即创建对象的第二个参数
        *   默认是false表示关闭,创建对象会清空文件
        *   传递true,表示打开续写,此时创建对象不会清空文件
        * */

        FileOutputStream fos = new FileOutputStream("src\\IOStream\\a.txt",true);
        String str1 = "kcbdkdvkdkjxkjdkj";
        String str2 = "\r\n";
        String str3 = "666";
        byte[] b1 = str1.getBytes();
        byte[] b2 = str2.getBytes();
        byte[] b3 = str3.getBytes();
        fos.write(b1);
        fos.write(b2);
        fos.write(b3);
    }
}

4.字节输入流的基本用法

FileInputStream:操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来

书写步骤:

①创建字节输入流对象

​ 细节1:如果文件不存在,就直接报错

②读数据

​ 细节1:一次读一个字节,读出来的数据在ASCII上对应的数字

​ 细节2:读到文件末尾了,read方法返回-1

③释放资源

​ 细节:每次使用完流之后都要释放资源

public class FileInputStreamDemo1 {
   
    public static void main(String[] args) throws IOException {
   
        FileInputStream fis = new FileInputStream("src\\IOStream\\a.txt");
        int ans = fis.read();
        while(ans!=-1){
   
            System.out.print((char)ans);
            ans = fis.read();
        }
        fis.close();//释放资源
    }
}

文件拷贝的基本代码

思想:边读边写

public class FileInputStreamDemo2 {
   
    public static void main(String[] args) throws IOException {
   
        //1.创建对象
        FileInputStream fis = new FileInputStream("C:\\Users\\zhangtenlan\\Desktop\\abc.txt");
        FileOutputStream fos = new FileOutputStream("src\\IOStream\\ans.txt");

        //2.拷贝
        //核心思想:边读边写
        int b;
        while((b=fis.read())!=-1)
        {
   
            fos.write(b);
        }
        //3.释放资源
        //规则:先开的最后关闭
        fos.close();
        fis.close();
    }
}

以上方法在拷贝大文件的时候速度非常的慢,原因就在于,每次只能读取一个字节的数据,我们可以用read方法的一个重载来一次性读取多个数据。

public int read(byte[] buffer)  //一次读一个字节数组数据
//注意:一次读一个字节数组的数据,每次读取会尽可能把数组装满
//长度尽量设置为1024的整数倍,不要太大,像1024*1024*5

例子:

public class FileInputStreamDemo3 {
   
    public static void main(String[] args) throws IOException {
   
        FileInputStream fis = new FileInputStream("src\\IOStream\\ans.txt");
        byte[] b = new byte[2];
        int len;
        while((len=fis.read(b))!=-1){
    //当读到的长度为-1时代表读完了
            System.out.print(new String(b,0,len));
        }
        fis.close();
    }
}

拷贝大文件的写法

public class FileInputStreamDemocratic {
   
    public static void main(String[] args) throws IOException {
   
        long start = System.currentTimeMillis();//记录开始时间

        //1.创建对象
        FileInputStream fis = new FileInputStream("大文件");
        FileOutputStream fos = new FileOutputStream("目标位置");
        //2.拷贝
        int len;
        byte[] bytes = new byte[1024*1024*5];
        while((len=fis.read(bytes))!=-1){
   
            fos.write(bytes,0,len);
        }
        //3.释放资源
        fos.close();
        fis.close();

        long end = System.currentTimeMillis();//记录结束时间

        System.out.println(end-start);//看看程序运行花了多少时间
    }
}

5.异常处理(了解即可)

try{
   

}catch(IOException e){
   

}finally{
   
    //finally中代码一定执行,除非JVM退出
    //所以释放资源的代码写到这里再合适不过
}

6.字符集

1.在计算机中,任意数据都是以二进制的形式来存储的

2.计算机中最小的存储单元是一个字节

3.ASCII字符集中,一个英文占一个字节

4.简体中文版Windows,默认使用GBK字符集

5.GBK字符集完全兼容ASCII字符集

注意:一个英文占一个字节,二进制第一位是0

一个中文占两个字节,二进制高位字节的第一位是1

6.Unicode字符集的UTF-8编码格式

​ 注意:一个英文占一个字节,二进制第一位是0,转成十进制是正数

​ 一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数

为什么会有乱码?

原因1:读取数据时未读完整个汉字

原因2:编码和解码时的方式不统一

Java中的解码和编码:

public class FileInputStreamDemo5 {
   
    public static void main(String[] args) throws UnsupportedEncodingException {
   
        /*
        * java中的编码方法
        *   public byte[] getBytes() 使用默认方式进行编码UTF-8
        *   public byte[] getBytes(String charsetName) 使用指定方式进行编码
        *
        * java中的解码方法
        *   String(byte[] bytes) 使用默认方式进行解码UTF-8
        *   String(byte[] bytes,String charsetName) 使用指定方式进行解码
        * */

        String str = "你好";
        byte[] res1 = str.getBytes();
        System.out.println(Arrays.toString(res1));

        System.out.println("=========================================================================");

        byte[] res2 = str.getBytes("GBK");
        System.out.println(Arrays.toString(res2));

        System.out.println("=========================================================================");

        String ans1 = new String(res1);
        System.out.println(ans1);

        System.out.println("=========================================================================");

        String ans2 = new String(res2,"GBK");
        System.out.println(ans2);
    }
}

7.字符输入流

image-20250216154830502.png

字符流

​ 字符流 = 字节流+字符集

特点

​ 输入流:一次读一个字节,遇到中文时,一次读多个字节(所以适合处理中文)

​ 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

使用场景

​ 对于纯文本文件进行读写操作

书写步骤

​ ①创建字符输入流对象

​ ②读取数据

​ 注意:细节1:按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数

细节2:读到文件末尾了,read方法返回-1

​ ③释放资源

7.1FileReader

public class IOTestOne {
   
    public static void main(String[] args) throws IOException {
   
        /*
        * 第一步:创建对象
        * public FileReader(File file)  创建字符输入流关联本地文件
        * public FileReader(String pathname)
        *
        * 第二步:读取数据
        * public int read() 读取数据,读到末尾返回-1
        * public int read(char[] buffer) 读取多个数据,读到末尾返回-1
        *
        * 第三步:释放资源
        * public void close 释放资源
        * */
        FileReader fr = new FileReader("src\\IOTest\\a.txt");
        int ch;
        while((ch=fr.read())!=-1){
   
            System.out.print((char)ch);
        }
        fr.close();
    }
}

/*
   有参的read
   FileReader fr = new FileReader("src\\IOTest\\a.txt");
   char[] chars = new char[2];
   int len;
   while((len=fr.read(chars))!=-1){//有参read返回值是
      System.out.print(new String(chars,0,len));
   }
   r.close();
*/

7.2FileWriter

①创建字符输出流对象

​ 细节1:参数是字符串表示的路径或者是File对象都可以

​ 细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的

​ 细节3:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关

②写数据

​ 细节:如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符

③释放资源

​ 细节:每次使用完流之后都要释放资源

public class IOTestTwo {
   
    public static void main(String[] args) {
   
        /*
        * 第一步:创建对象
        *   public FileWriter(File file)
        *   public FileWriter(String pathname)
        *   public FileWriter(File file,boolean append) 续写开关
        *   public FileWriter(String pathname,boolean append)
        *
        * 第二步:读取数据
        *   void write(int c)
        *   void write(String str)
        *   void write(String str,int off,int len)
        *   void write(char[] cbuf)
        *   void write(char[] cbuf,int off,int len)
        *
        * 第三步:释放资源
        *   public void close() 
        * */
    }
}

8.IO流综合练习

字节流和字符流的使用场景

​ 字节流:拷贝任意类型的文件

​ 字符流:读取纯文本文件中的数据,往纯文本文件中写出数据

8.1练习一

拷贝文件夹,考虑子文件夹

public class Test1 {
   
    public static void main(String[] args) throws IOException {
   
        File src = new File("C:\\Users\\zhangtenlan\\Desktop\\src");//数据源
        File dest = new File("C:\\Users\\zhangtenlan\\Desktop\\dest");//目的地

        copydir(src,dest);
    }

    private static void copydir(File src, File dest) throws IOException {
   
        dest.mkdirs();
        //1.进入数据源
        File[] arr = src.listFiles();
        //2.遍历数据源
        for(File file:arr){
   
            //3.如果是文件,则拷贝
            if(file.isFile()) {
   
                FileInputStream fis = new FileInputStream(file);
                FileOutputStream fos = new FileOutputStream(new File(dest,file.getName()));
                byte[] bytes = new byte[1024];
                int len;
                //边读边写
                while((len= fis.read(bytes))!=-1){
   
                    fos.write(bytes,0,len);
                }
                fos.close();
                fis.close();
            }
            //4.如果是文件夹,则递归
            else {
   
                copydir(file,new File(dest,file.getName()));
            }
        }
    }
}

8.2练习二

文件加密

为了保证文件的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。

加密原理:

​ 对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新文件中

解密原理:

​ 读取加密之后的文件,按照加密规则反向操作,变成原始文件

//完成这个功能,我们可以利用异或的原理
//加密,我们可以令每个字节都异或上一个数字
public class Test2 {
   
    public static void main(String[] args) throws IOException {
   
        FileInputStream fis = new FileInputStream("src\\yuan.png");
        FileOutputStream fos = new FileOutputStream("src\\jiami");
        int b;
        while((b=fis.read())!=-1){
   
            fos.write(b^5);
        }
        fos.close();
        fis.close();
    }
}
//解密,我们取原来加密过的图片,再次异或上这个数字
public class Test2 {
   
    public static void main(String[] args) throws IOException {
   
        FileInputStream fis = new FileInputStream("src\\jiami");
        FileOutputStream fos = new FileOutputStream("src\\jiemi.png");
        int b;
        while((b=fis.read())!=-1){
   
            fos.write(b^5);
        }
        fos.close();
        fis.close();
    }
}

8.3练习三

文本文件中有以下数据:2-1-9-4-7-8

将文本中的数据进行排序,变成以下数据:1-2-4-7-8-9

public class Test3 {
   
    public static void main(String[] args) throws IOException {
   
        //1.读取数据
        //纯文本文件,可以使用字符流来操作
        FileReader fr = new FileReader("src\\a.txt");
        StringBuilder sb = new StringBuilder();
        int b;
        while((b=fr.read())!=-1){
   
            sb.append((char)b);
        }
        fr.close();

        //2.排序
        ArrayList<Integer> list = new ArrayList<>();
        String[] arr = sb.toString().split("-");//分离-
        for (String s : arr) {
   //将数据转为整数类型,为排序做准备
            list.add(Integer.parseInt(s));
        }
        Arrays.sort(arr);//排序

        //3.写回
        FileWriter fw = new FileWriter("src\\b.txt");
        for (int i = 0; i < arr.length; i++) {
   
            if(i==arr.length-1) {
   
                fw.write(arr[i]+"");
            }
            else {
   
                fw.write(arr[i]+"-");
            }
        }
        fw.close();
    }
}
目录
相关文章
|
NoSQL Java 关系型数据库
23年春招最全1575道Java 面试题目,一份通往阿里的面试指南
疫情过后,不少人已经蓄势待发,信心满满地准备投递简历,到处面试,在不同的 Offer 之中择优而栖。 与此同时,也有人会悔恨自己这半年进步不大,每天噼里啪啦敲代码,但面对那些不能再熟悉的 Java 面试题时,只是感觉似曾相识,却怎么也回答不到点子上,比 HashMap 的工作原理,或 volatile 的使用场景等。 究其原因,主要有两方面: 第一,“知其然不知其所以然”。开发了很多业务应用,却从未缕清技术选择背后的逻辑。所以,领导不放心把有一定深度的任务交给他们,因为不知道其成长潜力有多大。 第二,知识碎片化,不成系统。面试时,无法完整、清晰地描述自己所开发的系统,或使用的技术。所以
|
NoSQL Java 关系型数据库
23年秋招最全1575道Java 面试题目,一份通往阿里的面试指南
金九银十不少人已经蓄势待发,信心满满地准备投递简历,到处面试,在不同的 Offer 之中择优而栖。 与此同时,也有人会悔恨自己这半年进步不大,每天噼里啪啦敲代码,但面对那些不能再熟悉的 Java 面试题时,只是感觉似曾相识,却怎么也回答不到点子上,比 HashMap 的工作原理,或 volatile 的使用场景等。 究其原因,主要有两方面: 第一,“知其然不知其所以然”。开发了很多业务应用,却从未缕清技术选择背后的逻辑。所以,领导不放心把有一定深度的任务交给他们,因为不知道其成长潜力有多大。 第二,知识碎片化,不成系统。面试时,无法完整、清晰地描述自己所开发的系统,或使用的技术。所以,
176 0
|
22天前
|
JSON Java 程序员
菜鸟之路Day17一一IO流(三)
本文主要介绍了Java中的打印流、压缩/解压缩流以及Commons-io和Hutool工具包的使用。打印流包括字节打印流(PrintStream)和字符打印流(PrintWriter),支持数据原样写出、自动刷新与换行。压缩/解压缩流通过ZipInputStream和ZipOutputStream实现文件和文件夹的压缩与解压。Commons-io和Hutool工具包提供了高效的IO操作方法,简化了文件复制、删除等常见任务。文中还展示了System.out.println()作为打印流的应用示例。
38 2
|
23天前
|
小程序 Java 程序员
菜鸟之路Day16一一IO流(二)
1. **缓冲流**:介绍了字节缓冲流和字符缓冲流的种类及其性能提升原理,重点讲解了`BufferedReader`和`BufferedWriter`的特有方法。 2. **转换流**:讲解了如何使用`InputStreamReader`和`OutputStreamWriter`实现字符集编码转换,避免乱码问题。 3. **对象序列化与反序列化**:详细说明了如何将Java对象保存到文件中及从文件中读取对象,并讨论了相关细节,如`Serializable`接口、`serialVersionUID`和`transient`关键字的使用。
47 1
|
19天前
|
存储 数据采集 算法
菜鸟之路Day18一一IO流综合练习
本文通过Java代码实现了一个姓名生成器,从指定网页爬取姓氏、男孩名和女孩名数据,处理后生成随机组合的姓名,并附加性别和年龄信息,最终将结果写入文件。代码涵盖了网页爬虫、正则表达式匹配、随机化处理等技术点。此外,还使用了hutool包简化了部分操作。文章进一步扩展到随机点名器的应用场景,包括简单随机点名、按概率点名、带权重的随机点名等多种变体,满足不同需求的测试场景。
22 2
|
13天前
|
安全 Java 程序员
菜鸟之路Day20一一多线程(二)
### 菜鸟之路Day20——多线程(二) 作者:blue 日期:2025.2.27 本文通过多个练习详细介绍了Java多线程的应用,包括买票、送礼、抢红包等场景的模拟。重点讲解了`Thread`类和`Runnable`接口的使用,以及如何利用锁机制确保线程安全。此外,还探讨了线程池的概念及其优势,并提供了创建和配置线程池的具体示例。最后,讨论了如何根据CPU并行数合理设置线程池大小,以优化性能。 通过这些练习,读者可以深入理解多线程编程的核心概念和实际应用技巧。
40 1
|
11天前
|
网络协议 Java
菜鸟之路Day21一一网络编程
《菜鸟之路 Day21:网络编程(一)》由 blue 于 2025 年 3 月 2 日发布。本文介绍了网络编程的基础知识,包括 CS/BS 架构的区别、网络编程三要素(IP、端口号、协议),并详细讲解了 InetAddress 类的使用。接着通过 UDP 和 TCP 协议演示了数据发送与接收的过程,涵盖单播、组播和广播通信方式。最后,通过多个综合练习(如多发多收、文件上传等)巩固所学内容,并引入多线程和线程池优化服务器性能。
35 2
|
16天前
|
Java 程序员 调度
菜鸟之路Day19一一多线程(一)
什么是多线程:进程与线程的区别,线程是操作系统调度的最小单位,多线程可提高效率。 并发与并行:并发是单个CPU上交替执行多个指令,并行是多个CPU同时执行。 多线程的实现方式: 线程常用方法:如`getName()`、`setName()`、`sleep()`等。 线程生命周期:从新建到终止的六个状态。 线程安全问题:通过同步代码块和方法解决共享数据的竞争问题。 Lock锁:手动控制锁的获取与释放。 死锁:产生原因及必要条件。 等待唤醒机制:生产者消费者模型及其优化。 多线程六种状态:新建、就绪、阻塞、等待、计时等待和结束。 通过实例代码详细讲解了多线程的应用场景和解决方案。
20 2
|
8月前
|
Java 数据库连接 开发者
从零到一:JAVA反射技术的“逆袭”之路
【7月更文挑战第1天】Java反射技术,从高级特性走向普及,核心是Class类,用于运行时检查和操作类信息。在Spring等框架中,反射实现DI和AOP,提升灵活性。动态代理通过Proxy和InvocationHandler实现方法拦截。反射现已成为Java不可或缺的工具,未来潜力无限。
30 0
|
10月前
|
消息中间件 分布式计算 算法
疫情在家“闭关修炼”,读完这些Java技术栈,愿金三银四过五斩六
现在已值2月中旬,但大部分企业仍然还没有开工,由于疫情,许多人还在家里宅着或是远程办公,实际上,对于有跳槽打算的人来说,现在正是“闭关修炼”的好时机,但很多人不知道从何开始学习,也正为即将到来的金三银四发愁!今天,小编就要分享今年的面试闯关攻略,读完这些Java技术栈,让你金三银四过五斩六。