在java中,将不同的输入输出源通过流的形式进行相关操作(输入,输出),流是一种抽象描述,在程序中表示数据的一种转移方式。将IO比喻为"流",即:stream. 就像生活中的"电流","水流"一样,它是以同一个方向顺序移动的过程.只不过这里流动的是字节(2进制数据).所以在IO中有输入流和输出流之分,我们理解他们是连接程序与另一端的"管道",用于获取或发送数据到另一端
理解:流(stream)
- 按流向分(站在程序角度考虑)
- 输入流(input)
- 输出流(output)
- 按类型分:
- 字节流(InputStream/OutputStream) 任何文件都可以通过字节流进行传输。【最基本的字节输入/输出流,抽象类,定义了读取/写入原始字节的所有基本方法】
- 字符流(Reader/Writer) 非纯文本文件,不能用字符流,会导致文件格式破坏,不能正常执行。
- 节点流(低级流:直接跟输入输出源对接) FileInputStream/FileOutputStream/FileReader/FileWriter/PrintStream/PrintWriter.【节点流的另一端是明确的,是实际读写数据的流,读写一定是建立在节点流的基础上进行的】
- 处理流(高级流:建立在低级流的基础上)
转换流:InputStreamReader、OutputStreamWriter,字节流转字符流/字符流转字节流
缓冲流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedReader可对节点流经行包装,使读写更快
【注】实际应用中,我们可以通过串联一组高级流到某个低级流上以流水线式的加工处理对某设备的数据进行读写,这个过程也成为流的连接,这也是IO的精髓所在.
理解 低级流和高级流关系
常用IO流继承关系图
InputStream:字节输入抽象类(做各个字节输入类的祖先基类)
InputStream
OutputStream:字节输出抽象类(做各个字节输出类的祖先基类)
OutputStream
Reader:字符输入抽象类(做各个字符输入类的祖先基类)
Reader
Writer:字符输出抽象类(做各个字符输出类的最终基类)
Writer
小Demo案例:
- 写入数据到文件中(FileOutputStream-低级流)
//向当前目录下的demo.dat文件中写入数据
/*
FileOutputStream提供的常用构造器
FileOutputStream(String path)
FileOutputStream(File file)
*/
//文件流创建时,如果该文件不存在会自动将其创建(前提是该文件所在目录必须存在!)
FileOutputStream fos = new FileOutputStream("./fos.dat");
/*
void write(int d)
向文件中写入1个字节,写入的内容是给定的int值对应的2进制的"低八位"
int值 1: vvvvvvvv
二进制:00000000 00000000 00000000 00000001
demo.dat文件内容:
00000000
*/
fos.write(1);
/*
vvvvvvvv
00000000 00000000 00000000 00000010
demo.dat文件内容
00000001 00000010
*/
fos.write(2);
fos.close();
- 读取文件数据(FileInputStream-低级流)
/*
int read()
读取一个字节,并一int型返回。返回的整数中读取的字节部分在该整数2进制的最后8位上
如果返回值为整数-1,则表示流读取到了末尾。对于读取文件而言就是EOF(end of file文件末尾)
调用read():
int d = fis.read();
fos.dat文件内容
00000001 00000011
^^^^^^^
读取该字节
返回int值时,2进制样子:
00000000 00000000 00000000 00000001
^^^^^^^
|-----补充24个0(3字节)-----| 读取的字节
返回的int值d就是上述内容
*/
FileInputStream fis = new FileInputStream("fos.dat");
int d = fis.read(); //返回值为整数-1,则表示流读取到了末尾
System.out.println(d);
fis.close();
- 文件复制(低级流实现)
//创建文件输入流读取原文件
FileInputStream fis = new FileInputStream("image.jpg");
//创建文件输出流写入复制文件
FileOutputStream fos = new FileOutputStream("image_cp.jpg");
int d;//保存每次读取到的字节
/*
原文件数据:
11000011 10101010 00001111 11001100 00110011 ...
^^^^^^^
d = fis.read();
d:00000000 00000000 00000000 10101010
fos.write(d);
复制文件的数据:
11000011 10101010
*/
long start = System.currentTimeMillis();//获取当前系统时间的毫秒值(UTC时间)
while((d = fis.read()) != -1) {
fos.write(d);
}
long end = System.currentTimeMillis();//获取当前系统时间的毫秒值(UTC时间)
System.out.println("复制完毕!耗时:" (end-start) "ms");
fis.close();
fos.close();
- 块读写的文件复制操作(byte[] 低级流)
int read(byte[] data); //
一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。
返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。
//块写操作
void write(byte[] data);
一次性将给定的字节数组所有字节写入到文件中
void write(byte[] data,int offset,int len);
一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件
//通过提高每次读写的数据量,减少实际读写的次数,可以提高读写效率。
//单字节读写是一种随机读写形式。而一组一组字节的读写是块读写形式。
//创建文件输入流读取原文件
FileInputStream fis = new FileInputStream("wnwb.exe");
//创建文件输出流写复制文件
FileOutputStream fos = new FileOutputStream("wnwb_cp.exe");
/*
流提供了块读写的方法
int read(byte[] data)
一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。
返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。
*/
int len;//记录每次实际读取的字节量
byte[] data = new byte[1024*10]; //10kb
long start = System.currentTimeMillis(); //获取utc标准时间的毫秒值
while((len = fis.read(data))!=-1){
fos.write(data,0,len);//读取多少就写多少
}
long end = System.currentTimeMillis();
System.out.println("复制完毕!耗时:" (end-start) "ms");
fis.close();
fos.close(); //流使用完毕后 须关闭
- 写入文本数据(getBytes() 低级流)
//String提供方法:
byte[] getBytes(String charsetName);
将当前字符串转换为一组字节
参数为字符集的名字,常用的是UTF-8。 其中中文字3字节表示1个,英文1字节表示1个。
//UTF-8: char是2字节,3z字节表示,就是拆开以 1110xxxx 10xxxx 10xxxx 把2字节分开写入x位置.
//当第二个参数传入true时,文件流为追加模式,即:指定的文件若存在,
// 则原有数据保留,新写入的数据会被顺序的追加到文件中
FileOutputStream fos = new FileOutputStream("demo.txt",true);
String str = "企业订单发布会,全球贸易交流";
byte[] data = str.getBytes("UTF-8"); //把字符转成字节
fos.write(data); //传入上面定义的字符串
fos.write("八月正午的阳光,都没你耀眼。".getBytes("UTF-8"));
System.out.println("写出完毕!");
fos.close(); //写完要关闭流
- 读取文本数据(低级流)
FileInputStream fis = new FileInputStream("fos.txt");
byte[] data = new byte[1024];
int len = fis.read(data);//块读操作
System.out.println("实际读取到了" len "个字节");
/*
String提供了将字节数组转换为字符串的构造方法:
String(byte[]data,String charsetName)
将给定的字节数组中所有字节按照指定的字符集转换为字符串
String(byte[]data,int offset,int len,String charsetName)
将给定的字节数组从下标offset处开始的连续len个字节按照指定的字符集转换为字符串
*/
String line = new String(data,0,len,"UTF-8"); //String 提供的方法
System.out.println(line);
System.out.println(line.length());
fis.close();
学习记录,如有侵权请联系删除。
,