字节流、字符流
主要内容
IO 流
字节流
字符流
异常处理
Properties
教学目标
能够说出IO流的分类和功能
能够使用字节输出流写出数据到文件能够使用字节输入流读取数据到程序
能够理解读取数据read(byte[])方法的原理能够使用字节流完成文件的复制
能够使用FileWirter写数据到文件
能够说出FileWriter中关闭和刷新方法的区别能够使用FileWriter写数据的5个方法
能够使用FileWriter写数据实现换行和追加写
能够使用FileReader读数据
能够使用FileReader读数据一次一个字符数组
能够使用Properties的load方法加载文件中配置信息
输入输出流
第一章 IO概述
1.1 什么是IO
我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为 input 和output,即流向内存是输入流,流出内存的输出流
Java中I/O操作主要是指使用java.io包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。
1.2 IO的分类:
根据数据的流向分为:输入流和输出流。
输入流 :把数据从 其他设备 上读取到 内存 中的流。
输出流 :把数据从 内存 中写出到 其他设备 上的流。
根据数据的类型分为:字节流和字符流。
字节流 :以字节为单位,读写数据的流。
字符流 :以字符为单位,读写数据的流
1.3 顶级父类们
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流InputStream | 字节输出流OutputStream |
字符流 | 字符输入流Reader | 字符输出流Writer |
第二章 字节流
2.1 一切皆为字节
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一 样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底 层传输的始终为二进制数据。
2.2 字节输出流【OutputStream】
java.io.OutputStream
此类是一个抽象类,表示输出字节流的所有类的超类
2.3 FileOutputStream类
java.io.FileOutputStream extends OutputStream
OutputStream有很多子类,我们从最简单的一个子类开始。
FileOutputStream类是文件输出流,用于将数据写出到文件。
java.io.FileOutputStream extends OutputStream
作用:把内存的数据写入到硬盘文件中
构造方法:
public FileOutputStream(File file)throws FileNotFoundException创建文件输出流以写入由指定的File对象表示的文件
public FileOutputStream(String name)throws FileNotFoundException创建文件输出流以指定的名称写入文件。
当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文 件,会清空这个文件的数据。
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;/*
java.io.OutputStream
此类是一个抽象类,表示输出字节流的所有类的超类
定义一些子类共性的成员方法:
public void close()throws IOException关闭此输出流并释放与此流相关联的任何系统资源
public void flush()throws IOException刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b)throws IOException将b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b,int off,int len)throws IOException从指定的字节数组写入len字节,从偏移off开始输出到此输出流。
public abstract void write(int b)throws IOException将指定的字节写入此输出流。写入数据的原理:
java程序——>JVM(Java虚拟机)——>OS(操作系统)——>OS调用写入数据的方法——>把数据写入到文件中
字节输出流的使用步骤:
1.调用构造方法,创建字节输出流对象
2.调用write方法,把数据写入到文件中
3.释放资源(流在使用的时候会占用内存,使用完毕要清空内存,可以提高程序的效率)
4.处理异常
注意:
flush()在字节输出流中可以不使用,可以不刷新*/
public class OutputStreamTest01 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("a.txt");fos.write(97);fos.close();}
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;/*
public void write(byte[] b)throws IOException将b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b,int off,int len)throws IOException从指定的字节数组写入len字节,从偏移off开始输出到此输出流。*/
public class OutputStreamTest02 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("b.txt");/*** public void write(byte[] b)throws IOException* 将b.length字节从指定的字节数组写入此输出流。* 如果写的正数(0~127),就会查询ASCII码表,显示对应的字母* 如果写的负数,那么第一个和第二个字节会组成一个中文,就会查询系统默认编码表(GBK)*/byte[] bytes = {65,66,67,68,69};//byte[] bytes = {-65,-66,-67,-68,-69};//fos.write(bytes);/*** public void write(byte[] b,int off,int len)throws IOException* 从指定的字节数组写入len字节,从偏移off开始输出到此输出流。*/fos.write(bytes,1,2);fos.close();}}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;/*
public FileOutputStream(String name,boolean append)throws FileNotFoundException创建文件输出流以指定的名称写入文件。
public FileOutputStream(File file,boolean append)throws FileNotFoundException
append参数值:
true:创建对象不会覆盖源文件,继续在文件末尾追加写入数据
false:创建一个新文件,覆盖源文件换行:写换行符号
windows:\r\n
Linux: /n
mac: /r*/
public class OutputStreamTest03 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("c.txt",false);for (int i = 1; i <=10 ; i++) {fos.write("你好".getBytes());fos.write("\r\n".getBytes());}fos.close();}
}
2.4字节输入流【InputStream】
java.io.InputStream
此类是一个抽象类,表示输入字节流的所有类的超类
定义一些子类共性的成员方法:
public abstract int read()throws IOException从输入流读取数据的下一个字节。
public int read(byte[] b)throws IOException从输入流读取一些字节数,并将它们存储到缓冲区b 。
public int read(byte[] b,int off,int len)throws IOException从输入流读取len字节的数据到一个字节数组。
public int available()throws IOException返回从该输入流中可以读取(或跳过)的字节数的估计值
public long skip(long n)throws IOException跳过并丢弃来自此输入流的n字节数据。
2.5 FileInputStream类
public class FileInputStream extends InputStream
作用:把写入到硬盘文件中的数据读出来到内存中
读取字节数据
1.读取字节:reaad()方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回 -1,代码演示:
//字节输入流一次读取一个字节的方法:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class InputStreamTest01 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("b.txt");/*int len = fis.read();System.out.println(len);//65len = fis.read();System.out.println(len);//66len = fis.read();System.out.println(len);//67len = fis.read();System.out.println(len);//68len = fis.read();System.out.println(len);//69len = fis.read();System.out.println(len);//-1len = fis.read();System.out.println(len);//-1*/int len = 0;//记录读到的字节while ((len=fis.read())!=-1){System.out.println(len);}/*读取字节数据
读取字节:reaad()方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回 -1*//*错误:while (fis.read()!=-1){//65System.out.println(fis.read());//66 68 -1}*/fis.close();}
}
2.使用字节数组读取: read(byte[] b) ,每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回 -1 ,代码使用演示:
package com.hqyj.demo02;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;/*
字节输入流一次读取多个字节的方法:
public int read(byte[] b)throws IOException从输入流读取一些字节数,并将它们存储到缓冲区b 。
public int read(byte[] b,int off,int len)throws IOException从输入流读取len字节的数据到一个字节数组。
明确两件事情:
1.方法的参数byte[]的作用?
起到了缓冲的作用,存储每次读取到的多个字节
数组的长度一般定义为1024或者1024的整数倍
2.方法的返回值int是什么?
每次读取到的有效字节个数*/
public class InputStreamTest02 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("b.txt");//b.txt:我爱JAVA,很爱很爱/*byte[] bytes = new byte[2];int len = fis.read(bytes);System.out.println(len);//2System.out.println(Arrays.toString(bytes));//[65, 66]len = fis.read(bytes);System.out.println(len);//2System.out.println(Arrays.toString(bytes));//[67, 68]len = fis.read(bytes);System.out.println(len);//1System.out.println(Arrays.toString(bytes));//[69, 68]len = fis.read(bytes);System.out.println(len);//-1System.out.println(Arrays.toString(bytes));//[69, 68]*///读数据优化:byte[] bytes = new byte[1024];//存储读到的多个字节int len = 0;//每次读取到的有效字节个数while ((len=fis.read(bytes))!=-1){//public String(byte[] bytes,int length)System.out.println(new String(bytes,0,len));}fis.close();}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;/*
使用字节流读取中文文件:
1个中文
GBK:占用两个字节
UTF-8:占用三个字节
注:使用字节流读取文本文件中的数据时,可能会有一个小问题。
就是在遇到中文数据的时候,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。
所以Java提供了一些字符流类,以字符为单位读写数据,专门用来处理文本文件*/
public class InputStreamTest03 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("b.txt");int len = 0;while ((len=fis.read())!=-1){System.out.print((char)len);//我爱JAVA,很爱很爱}fis.close();}}
2.6 字节流练习:图片复制
复制原理图解
图片文件复制:一边读一边写
数据源:D:\test.jpg
数据的目的地:项目下test_copy.jpg
文件复制的步骤:
1.创建一个字节输入流对象,构造方法中要绑定要读取的数据源
2.创建一个字节输出流对象,构造方法中要绑定要写入的数据的目的地
3.使用read()和write()方法,一边读一边写
4.释放资源
复制图片,代码演示:
public class Copy {public static void main(String[] args) throws IOException {// 1.创建流对象// 1.1 指定数据源FileInputStream fis = new FileInputStream("D:\\test.jpg");// 1.2 指定目的地FileOutputStream fos = new FileOutputStream("test_copy.jpg");// 2.读写数据// 2.1 定义数组byte[] b = new byte[1024];// 2.2 定义长度int len;// 2.3 循环读取while ((len = fis.read(b))!=‐1) {// 2.4 写出数据fos.write(b, 0 , len);}// 3.关闭资源fos.close();fis.close();}
}
小贴士:
流的关闭原则:先开后关,后开先关。
第三章 字符流
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文 件。
3.1 字符输入流【Reader】
java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。
public void close() :关闭此流并释放与此流相关联的任何系统资源。
public int read() : 从输入流读取一个字符。
public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。
3.2 FileReader类
public class FileReader extends InputStreamReader
构造方法
FileReader(File file) : 创建一个新的 FileReader ,给定要读取的File对象。
FileReader(String fileName) : 创建一个新的 FileReader ,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。
public class FileReaderConstructor throws IOException{ public static void main(String[] args) {// 使用File对象创建流对象File file = new File("a.txt"); FileReader fr = new FileReader(file);// 使用文件名称创建流对象FileReader fr = new FileReader("b.txt");}
}
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;/*
java.io.Readerjava.io.InputStreamReaderjava.io.FileReader
public FileReader(String fileName)throws FileNotFoundExceptionpublic int read()throws IOException
public int read(char[] cbuf)throws IOException 将字符读入数组。*/
public class ReaderTest {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("b.txt");int len = 0;while ((len=fr.read())!=-1){System.out.println((char)len);}/*char[] chs = new char[1024];int len = 0;while ((len=fr.read(chs))!=-1){//convertSystem.out.println(new String(chs,0,len));}*/fr.close();}
}
3.3 字符输出流【Writer】
java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节 输出流的基本共性功能方法。
3.4 FileWriter类
java.io.FileWriter类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
构造方法:
FileWriter(File file) : 创建一个新的 FileWriter,给定要读取的File对象。
FileWriter(String fileName) : 创建一个新的 FileWriter,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。
构造举例,代码如下:
public class FileWriterConstructor {public static void main(String[] args) throws IOException {// 使用File对象创建流对象File file = new File("a.txt");FileWriter fw2 = new FileWriter(file);// 使用文件名称创建流对象FileWriter fw2 = new FileWriter("b.txt");}
}
基本写出数据
写出字符:write(int b)方法,每次可以写出一个字符数据,代码使用演示:
public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw = new FileWriter("fw.txt");// 写出数据fw.write(97); // 写出第1个字符fw.write('b'); // 写出第2个字符fw.write('C'); // 写出第3个字符fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。/*【注意】关闭资源时,与FileOutputStream不同。如果不关闭,数据只是保存到缓冲区,并未保存到文件。*/// fw.close();}
}
输出结果:
abC田
import java.io.FileWriter;
import java.io.IOException;/*
java.io.Writerjava.io.OutputStreamWriterjava.io.FileWriter
public void write(int c) throws IOException写一个字符
public void write(char[] cbuf) throws IOException写入一个字符数组。
public abstract void write(char[] cbuf,int off,int len) throws IOException写入字符数组的一部分。
public void write(String str)throws IOException写一个字符串
public void write(String str,int off,int len)throws IOException写一个字符串的一部分。
public abstract void flush()throws IOException刷新流。
public abstract void close()throws IOException关闭流前,先刷新注意:字符输出流是建议刷新,调用flush方法,字节输出流可以不用刷新!!!*/
public class WriterTest01 {public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("d.txt");fw.write(97);fw.flush();fw.close();}
}
package com.hqyj.demo04;import java.io.FileWriter;
import java.io.IOException;/*
flush方法和close方法的区别:
flush方法:刷新缓冲区,流对象是可以继续使用的
close方法:先刷新缓冲区,然后通知系统释放资源。流对象不可以继续使用的。*/
public class WriterTest02 {public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("d.txt");fw.write(97);fw.flush();fw.write(98);fw.flush();fw.close();/*以下代码报异常Exception in thread "main" java.io.IOException: Stream closedfw.close();fw.write(99);fw.flush();*/}}
package com.hqyj.demo04;import java.io.FileWriter;
import java.io.IOException;/*
字符输出流写入数据的其他方法:
public void write(char[] cbuf) throws IOException写入一个字符数组。
public abstract void write(char[] cbuf,int off,int len) throws IOException写入字符数组的一部分。
public void write(String str)throws IOException写一个字符串
public void write(String str,int off,int len)throws IOException写一个字符串的一部分。*/
public class WriterTest03 {public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("e.txt");char[] cs = {'a','b','c','d','e'};fw.write(cs);fw.write(cs,1,2);fw.write("迪丽热巴");fw.write("易烊千玺",2,2);fw.flush();fw.close();}
}
package com.hqyj.demo04;import java.io.FileWriter;
import java.io.IOException;/*
续写和换行:
public FileWriter(String fileName,boolean append)throws IOException
append参数值:
true:创建对象不会覆盖源文件,继续在文件末尾追加写入数据
false:创建一个新文件,覆盖源文件换行:写换行符号
windows:\r\n
Linux: /n
mac: /r*/
public class WriterTest04 {public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("f.txt",false);for (int i = 1; i <=10 ; i++) {fw.write("我爱脑花儿"+i+"\r\n");}fw.flush();fw.close();}
}
第四章 IO异常的处理
package com.hqyj.demo05;import java.io.FileWriter;
import java.io.IOException;/*
在JDK1.7之前使用try...catch...finally处理流中的异常和释放资源
格式:
try{
可能出现异常的代码
}cath(异常类型 变量名){异常的处理逻辑
}finally{
释放资源
}*/
public class TryCatchTest01 {public static void main(String[] args) {FileWriter fw = null;try {fw = new FileWriter("f.txt", false);for (int i = 1; i <= 10; i++) {fw.write("我爱脑花儿" + i + "\r\n");}fw.flush();}catch (IOException e){e.printStackTrace();}finally {if(fw!=null) {try {fw.close();} catch (IOException e) {e.printStackTrace();}}}}}
package com.hqyj.demo05;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;/*
JDK1.7新特性:
在try的后面可以增加一个小括号(),在小括号中定义流对象,那么这个流对象的作用域就在try中有效,
try中的代码执行完毕,会自动把流对象释放,就不用再写finally了格式:
try(定义流对象1 定义流对象2...){
可能出现异常的代码
}cath(异常类型 变量名){异常的处理逻辑
}*/
public class TryCatchTest02 {public static void main(String[] args) {try(FileInputStream fis = new FileInputStream("d:\\1.jpg");FileOutputStream fos = new FileOutputStream("e:\\1.jpg")){byte[] bytes = new byte[1024];int len = 0;while ((len=fis.read(bytes))!=-1){fos.write(bytes,0,len);}}catch (IOException e){e.printStackTrace();}}
}
第五章 属性集
5.1 概述
java.util.Properties继承于Hashtable,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时,System.getProperties方法就是返回一个Properties对象。
5.2 Properties类
package com.hqyj.demo06;import java.io.*;
import java.util.Properties;
import java.util.Set;/*
java.util.Hashtable<Object,Object>java.util.Properties
1.Properties表示一个持久的属性集,Properties 可以保存在流中或者从流中加载
2.Properties 集合唯一一个和IO流相关的集合
3.Properties 集合中的store方法,把集合中临时数据,持久化写入到硬盘存储
4.Properties 集合中的load方法,把硬盘中保存的文件(键值对),读取到集合中使用注意1:是个双列集合,key和value都是String类型
注意2:
1)存储键值对的文件中,建和值的连接符号可以使用=,空格(其他符号)
2)存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取了
3)存储键值对的文件中,键和值默认都是都是字符串,不用再加上引号*/
public class PropertiesTest {public static void main(String[] args) throws IOException {show03();}/*public void load(InputStream inStream)throws IOExceptionpublic void load(Reader reader)throws IOException*/private static void show03() throws IOException {Properties prop = new Properties();prop.load(new FileReader("prop.txt"));Set<String> set = prop.stringPropertyNames();for (String key : set) {String value = prop.getProperty(key);System.out.println(key+"="+value);}}/*public void store(OutputStream out,String comments)throws IOExceptionpublic void store(Writer writer,String comments)throws IOException*/private static void show02() throws IOException {Properties prop = new Properties();prop.setProperty("张艺兴","breaking");prop.setProperty("王一博","poping");prop.setProperty("王嘉尔","hip-hop");prop.setProperty("钟汉良","urban");prop.store(new FileWriter("prop.txt"),"hehehehe");}/*public Object setProperty(String key,String value)public String getProperty(String key)public Set<String> stringPropertyNames()*/private static void show01() {Properties prop = new Properties();prop.setProperty("张艺兴","breaking");prop.setProperty("王一博","poping");prop.setProperty("王嘉尔","hip-hop");prop.setProperty("钟汉良","urban");Set<String> set = prop.stringPropertyNames();for (String key : set) {String value = prop.getProperty(key);System.out.println(key+"="+value);}}/*public void store(OutputStream out,String comments)throws IOExceptionpublic void store(Writer writer,String comments)throws IOException*/private static void show02() throws IOException {Properties prop = new Properties();prop.setProperty("张艺兴","breaking");prop.setProperty("王一博","poping");prop.setProperty("王嘉尔","hip-hop");prop.setProperty("钟汉良","urban");prop.store(new FileWriter("prop.txt"),"hehehehe");}/*public Object setProperty(String key,String value)public String getProperty(String key)public Set<String> stringPropertyNames()*/private static void show01() {Properties prop = new Properties();prop.setProperty("张艺兴","breaking");prop.setProperty("王一博","poping");prop.setProperty("王嘉尔","hip-hop");prop.setProperty("钟汉良","urban");Set<String> set = prop.stringPropertyNames();for (String key : set) {String value = prop.getProperty(key);System.out.println(key+"="+value);}}
}