一:概念
1.字符,字节,字符集(编码)
字节是内存存储数据的单位,字符则是一种数据。字节是存储容量的基本单位,1字节=8个二进制位,即一个8位的二进制数,是一个很具体的存储空间,如0x01,0xFA。
字符是指字母、数字、汉字和各种符号,如‘1‘,‘中‘,‘#’。一个字符在计算机中用若干个字节的二进制数表示,西文字符1个字节,中文字符2个字节。
字符集(编码):一种标准,规定使用哪些字符,每个字符分别用一个还是多个字节存储,用哪些字节存储;
2.流,字符流与字节流
流:一组有序的数据序列,可以理解为传输通道。Java中的IO流是输入输出流。
如何判断是输入流还是输出流?
以内存为参照物,如果数据是向内存流动是输入流,反之则是输出流。
将输入和输出两个端点看作是两个工厂,工厂之间需要互相运输货物,而流则是两工厂之间的公路,没有公路就不能互相运输,至于字符,字节和二进制则可以看作是运输的方式和单位大小,比如说把二进制理解成三轮车,那么字节就是小卡车,而字符则是更高级的集卡之类的。
字节流可处理所有类型的数据,如MP3,图片,文字,读取时,读到一个字节就返回一个字节;JAVA中字节流对应的类都以“Stream”结尾;
字符流仅可处理纯文本数据,读取时,读到一或多个字节,先查找指定的编码表,然后将查到的字符返回。在AVA中字符流对应的类都以“Reader”或"Writer"结尾;
字符流的底层就是字节流。而字符流主要是读取文本文件内容的,可以一个字符一个字符的读取,也可以一行一行的读取文本文件内容。而字节流读取单位为byte.byte作为计算机存储最基本单位,可以用字节流来读取很多其他格式的文件,比如图片视频等等。基于B/S和C/S的文件传输都可以采用字节流的形式。
二:函数
1.包括在输入输出功能的包Java.io中,所有方法遇到错误时均会抛出IOException异常。
2.java流分为两种流
字节流:可以用于读写二进制文件及任何类型文件byte
字符流:可以用于读写文件文本
字节流:输入(InputStream) 输出(OutputStream)
字符流:输入(Reader) 输出(writer)
Reader类的read()方法返回类型为int :作为整数读取的字符(占两个字节共16位),范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1(表明已成功读取完毕)
inputStream的read()虽然也返回int,但由于此类是面向字节流的,一个字节占8个位,所以返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。因此对于不能用0-255来表示的值就得用字符流来读取!比如说汉字.
3.FileInputStream 是文件输入流,它继承于InputStream。
通常,我们使用FileInputStream从某个文件中获得输入字节。
FileOutputStream 是文件输出流,它继承于OutputStream。
通常,我们使用FileOutputStream 将数据写入 File 或 FileDescriptor 的输出流。
4.带缓存的流
若不指定缓存区大小,默认为分配32个字节。
java.io.BufferedReader和java.io.BufferedWriter类各拥有8192字符的缓冲区。
BufferedReader:一个包装类,它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了或者你flush的时候,再读入内存,就是为了提供读的效率而设计的。如果缓冲区数据不足,才会再从文件中读取。
BufferedWriter:写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。
5.从标准输入流System.in中直接读取使用者输入时,使用者每输入一个字符,System.in就读取一个字符。为了能一次读取一行使用者的输入,使用了BufferedReader来对使用者输入的字符进行缓冲。readLine()方法会在读取到使用者的换行字符时,再一次将整行字符串传入。
System.in是一个位流,为了转换为字符流,可使用InputStreamReader为其进行字符转换,然后再使用BufferedReader为其增加缓冲功能
三:过程
操作流程
在Java中IO操作也是有相应步骤的,以文件操作为例,主要的操作流程如下:
1 使用File类打开一个文件
2 通过字节流或字符流的子类,指定输出的位置
3 进行读/写操作
4 关闭输入/输出
IO操作属于资源操作,一定要记得关闭
四:常用方法
字节流:
Inputstream:
read(int);
read(byte);
reset();
mark();
skip(long n);//以上三个只对某些子类有用
markSupported();
OutputStream(所有方法均返回void):
write(int);
write(byte);
flush(); //BufferedOutputStream中的方法,用来刷新内存,将内存中的数据立刻写出。
close();
字符流:
BufferedReader:
读取单个字符
read();//读取单个字符
readLine();//读取一个文本行,返回为字符串,无数据则返回null
BufferedWriter:
write();
flush();
newLine(); //写入一个行分隔符
五:代码
一:字节流
1.字节流的读入,写出,拷贝
其中用到字符串与字节数组的互相转化:
getBytes():将一个字符串转化为一个字节数组byte[]:getBytes(“utf-8”);
//FileInputStream import java.io.FileInputstream; import java.io.IOException; import java.io.FileNotFoundException; public class ReadByteStream{ public static void main(String args[]){ //File类打开要读入的数据 FileInputStream fis = new FileInputStream("text.txt");//使用一个相对路径 //调用read方法来读入字节流到字节数组中,首先创建字节数组: Byte input = new Byte[20]; fis.read(input); //由于所读取内容为文本,转化为字符串 String inputString = new String(input); //后面可以指定编码方式 System.out.println("inputString"); } }
//FileOutputStream import java.io.FileOutputstream; import java.io.IOException; import java.io.FileNotFoundException; public class WriteByteStream{ public static void main(String args[]){ //指定写出的文件夹 FileOutputStream fos = new FileOutputStream("text.txt"); //调用write方法,首先要有待写入的数据 String outputString = "lalala啦啦啦123"; //可以直接从当前的字符串中获得字节数组 byte output[] = outputString.getBytes("UTF-8");//调用getbytes()方法 fos.write(output); } }
//字节流的拷贝 //打开要拷贝的文件 FileInputStream fis = new FileInputStream (“1.txt”); FileOutputStream fos = new FileOutputStream ("copy1.txt"); //调用方法 //定义字节数组:为避免数组过小,造成拷贝不完全,需要循环读取 //read方法返回值为已从文件读取到的数据值;若返回-1,则说明已读到文件末尾 byte input[] = new Byte(50); while(fis.read(input) != -1) { fos.write(input); } //记得关闭 fis.close(); fos.close(); system.out.println("OK!");
2.带有缓冲的字节流的读入,写出(文件容量大时高效)
//1.使用带缓冲区的字节流来进行读入,拷贝 FileInputStream fis = new FileInputStream("Movio.mp4);//2.从这个文件中获得输入字节 //3.创建一个带缓冲的输入字节流,传入的参数为输入流,即当前的FileInputStream BufferedInputStream bis = new BufferedInputStream(fis);//12.还可以传入参数:缓冲区大小 //8.进行文件的拷贝: FileOutputStream fos = new FileOutputStream ("newMovio.mp4); BufferedoutputStream bos = new BufferedOutputStream(fos);//9.带上缓冲区 //4.调用read方法,首先创建字符数组,文件里的数据就读入到这个数组 byte input[] = new byte(100); int count = 0;//7.定义整型来统计读入了多少字节 while(bis.read(input) != -1){ 5.//依旧使用循环,避免读取不完整 bos.write(input);//10.写出字节流 count++; } //6.关闭文件时:先打开的后关闭 bis.close(); fis.close(); bos.close();//11.关闭也一样 fos.close(); sysytem.out.println("共读取了:"+count +"次!");
2.1缓冲区做优化:///////////////////////////////////
二:字符流
1.使用字符流读写数据
六:争议
字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的
字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容