JavaIO

IO概述

字符流回顾

代码案例:

public class CharStreamDemo {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("a.txt");

        //一次读取一个数组的数据
        char[] chs=new char[10];
        int len=-1;
        while((len=fr.read(chs))!=-1){
            System.out.print(new String(chs,0,len));
        }
        fr.close();

        System.out.println("==============");
        FileReader r = new FileReader("a.txt");    //这里若继续使用上面定义的fr 则输出的结果则是空
        //一次读取一个字符
        int ch;
        while((ch=r.read())!=-1){
            System.out.print((char)ch);
        }
        r.close();
    }
}

运行结果:

Hello World!
Hello World!
Hello World!
==============
Hello World!
Hello World!
Hello World!

数据的本质

数据在传输的过程中,一切数据(文本,图像,声音等)最终存储的均为一个个字节,即二进制数字。所以数据传输过程中,使用二进制数据可以完成任意数据的传输

我们想一个文件中存储一定的数据,如果使用文本方式打开,则会以文本的方式解释数据。如果以视频的方式打开则会以视频的方式解释数据。音频,可执行文件等都是如此。所以在文件传输过程中,我们要时刻明确,传输的始终是二进制数据。

字节输入流和字节输出流

字节输出流

输出流:OutputStream抽象类 FileOutputStream基本输出流

构造方法:
public FileOutputStream(String name) 创建输出流操作得分目标
public FileOutputStream(String name,boolean append) append为true时代表每次写入都向文件末尾追加,为False则覆盖原有内容

操作方法:
write(int n) 输出一个字节;
write(byte[] b) 输出一个字节数组
write(byte[] b,int off,int len) 输出字节数组的一部分
close() 释放IO占用的windows底层资源

代码案例:

public class OutputStreamDemo {
    public static void main(String[] args) {
        try {
            OutputStream os=new FileOutputStream("test.txt",true);  //true表示输出内容是在文件末尾追加内容的
            os.write(97);   //输出的是字符a

            byte[] b={97,98,99};   //输出的是abc
            os.write(b);
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字节输入流

输入流: InputStream 抽象类 FileInputStream 基本输入流
构造方法:
public FileInputStream(String name)
操作方法:
int read(); 读取一个字节 返回字节内容本身 读取到文件末尾返回-1
int read(byte[] b) 读取一个字节数组
close() 释放资源

代码案例:

public class InputStreamDemo {
    public static void main(String[] args) throws IOException {
        InputStream fis=new FileInputStream("test.txt");
        //一次读取一个字节    也可以一次读取一个字节数组
        System.out.println(fis.read());
        int c=-1;
        while((c=fis.read())!=-1){
            System.out.println(c);
        }

    }
}

运行结果:

97
97
98
99

文件复制与高效流

文件复制

方式1:不使用字节数组 即一次读取一个字节
方式2:使用字节数组 一次读取一个字节数组

高效字节流

Java在常规IO的基础上,提供了更为高效的缓冲流,如下:
高效字节缓冲流:BufferedInputStream/BufferedOutputStream
高效流使用普通流对象作为构造方法参数。将普通流包装,提供高效的装饰
高效流write写出数据时,写出位置为缓冲区,并非目标资源。需要通过flush刷新方法将缓冲区的内容写出到目标文件中。
并且高效输出流的关闭方法会自动调用flush方法

高效原理:缓冲区临时存储多个数据,然后一次调用底层资源,减少代用底层资源的次数,也即调用中断次数,从而提高程序运行速度。

代码案例:

public class BufferedByteStreamDemo {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("test.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);

        int c = bis.read();
        System.out.println(c);

        byte[] b=new byte[10];
        int len=-1;
        while((len=bis.read(b))!=-1){
            System.out.println(new String(b,0,len));
        }
    }
}

运行结果:

97
abc

转换流

操作纯文本文件时,使用字节流对于程序来说过于繁琐,程序员更偏好操作字符。所以当面对一些字节流的操作时,我们可以将其转换成字符流再进行操作,这样便非常方便了。

Reader:
InputStreamReader可以完成字节输入流转换成字符流
Writer:
OutputStreamWriter可以完成字节输出流转换成字符输出流。

由上边可以知道,转换流是字符流的一种,创建对象是传入对于的字节流对象即可完成转换动作。

转换流同样使用了包装的思想,其构造方法接受的同样为IO流对象,并非某个文件资源。关闭转换流的同时即关闭了对应的字节流。

OutputStreamWriter

//利用转换流向test.txt中写入“hello:中国”
public class OutputStreamWriterDemo {
    public static void main(String[] args) throws IOException {
        //创建字节输出流
        FileOutputStream fos = new FileOutputStream("test.txt", true);
        OutputStreamWriter osw = new OutputStreamWriter(fos);

        osw.write("hello:中国");   //向字节流中写入字符串

        osw.close();

    }
}

InputStreamReader

需求:已经具备字节流,绑定了IO资源。需要将字节流转换字符流

此时,可以使用转换流,接受一个字节流对象,进行字符流的操作,转换流本身就是字符流。

public class InputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("test.txt");
        InputStreamReader isr = new InputStreamReader(fis);

        int b=-1;
        while((b=isr.read())!=-1){
            System.out.println((char)b);
        }

        fis.close();
    }
}

运行结果:

a
a
b
c
h
e
l
l
o
:
中
国

编码表

编码表概述

我们知道计算机底层数据存储的都是二进制数据,而我们生活中各种各样的数据,如何才能和计算机中存储的二进制数据对应起来呢??

这时美国就把他们的每一个字符和一个整数对应起来,就形成了一张编码表,美国他们的编码表就是ASCII表。其中就是各个英文字符对应的编码

编码表:就是生活中字符和计算机二进制的对应关系表。

  1. ASCII:一个字节中的7位表示。对应的字节就是正数:0xxxxxxx。

  2. ISO-8859-1:拉丁Latin码表,用一个字节8位表示。1xxxxxxx:负数

  3. GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节就是负数,第二个字节可能是正数

    GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中一部分文字,第一个字节开头是1,第二个字节开头是0.

    GB18030:最新的中文码表,目前还没有正式使用。

  4. Unicode:国际标准码表:无论是什么文字,都用两个字节存储。

    Java中char类型用的就是这个码表:char c=‘a’ ;占用两个字节

  5. UTF-8:基于Unicode,一个字节就可以存储数据,不用两个字节存储,而且这个码更加标准化,中文一般使用3个字节

    能识别中文的码表:GB2312,GBK,Unicode,UTF-8

乱码问题

A:乱码:当字符与字节转换过程中使用了不同的码表,会造成乱码的情况

B:在字符串中:当我们将字符串转为对应的数字字节时,需要指定码表,则存储为该字符该码表对应的数字字节,如果使用了其他码表重写翻译回字符串,则拼写的新字符串回出现乱码

C:在IO中:与字符串编码表使用类似,当以某个码表写出字节数据时,又使用另外的码表展示,就会出现乱码。

将字节流设置指定编码的字节流:
public Output StreamWriter(OutputStream out,String charsetName);
public Input StreamReader(InputStream in,String charsetName);

代码实例:

public class CharSetDemo {
    public static void main(String[] args) throws IOException {
        //使用UTF-8的方式将字符输出到文件中
        FileOutputStream fos = new FileOutputStream("test.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");

        osw.write("你好");
        osw.close();    //注意这里需要关闭osw(在关闭对象资源之前会先清空缓存) 否则下面可能不会输出任何内容

        //如果使用UTF-8的方式写出两个汉字(6个字节),在那个写出的文件中观看时乱码了 这时在使用UTF-8的方式从那个文件中读回就不会乱码了
        FileInputStream fis = new FileInputStream("test.txt");
        InputStreamReader isr = new InputStreamReader(fis, "UTF-8");   //这里若使用GBK的方式读会就会出现乱码
        int ch=-1;
        while((ch=isr.read())!=-1){
            System.out.print((char)ch);
        }
        isr.close();
    }
}

其他流

序列化和反序列化

概述

用于向流中写入对象的操作流ObjectOutputStream 称为序列化流。
用于从流中读取对象的操作流 ObjectInputStream 称为反序列化流。

特点:用于操作对象。可以将对象写入到文件中,也可以从文件中读取对象

ObjectOutputStream 序列化流
public final void writeObject(Object o);

ObjectInputStream 反序列化流
public final Object readObject();

每个被序列化操作的类型必须实现Serializable接口(使其具备序列化功能的标记接口,不需要实现任何方法)。

对象序列化流ObjectOutputStream

ObjectOutputStream将Java对象写入到OutputStream,利用输出流将对象写入到指定文件中。

代码案例:

public class ObjectOutputStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person person = new Person("Jack","22");
        //利用OutputStream将Person对象写入到指定文件中
        FileOutputStream fos = new FileOutputStream("personObject.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(person);
        oos.close();

        //利用InputStream从泰国指定文件中读取对象
        FileInputStream fis = new FileInputStream("personObject.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Person o = (Person)ois.readObject();

        System.out.println(o.getName());
        System.out.println(o.getAge());
    }
}

打印流

打印流添加输出数据的功能,使他们能够方便打印各种数据值表示形式

打印流只有输出流,没有输入流:

​ PrintStream 字节打印流 调用println 方法时自动刷新

​ PrintlnWriter 字符打印流 指定自动刷新开关后,调用prinln方法时自动刷新,无序手动调用flush() 方法

第三方工具CommonsIO

导入classpath

A:加入classpath的第三方jar包内的class文件才能在项目使用

B:创建lib文件夹
将commons-io.jar拷贝到lib文件夹
右键点击Commons-io.jar,Build Parth ---->Add to Build Path

Filename Utils

这个工具是用来处理文件名(包含文件路径)的,他可以轻松解决不同不同操作系统文件名称规范不同的问题

常用方法:

​ getExtension(String path) 获取文件的扩展名
​ getName() 获取文件名
​ isExtension(String fileName,String ext) 判断fileName是否是ext后缀名

FileUtils

提供文件操作(移动文件,读取文件,检查文件是否存在等等)的方法。

常用方法:

​ readFileToString(File file) 读取文件内容,并返回一个String
​ writeStringtoFile(File file,String content) 将内容content写入到file中
​ copyDirectoryToDirectory(File srcDir,File destDir) 文件夹复制
​ copyFile(File srcFile,File destFile) 文件复制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值