IO流(字符流,字节流)

一些基本概念:

内存:临时存储

硬盘:永久存储

流数据:(字符,字节) 1个字符 = 2个字节 = 8个比特位

输入:就是把硬盘中的数据,读取到内存中使用

输出:把内存中的数据,写入到硬盘中保存.

字节流

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

字节输出流:(OutputStream)

java.io.OutputStream抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地,它定义了字节输出流的基本共性功能方法.

public void close():关闭此输出流并释放与此流相关联的任何系统资源。public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。public void write(byte[] b, int off, int len):从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。public abstract void write(int b) :将指定的字节输出流。(最后显示的是字符)

close的方法,在完成流的操作时候,必须调用这个方法,释放系统的资源.

FileOutputStream 类 (extends OutputStream)

作用:把内存中的数据写入到硬盘中的文件中

构造方法:

​ FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流

​ FileOutputStream(File file):创建一个向具有指定file对象的文件中写入数据的输出文件流

参数:

​ String name:目的地是一个文件的路径

​ File file:目的地是一个文件

构造方法的作用:

  1. 创建一个FileOutputStream对象

  2. 会根据构造方法中传递的文件/文件路径,创建一个空的文件

  3. 会把FileOutputStream对象指向创建好的文件.

可以帮我们创建文件,但是给出的文件夹路径必须对,否则可能就报空指针异常

写入数据的原理:(内存->硬盘)

java程序->jvm->os->调用写数据的方法->把数据写入到文件中

使用步骤:

  1. 创建一个fileoutputStream对象,构造方法中传递写入数据的目的地

  2. 调用fileoutputStream中的方法write,把数据写到文件中

  3. 释放资源(流的使用会占用一定的内存,使用完毕要把内存清空,提高程序的运行效率)

写数据的时候,会把十进制的整数,转换成为二进制的整数,写入到硬盘中

 

  • 任意的文本编辑器,在打开文件的时候,都会查询编码表,把字节转换为字符表示

  • 0-127:查询ACCII表

  • 其他值:查询系统默认码表

存入数字的时候,可以使用字符串。

一次写多个内容

public void write(byte[] b):当一次写多个字节的时候:

如果写的第一个字节是正数(0-127):那么显示的时候会查询ASCII表

如果写的第一个字节是负数:那么第一个字节会和第二个字节组成一个中文显示,查询默认码表GBK(即会变成汉字)

GBK:两个字节是一个中文

UTF-8:三个字节是一个中文

最终存入计算机的还是unicode表对应的二进制的数字(01字符串)

文件的追加写入:构造方法的第二个参数是true,就可以追加,默认是false,不追加

写入一个空格或者换行

windows:\r\n

linux:/n

mac:/r,从macosX开始与linux统一

字节输入流:(InputStream)

java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。public void close():关闭此输入流并释放与此流相关联的任何系统资源。public abstract int read() : 从输入流读取数据的下一个字节。public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。

close方法,当完成流的操作时,必须调用此方法,释放系统资源。(在字节流中不关闭也能写进去,但是在字符流中不关闭就写不进去)

FileInputStream 类 (extends InputStream)

文件字节输入流

作用:把硬盘文件中的数据,读取到内存中使用

构造方法以及作用与输出流类似.

读取数据的原理:(硬盘->内存)

java程序->jvm->os->os读取数据的方法->读取文件

字节输入流的使用步骤

  1. 创建FileInputStream对象,构造方法中绑定要读取的数据源

  2. 使用FileInputStream对象中的方法read,读取文件

  3. 读取完毕,释放资源

 

int read()读取文件中的一个字节并返回,读取到文件的末尾返回-1(就算多读取还是-1)

使用int len来记录读写的写法

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

int read(byte[]b):一次读取多个字节,返回值就是读取的有效字节个数

方法中参数的byte[] b作用:

  1. 起到缓冲作用,存储每次读取到的多个字节

  2. 数组的长度一般定义为1024(1kb)或者1024的整数倍

int len;
byte[] bytes = new byte[1024];
while((len = fis.read) != -1){
   System.out.println(new String(bytes)); 
}
//这时候会有bug,会出现上次读取的数据没有被完全替换的情况,就会打印出不想要的数据
​
//所以使用String的构造方法来优化(获取有效的字节)
sout(new String(bytes,0,len));

练习:图片的复制

题目:把D:\a.jpg --(复制到)-->E:\b.jpg

public class Copy {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("E:\\b.jpg");
        FileInputStream fis = new FileInputStream("D:\\a.jpg");
        int len;
        byte[] bytes = new byte[1024];
        while ((len = fis.read(bytes)) != -1){
            //如果是读的操作,应该写出来为
            //sout(new String(bytes,0,len));
            fos.write(bytes,0,len);
        }
        fos.close();
        fis.close();
    }
}
​

在文件的复制的过程中关闭资源的时候,先关闭写的,再关闭读的.

字符流(只能读文本类,不能读电影等等)

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

字符输入流:(Reader)

java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。public void close():关闭此流并释放与此流相关联的任何系统资源。public int read(): 从输入流读取一个字符。public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。

FileReader类(extends InputStreamReader extends Reader)

构造方法:

FileReader(File file): 创建一个新的 FileReader ,给定要读取的File对象。FileReader(String fileName): 创建一个新的 FileReader ,给定要读取的文件的名称。当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。

字符流的使用步骤与字节流一样.但是缓冲区变成了字符数组(字节流使用的是字节数组)

字符输出流:(Writer)

java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。void write(int c)写入单个字符。void write(char[] cbuf) 写入字符数组。abstract  void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len写的字符个数。void write(String str)写入字符串。void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索 引,len写的字符个数。void flush()刷新该流的缓冲。void close()关闭此流,但要先刷新它。

FileWriter类(extends OutputStreamWriter extends Writer)

作用:把内存中的字符数据写入到文件

构造方法以及作用:类比OutputStream

使用步骤:

  1. 创建FileWriter对象

  2. 使用FileWriter中的方法写入到内存缓冲去(字符转换为字节的过程)

  3. 使用FileWriter中的方法flush,把内存缓冲区中的数据刷新到文件中

  4. 释放资源

如果没有调用flush或者close方法,就不会写到文件中.而close方法之后流已经关闭了,已经从内存中消失了,不能再用了.

写出其他数据

写出字符数组 :write(char[] cbuf)write(char[] cbuf, int off, int len),每次可以写出字符数组中的数据,用法类似FileOutputStream,

写出字符串: write(String str)write(String str, int off, int len) ,每次可以写出字符串中的数据,更为方便.

续写和换行:操作类似于FileOutputStream。

(就是在构造的时候参数多一个true)(write("\r\n"))

 

IO异常处理

在jdk1.7之前使用:try catch finally

格式:

try{

可能产生异常的代码

}catch(异常类型 变量){

异常处理逻辑

}finally{

一定执行的代码

资源释放

}

public class FileWriterDemo01 {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("a.txt");
            fw.write(97);
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            try {
                if (fw != null) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
几个注意的点:
1.在对创建对象时候的异常处理的时候,要把对象声明到try...catch之外,并初始化
2.在finally代码块中对资源释放的时候,要注意对空指针的判断

在jdk7的新特性

在try的后面可以增加一个(),在()可以定义流对象,那么这个流对象的作用域在try中有效,try中的代码执行完毕,会自动把流对象释放,不用再写finally,如果有多个对象,要使用;隔开

try(定义流对象){

可能产生异常的代码

}catch(异常类型 变量){

异常处理逻辑

}

public class FileWriterDemo01 {
    public static void main(String[] args) {
        try( FileWriter fw = new FileWriter("a.txt")) {
            fw.write(97);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
在try后面的括号中参数使用;隔开

在jdk9的新特性

try前面可以定义对象,在try后面的()中可以直接引入流对象的名称(变量名),在try代码执行完毕之后,流对象也可以释放掉,不用写finally

格式:

int a = 1;

int b = 2;

try(a;b){

可能产生异常的代码

}catch(异常类型 变量){

异常处理逻辑

}

比较麻烦..尽量还是使用第一种,或者第二种

属性集

概述

java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时, System.getProperties() 方法就是返回一个 Properties 对象。

Properties类

构造方法:

public Properties() :创建一个空的属性列表

基本的存储方法

public Object setProperty(String key, String value): 保存一对属性。public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。public Set<String> stringPropertyNames():所有键的名称的集合。

 

package com.qin.study;
​
import java.util.Properties;
import java.util.Set;
​
/**
 * Created by SunYuqin in 2018/8/14
 * Description:
 **/
​
public class PropertiesDemo01 {
    public static void main(String[] args) {
        //创建属性集对象
        Properties pro = new Properties();
        //添加键值对元素
        pro.setProperty("filename","a.txt");
        pro.setProperty("length","200");
        pro.setProperty("location","D:\\a.txt");
        //打印对象集对象
        System.out.println(pro);
        //通过键,获取属性值
        System.out.println(pro.getProperty("filename"));
        System.out.println(pro.getProperty("length"));
        System.out.println(pro.getProperty("location"));
​
        // 遍历属性集,获取所有键的集合
        Set<String> strings = pro.stringPropertyNames();
        for (String string : strings) {
            System.out.println(string+"--"+pro.getProperty(string));
        }
    }
}
​
结果
{length=200, filname=a.txt, location=D:\a.txt}
a.txt
200
D:\a.txt
length--200
filname--a.txt
location--D:\a.txt

与流相关的方法

public void load(InputStream inStream): 从字节输入流中读取键值对。

public class ProDemo2 {
​
    public static void main(String[] args) throws FileNotFoundException {
​
        // 创建属性集对象
​
        Properties pro = new Properties();
​
        // 加载文本中信息到属性集
​
        pro.load(new FileInputStream("read.txt"));
​
        // 遍历集合并打印
​
        Set<String> strings = pro.stringPropertyNames();
​
        for (String key : strings ) {
​
           System.out.println(key+" ‐‐ "+pro.getProperty(key));  
​
        }
​
     }
​
}
​
输出结果:
​
filename ‐‐ a.txt
​
length ‐‐ 209385038
​
location ‐‐ D:\a.txt

 

 

ps:文本中的数据,必须是键值对形式,可以使用空格、等号、冒号等符号分隔。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值