【JavaSE笔记】IO(三)IO流_字节流

来源:互联网 发布:b2c商城网站源码下载 编辑:程序博客网 时间:2024/06/04 19:59
本期知识点:
IO流
字节流

IO流

1.IO流

设备和设备之间的传输(读和写)

2.分类

a.按流向分为:

输入流---读取数据
输出流---写出数据

b.按数据类型分为:

字节流:
字节输入流:InputStream
字节输出流:OutputStream
字符流:
字符输入流:Reader
字符输出流:Writer
注意:
a:如果我们没有明确说明按照什么分,默认按照数据类型分。
b:除非文件用windows自带的记事本打开我们能够读懂,才采用字符流,否则建议使用字节流。

字节流

1.FileOutputStream写出数据

a.字节输出流对象中的写数据的方法:

public void write(int b):写入一个字节
public void write(byte[] b):写一个字节数组

public void write(byte[] b, int index,int len):写一部分字节数组(常用)

import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class 写数据的方法 {public static void main(String[] args) throws IOException {//创建文件字节输出对象FileOutputStream fos = new FileOutputStream("fos.txt");//public void write(int b):写入一个字节fos.write(97);//打开记事本 看到写入了 97ASCII码对应的字符 //public void write(byte[] b):写一个字节数组byte []a = {97,98,99,100,101};fos.write(a);//打开记事本 看到写入了 ASCII码对应的字符  bcdef//public void write(byte[] b, int index,int len):写一部分字节数组(常用)fos.write(a, 2, 3);//cdefos.close();}}

b.操作步骤:

i.创建字节输出流对象
FileOutputStream里面的具体的构造方法:
public FileOutputStream(File file)指定一个File对象
public FileOutputStream(String name) 直接指定文件名称
ii.调用write()方法写数据
iii.释放资源close()

c.相关的问题?

i.创建字节输出流对象做了几件事情?
1)调用系统功能区创建FileOutputStream对象

2)将fos对象指向fos.txt文件


ii.为什么要close()?

iii.如何实现数据的换行?
现了一个给文件中写入了一个数据,并且没有换行,那是因为我们没有给for循环中增加一个换行符号:针对不同的操作系统换行符号是不一样的:
windows:\r\n
Linux:\n

Mac:\r


iv.如何实现数据的追加写入?
构造方法:
public FileOutputStream(File file, boolean append)

如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处

public class FileOutputStreamDemo3 {public static void main(String[] args) throws IOException {//创建文件字节输出流对象//FileOutputStream fos = new FileOutputStream("fos3.txt") ;FileOutputStream fos = new FileOutputStream("fos3.txt", true) ;//写数据for(int x = 0 ; x <10 ; x ++){fos.write(("hello"+x).getBytes());//需要写一个换行符号fos.write("\r\n".getBytes());}//释放资源fos.close();}}

d.文件字节输出流中加入异常处理(try...catch方式)

i.1.0分开处理

import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;/** *  * 文件字节输出流中加入异常处理(try...catch方式) * */public class 异常处理1 {public static void main(String[] args) {//分开处理FileOutputStream fos = null ;try {//创建文件字节输出流对象fos = new FileOutputStream("fos4.txt") ;} catch (FileNotFoundException e) {e.printStackTrace();}//写数据try {fos.write("java".getBytes());} catch (IOException e) {e.printStackTrace();}//关闭资源try {fos.close();} catch (IOException e) {e.printStackTrace();}}}


ii.2.0一起处理

import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class 异常处理2 {public static void main(String[] args) {//方式2:一起处理try {FileOutputStream fos1 = new FileOutputStream("fos4.txt") ;//写数据fos1.write("java".getBytes());//释放资源fos1.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}


iii.3.0 最终版本

import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class 异常处理3 {public static void main(String[] args) {FileOutputStream fos  = null ;try {fos = new FileOutputStream("fos4.txt") ;//写数据fos.write("java".getBytes());} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{//关闭资源,但是资源之前,首先判断资源对象是否为空if(fos !=null){//开始关闭资源try {fos.close();} catch (IOException e) {e.printStackTrace();} }}}}


2.FileInputStream读取数据

a.操作步骤:

i.创建字节输入流对象
ii.调用read()方法
iii.释放资源

b.字节输入流对象中的读数据的方法:

public int read():一次读取一个字节
public int read(byte[] b):一次读取一个字节数组

i.

import java.io.FileInputStream;import java.io.IOException;public class 读取Demo01 {public static void main(String[] args) throws IOException {//创建字节输入流对象FileInputStream fis = new FileInputStream("读取Demo.txt") ;//public int read(byte[] b):一次读取一个字节数组//定义数组byte[] bys = new byte[5] ;//第一次读取int len = fis.read(bys) ;System.out.println(len);System.out.println(new String(bys));System.out.println(new String(bys,0,len));//第二次读取len = fis.read(bys) ;System.out.println(len);System.out.println(new String(bys));System.out.println(new String(bys,0,len));//第三次读取len = fis.read(bys) ;System.out.println(len);System.out.println(new String(bys));System.out.println(new String(bys,0,len));//第四次len = fis.read(bys) ;System.out.println(len);System.out.println(new String(bys));System.out.println(new String(bys,0,len));}}

ii.
import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class 读取Demo02 {public static void main(String[] args) throws IOException {//创建字节输入流对象FileInputStream fis = new FileInputStream("读取Demo.txt") ;/*跟一次读取一个字节是一样的,读到末尾返回-1这作为他的一个结束条件*///定义字节数组byte[] bys = new byte[115] ; //自己定义的长度int len = 0 ;//一次读取一个字节数组,然后赋值,判断while((len = fis.read(bys))!=-1){//System.out.println(new String(bys));//输出的话:不能直接输出(new String(bys)//正确的输出:new String(bys,0,len)System.out.println(new String(bys,0,len));}}}

iii.终极版本!!!
import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class 读取Demo03 {public static void main(String[] args) throws IOException {//创建字节输入流对象FileInputStream fis = new FileInputStream("读取Demo.txt") ;//读取数据:给定字节数组的长度是1024或者1024的倍数//最终版代码byte[] bys = new byte[1024] ;//定义长度int len = 0;while((len=fis.read(bys)) !=-1){System.out.println(new String(bys,0,len));}}}

3.字节流的复制

需求:在当前项目有一个a.txt文件,然后我要将a.txt文件的内容复制到当前文件下的b.txt文件
分析:
源文件:当前项目下的a.txt--->读数据--->FileInputStream
目的文件:当前项目下的b.txt文件--->写数据--->FileOutputStream
代码:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo1 {
public static void main(String[] args) throws IOException {
//封装源文件
FileInputStream fi = new FileInputStream("src\\IO\\a.txt");
//封装目标文件
FileOutputStream fo = new FileOutputStream("src\\IO\\b.txt");
//一次读取一个字节
int x = 0;
while((x=fi.read())!=-1){
//每次读一个字节,就写一个字节。
fo.write(x);
}
//释放资源
fi.close();
fo.close();
}
}
问题:在实际操作中我们发现使用FileInputStream一次读取一个字节,会出现中文乱码,现在却没有,为什么?
解答:在以前写法中存在强制类型转换,把字节转换成了字符,而一个字符对应2个字节,出现中文乱码;在新的写法中每次都一个字节,写一个字节,并没有强制类型转换,不会有乱码。

4.关于汉字

计算机计算机是何如识别中文这样的字符的?
一个中文对应两个字节。
两个两个进行拼接在一块
第一个字节:确定是否是负数
第二个字节:可以是负数,也可以是整数,对实际是没有影响的
import java.util.Arrays;public class 关于汉字 {public static void main(String[] args) {String s = "abcde";byte[] a = s.getBytes();System.out.println(Arrays.toString(a));//[97, 98, 99, 100, 101]String ss = "是你就好";byte[] b = ss.getBytes();System.out.println(Arrays.toString(b));//[-54, -57, -60, -29, -66, -51, -70, -61]}} 


字节缓存流

1.概述

字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流

2.缓存流(高效流)

BufferedInputStream
BufferedOutputStream

3.BufferOutputStream的构造方法

public BufferedOutputStream(OutputStream out):推荐使用第一种
public BufferedOutputStream(OutputStream out, int size):指定一个缓冲区大小(第二种构造方法不常用,因为第一种构造方法默认的缓冲区大小足够存储数据!)

4.问题:

字节缓冲输出流中为什么不直接将文件的路径或者文件夹的路径作为参数,为什么是OutputSteram?

缓冲流只是为了高效而设计的,只是构建了一个缓冲区,要进行读写操作还需要使用基本的流对象

OutputStream是抽象类,不能直接实例化
BufferOutputStream(new FileOutputStream("路径抽象表现形式"))
属于java的一种设计模式:装饰者设计模式

5.读取数据

在字节缓冲输入流中,在同一个对象中,读取数据只能是一种方式,不能同时使用。
a.一次读取一个字节

b.一次读取一个字节数组

import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.IOException;/*在字节缓冲输入流中,在同一个对象中:读数据只能是一种方式:要么一次读取一个字节,要么就是一次读取一个字节数组不要同时使用*/public class BufferedInputStream类 {public static void main(String[] args) throws IOException {//创建字节缓冲输入流对象//public BufferedInputStream(InputStream in)BufferedInputStream bi = new BufferedInputStream(new FileInputStream("BufferedInputStream类.txt"));//读取数据:一次读取一个字节int x = 0;while((x=bi.read())!=-1){System.out.print((char)x);}bi.close();}}
import java.io.BufferedOutputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class BufferedOutputStream类 {public static void main(String[] args) throws IOException {//public BufferedOutputStream(OutputStream out):推荐使用第一种BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("box.txt")) ;//写数据bos.write("hello".getBytes());//释放资源bos.close();}}

6.效率问的比较

需求:把桌面的一个视频复制到当前项目下
代码:
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/*基本的字节输入流一次读取一个字节:基本的字节输入流一次读取一个字节数组:高效流的字节缓冲输入流一次读取一个字节:高效流的字节缓冲输入流一次读取一个字节数组: */public class 对比 {public static void main(String[] args) throws IOException  {//基本的字节输入流一次读取一个字节:long star = System.currentTimeMillis();//fun1("C:\\Users\\Administrator\\Desktop\\AAA.mp4","bbb.mp4");//耗时:79183毫秒//fun2("C:\\Users\\Administrator\\Desktop\\AAA.mp4","bbb.mp4");//耗时:116毫秒//fun3("C:\\Users\\Administrator\\Desktop\\AAA.mp4","bbb.mp4");//耗时:676毫秒//fun4("C:\\Users\\Administrator\\Desktop\\AAA.mp4","bbb.mp4");//耗时:44毫秒long end = System.currentTimeMillis();System.out.println("耗时:"+(end-star)+"毫秒");}public static void fun4(String star, String end) throws IOException {System.out.println("高效流的字节缓冲输入流一次读取一个字节数组: ");BufferedInputStream bi = new BufferedInputStream(new FileInputStream(star));BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(end));byte[] a = new byte[1024];int len = 0;while((len=bi.read(a))!=-1){bo.write(a, 0, len);}bi.close();bo.close();}public static void fun3(String star, String end) throws IOException {System.out.println("高效流的字节缓冲输入流一次读取一个字节:");BufferedInputStream bi = new BufferedInputStream(new FileInputStream(star));BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(end));int x =0 ;while((x=bi.read())!=-1){bo.write(x);}bi.close();bo.close();}public static void fun2(String star, String end) throws IOException {System.out.println("基本的字节输入流一次读取一个字节数组:");FileInputStream fi = new FileInputStream(star);FileOutputStream fo = new FileOutputStream(end);byte []x=new byte[1024];int len =0;while((len=fi.read(x))!=-1){fo.write(x, 0, len);}fi.close();fo.close();}public static void fun1(String star,String end) throws IOException{System.out.println("基本的字节输入流一次读取一个字节:");FileInputStream fi = new FileInputStream(star);FileOutputStream fo = new FileOutputStream(end);int x = 0;while((x=fi.read())!=-1){fo.write(x);}fi.close();fo.close();}}


结论:
基本的字节输入流一次读取一个字节:耗时:79183毫秒
基本的字节输入流一次读取一个字节数组:耗时:116毫秒
高效流的字节缓冲输入流一次读取一个字节:耗时:676毫秒
高效流的字节缓冲输入流一次读取一个字节数组:耗时:44毫秒
原创粉丝点击