java io基础知识总结

本文详细介绍了Java中的IO流,包括输入流和输出流,字节流与字符流的区别,以及FileInputStream和FileOutputStream的使用。还讨论了文件拷贝、字符编码、乱码问题以及如何使用缓冲流提高性能。此外,提到了对象的序列化和反序列化过程。
摘要由CSDN通过智能技术生成

io是input 和output,输入和输出,在java中分为输入流和输出流

也可以根据数据的处理方式分为字节流,字符流

java的io流的40 多个类,是从以下的四个抽象类基类中抽象出来的

inputstream /reader,前者字节输入,后者字符输入

outputstream/writer

inputstream 字节输入流:用于从源头通常是文件 读取数据到内存中,是所有字节输入流的父类

read():返回输入流中的下一个字节数据

read(byte b[]) 从输入流中读取一些字节存储到数组b中,如果数组长度为0 则不读取,返回-1,如果有,则最多读取b.length,返回读取的字节数

Fileoutputstream:

字节输出流的细节:参数可以是字符串表示的路径或者file对象,如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的,如果文件已经存在会清空文件

写数据:write 方法的参数是整数,实际上写到本地文件中的整数是ascii上对应的字符

释放资源,每次使用完都要释放

字节输出流写出数据的三种方式: 一次写一个数据 write(int b),write(byte[]b) ,write (byte []b ,int off,int len)

换行写怎么写:

在俩个write中间写一个换行符,windows操作系统\r\n 换行 linux \n ios \r

不想清空原来的怎么写,续写:打开续写功能,在new创建的时候写上true,默认是false

fileinputstream:

read 表述读取数据,读取一次数据就移动一次指针

创建对象:如果文件不存在 会直接报错,因为数据很重要

读取数据:如果读不到会返回-1,一次读一个字节,读出来的是ascii上对应的数字,读到空格会对应ascii上的32,读取到-1的时候会分开先读负数号

释放资源

循环读取:循环的条件是不为-1 ,要用一个数据对象去接受,因为read 读取一次就移动一次指针

public class fileinputstream {
    public static void main(String[] args) throws IOException {
        FileInputStream fi = new FileInputStream("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\q");
        int  a;
        while ((a = fi.read()) !=-1){
            System.out.println((char)a);
        }
    }
}

文件拷贝:边读边写

public class demo1 {
    public static void main(String[] args) throws IOException {
         FileInputStream fio= new FileInputStream("C:\\Users\\77918\\Desktop\\file.txt");
        FileOutputStream fos = new FileOutputStream ("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\file.txt");
        int b;
        while ((b=fio.read())!=-1){
            fos.write((char)b);
        }
        fio.close();
        fos.close();
    }
}

文件拷贝的弊端: 一次读一个数据,缓慢

Fileinputstream :一次读多个字节,read(byte [] buffer )一次读一个字节数组数据,1024 的整数倍,会尽可能把数组读满

IO流中不同的jdk版本捕获异常:jdk7 java提出一个接口 可以在特定情况下,可以自动释放资源

字节流读取文件时,文件中不要有中文:

字符集详解:

计算机的存储规则:

以二进制来存储

ascii 存储英文 一个字节(一个字节八位,编码,存储,不够补0)

gbk:字符集,ansi,windows默认 ansi,完全兼容ascii,中文俩个字节,高位字节二进制一定是以1 开头,转成十进制一定是负数,为了和英文区分开,英文一个 第一位是0

unicode:国际标准字符集

utf-16:2-4个字节保存

utf-32:固定四个字节baocun

utf-8:用1-4个字节保存 中文三个字节表示,英文一个字节表示,不是字符集是一种编码方式

为什么会有乱码:

原因一:读取数据时未读完整个汉字,字节流一次只能读一个字节,原因二:编码和解码的方式不统一

扩展: 字节流读取会乱码,但是拷贝不会乱码的原因,拷贝时把字节拷贝过去,数据没有丢失,读取时也是保持一致所以不会乱码

java中编码和解码的方法:

字符流:底层字节流,字节流+字符集,输入流一次读一个字节,遇到中文时一次读多个字节

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

使用场景 一般用于纯文本文件进行读写操作

Reader:字符输入流 filereader 有参read(),空参reader()

writer:字符输出流 filewriter

细节:读到文件末尾,read返回-1,需要资源关闭

read()细节:读取后会进行解码转成十进制,十进制对应的时字符集里的数字

字符流原理解析:

创建字符输入流对象:底层关联文件,创建缓冲区

读取数据:

判断缓冲区是否有数据可以读取,有则直接读取,无则读取文件,每次尽可能装满缓冲区,如果文件中也没有数据,则返回-1,

空参的read()方法,读取,解码成十进制 返回

有参的read()方法:读取字节,转码,强转

flush 和close

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

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

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

练习1 拷贝文件

public class demo2 {
    //拷贝文件夹
    //参数一:数据源
    //参数二:目的地
    public static void main(String[] args) throws IOException {


        //
        //1.创建对象表示数据源
        File src = new File("C:\\Users\\77918\\Desktop\\task");
        //创建目的源对象
        File dest = new File("C:\\Users\\77918\\Desktop\\task\\bb");
        //调用方法开始拷贝
        copydir (src,dest);


    }
// 作用 拷贝文件夹
    private static void copydir(File src, File dest) throws IOException {
        dest.mkdirs();//以防没有这个文件夹
        // 递归: 进入数据源,遍历数组,文件和文件夹处理的判断,文件拷贝,文件夹递归
         File []files =src.listFiles();
         //遍历数组
        for (File file :files){
            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();
                }
            else{
                //判断文件夹,递归
                copydir(file,new File(dest,file.getName()));

            }

        }

    }

}

练习2:文件加密 为了保证文件的安全性,需要对原始文件进行加密存储,使用时在对其进行解密处理

加密原理:

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

解密原理:

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

public class demo3 {

    public static void main(String[] args) throws IOException {
        File src= new File("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\file.txt");
        File dest =new File("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\file1.txt");
        FileInputStream fis= new FileInputStream(src);
        FileOutputStream fos=new FileOutputStream(dest);
        int len ;
        while ((len=fis.read())!= -1){
             fos.write(len^2);
        }
        fos.close();
        fis.close();

    }


}

加密

源文件

解密

修改文件中的数据排序

public class demo4 {
    public static void main(String[] args) throws IOException {
        FileReader fr=new FileReader("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\b");
        StringBuilder sb=new StringBuilder();
        int ch;
        while ((ch=fr.read())!=-1) {
            sb.append((char)ch);
        }
        fr.close();
        System.out.println(sb);


        String str=sb.toString();
        String[]arrstr=str.split("-");
        ArrayList<Integer> list =new ArrayList<>();
        for (String s:arrstr){
            int i = Integer.parseInt(s);//parseInt() 方法用于将字符串参数作为有符号的十进制整数进行解析。如果方法有两个参数, 使用第二个参数指定的基数,将字符串参数解析为有符号的整数。
            list.add(i);
        }
        Collections.sort(list);
        System.out.println(list);

        FileWriter fw= new FileWriter("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\b");
        for (int i =0;i<list.size();i++){
            if(i==(list.size()-1)){
                fw.write(list.get(i)+"");
            }
            else{
                fw.write(list.get(i)+"-");
            }
        }
        fw.close();
    }


}

方法二

public class demo5 {
    public static void main(String[] args) throws IOException {
        FileReader fr=new FileReader("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\b");
        StringBuilder sb=new StringBuilder();
        int ch;
        while ((ch=fr.read())!=-1) {
            sb.append((char)ch);
        }
        fr.close();
        System.out.println(sb);

        // 排序
        Integer[] arr=Arrays.stream(sb.toString().split("-")).map(Integer::parseInt)
                .sorted().toArray(Integer[]::new);
        //写出
        FileWriter fe=new FileWriter("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\b");

        String s =Arrays.toString(arr).replace(", ","-");
        String re= s.substring(1,s.length()-1);
        System.out.println(re);
        fe.write(re);
        fe.close();
    }
}

字节缓冲流

基本流

高级流 基本流+缓冲流

字节缓冲流:BufferedInputStream BufferedOutputStream

字符缓冲流: BufferedReader BufferedWriter

原理:底层自带了8K缓冲区提高性能,可以显著提高字节流的读写功能,对字符流提升不明显但是字符流

创建对象时需要关联基本流

字节缓冲流 一次读取一个字节和一次读取多个字节:

字符缓冲流: 把基本流变成高级流,有readLine()方法

newLine 跨平台换行(输出流)

续写功能 开启续写功能,但是bufferedwriter 没有这个功能,需要写在关联的filewriter

转换流

属于字符流,高级流,包装基本流,inputstreamreader outputstreamreader

可以把字节流转换为字符流,filewriter filereader可以通过 charset.forName指定字符编码

序列化流:

高级流 把基本流包装成高级流

objectInputStream ObjectOutputStream 反序列化流 序列化流

序列化流: 把java对象写到本地文件中,通过此流读取出来

反序列化流:writeObject 方法

小细节: 需要Javabean 类实现 一个serializable接口,这个接口没有抽象方法标记类接口,实现这个接口,就表示类可以被序列化

public class demo6 {

    public static void main(String[] args) throws IOException {

        Student s= new Student("z",12);

        ObjectOutputStream oop= new ObjectOutputStream(new FileOutputStream("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\b"));

        oop.writeObject(s);

        oop.close();

    }
}
public class Student implements Serializable {

    String name;
    int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

反序列化流:

readObject方法

把序列化到本地文件中的对象读取到程序中来

public class demo7 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        ObjectInputStream oop= new ObjectInputStream(new FileInputStream("C:\\Users\\77918\\Documents\\temp\\timacatdemo\\src\\main\\resources\\b"));

     Object  oo= oop.readObject();

        System.out.println(oo);

        oop.close();
    }
}

细节:序列化流写到对象时需要实现一个接口,否则会出现异常,序列化流写到文件中的数据是不能更改的,一旦修改就无法读取回来,序列化对象后,修改了 javabean类 再次反序列化,会抛出 invalidclassexception异常,解决方法给Javabean 加上seriversionUID b版本号

不想被序列化的可以加上transient关键字修饰

打印流:只有输出流,高级流 ;只有打印不能读,原样写出,特有的写出方法,可以自动刷新自动换行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,作为文本AI助手,我无法绘制思维导图。但是,我可以为您提供一个简要的java IO流知识点总结Java IO流是Java中用于处理输入和输出的机制。它提供了一种有效的方式来读取和写入数据,以及与文件、网络和其他设备进行交互。 Java IO流包括字节流和字符流两种类型。字节流以字节为单位进行操作,适用于处理二进制数据。而字符流以字符为单位进行操作,适用于处理文本数据。 常用的字节流包括InputStream和OutputStream类,用于读取和写入字节数据。常用的字符流包括Reader和Writer类,用于读取和写入字符数据。可以通过使用字节流和字符流的组合来实现不同类型数据的读写操作。 在Java IO流中,还有一些特殊的流,如缓冲流、转换流、对象流等。缓冲流提供了缓冲区来提高IO性能。转换流用于处理字符编码和解码。对象流用于对Java对象进行读写操作。 此外,Java IO流还包括一些常用的类和方法,如File类用于处理文件和目录,RandomAccessFile类用于对文件进行随机访问,FileInputStream和FileOutputStream类用于读写文件等。 通过组合和使用不同类型的流和类,您可以实现各种复杂的IO操作,如读写文件、网络通信、序列化对象等。 希望这个简要总结对您有所帮助。如果您有任何更具体的问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [万字长文+思维导图帮你梳理 Java IO 流,还学不会你来打我(值得收藏)](https://blog.csdn.net/a1405/article/details/116766237)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值