1.什么是IO流
流: 一种比喻.把数据传输的过程比喻成流
I: Input 输入流
O: Output 输出流
2.IO流的分类
a.根据流的流向:
输入流
输出流
b.根类流操作的数据类型:
字节流
字符流
3.Java中IO的四大流
字节输出流: OutputStream(抽象类)
字节输入流: InputStream(抽象类)
字符输出流: Writer(抽象类)
字符输入流: Reader(抽象类)
Java中所有的流都是以上四种的某一种的子类,并且所有流的命名是非常规范:
流的命名: 功能+父类名
比如:
FileWriter: 向文件中写以字符为单位的数据
FileOutputStream:向文件中写以字节为单位的数据
4.字节流
- 万物皆对象和IO流一切皆字节
在学习Java时,万物皆对象思想!
在学习IO流时,一切皆字节!!
我们电脑上所有文件的底层最终都是字节(都是010101二进制)
注意:
a.为什么打开文件后看到的不是010101呢?
因为我们是用软件打开他的,软件会将0101进行解析,解析成对应的文字,图片,声音,画面等…
b.能不能不用解析,就想看到0101这些数据呢?
可以!使用二进制查看器软件即可打开!BinaryViewer!
- 字节输出流
顶层父类: OutputStream (抽象类)
共性方法:
public void close();//关闭该流,释放资源
public void flush();//刷新缓冲区(对于字节输出流来说没用!!)
public void write(int b);//写一个字节
public void write(byte[] bs);//写一堆字节
public void write(byte[] bs,int startIndex,int length);//写一堆字节的一部分
- FileOutputStream类的使用
文件的字节输出流:向文件中写以字节为单位的数据!!
a.构造方法
public FileOutputStream(String filepath);//指定文件路径
public FileOutputStream(File file);//指定文件对象
/**
* FileOutputStream的构造方法
*/
public class FileOutputStreamDemo01 {
public static void main(String[] args) throws FileNotFoundException {
//1.创建FileOutputStream对象
FileOutputStream fos = new FileOutputStream("1.txt");
// FileOutputStream fos = new FileOutputStream(new File("1.txt"));
/**
* 以上构造干了三件事!
* a.创建对象fos
* b.判断文件是否存在
* 如果存在,清空文件内容
* 如果不存在,则自动创建一个
* c.让对象fos和文件1.txt绑定在一起
*/
}
}
b.写字节数据的三个方法
public void write(int b);//写一个字节
public void write(byte[] bs);//写一堆字节
public void write(byte[] bs,int startIndex,int length);//写一堆字节的一部分
/**
* FileOutputStream的write方法
*/
public class FileOutputStreamDemo02 {
public static void main(String[] args) throws IOException {
//1.创建FileOutputStream对象
FileOutputStream fos = new FileOutputStream("1.txt");
//2.写字节数据
//a.写一个字节
fos.write(97);//0110 0001
//问题:我想打开1.txt之后看到97,怎么做??
fos.write(57);
fos.write(55);
//b.写一堆字节
byte[] bs = {106,97,118,97};
fos.write(bs);
//问题:我想向文件中写入 ILOVEJAVAHELLOWORLD
byte[] bs1 = "ILoveJava!HelloWorld".getBytes();
fos.write(bs1);
//c.写一堆字节的一部分
byte[] bs2 = {106,97,118,97};
fos.write(bs2,1,2);
}
}
c.如何追加续写
非常简单!! 只要使用下面的构造即可!!
public FileOutputStream(String filepath,boolean append);//指定文件路径
public FileOutputStream(File file,boolean append);//指定文件对象
/**
* FileOutputStream的追加/续写
*/
public class FileOutputStreamDemo03 {
public static void main(String[] args) throws IOException {
//1.创建FileOutputStream对象
FileOutputStream fos = new FileOutputStream("1.txt",true);//true就代表追加
//追加写入
fos.write("Java".getBytes());
}
}
d.如何换行
非常简单,只需要向文件中写入代表换行的字节即可
windows: \r\n
Linux: \n
mac: \r
/**
* FileOutputStream的换行
*/
public class FileOutputStreamDemo04 {
public static void main(String[] args) throws IOException {
//1.创建FileOutputStream对象
FileOutputStream fos = new FileOutputStream("2.txt");
for (int i = 0; i < 10; i++) {
fos.write("Java\r\n".getBytes());
// fos.write("\r\n".getBytes());
}
}
}
close和flush
close方法,称为释放资源
注意:当某个流使用完毕之后,务必释放资源
flush方法,称为刷新缓冲区
- .字节输入流InputStream
顶层父类:InputStream(抽象类)
共性方法:
public void close();释放资源
public int read();//读取一个字节
public int read(byte[] bs);//读取一堆字节,返回值代表实际读取的字节个数
- FileInputStream类的使用
文件的字节输入流:从文件中以字节为单位读取数据
a.构造方法
public FileInputStream(String filepath);指定文件路径
public FileInputStream(File file);指定文件对象
/**
* FileInputStream的构造方法
*/
public class FileInputStreamDemo01 {
public static void main(String[] args) throws FileNotFoundException {
//1.创建FileInputStream对象
FileInputStream fis = new FileInputStream("1.txt");
// FileInputStream fis = new FileInputStream(new File("1.txt"));
/**
* 以上构造干了三件事!!
* a.创建对象fis
* b.判断文件是否存在
* 如果存在,就存在,不会清空!!!
* 如果不存在,直接抛出FileNotFoundException异常
* c.绑定fis和1.txt
*/
}
}
b.读取一个字节
/**
* FileInputStream的read
*/
public class FileInputStreamDemo02 {
public static void main(String[] args) throws IOException {
//1.创建FileInputStream对象
FileInputStream fis = new FileInputStream("1.txt");
//2.一次读取一个字节
//int b = fis.read();
//System.out.println((char)b);
//==========一次读取一个字节的标准循环代码===========
int b = 0;//用来保存读取的字节
/**
* (b = fis.read()) != -1
* 以上代码干了三件事!!
* a.先读 fis.read()
* b.赋值 b = 读到的字节
* c.判断 b != -1
*/
while ((b = fis.read()) != -1) {
System.out.println((char) b);
}
//3.释放资源
fis.close();
}
}
c.读取一个字节数组
/**
* FileInputStream的read
*/
public class FileInputStreamDemo03 {
public static void main(String[] args) throws IOException {
//1.创建FileInputStream对象
FileInputStream fis = new FileInputStream("1.txt");
//2.一读取一个字节数组
// byte[] bs = new byte[4];
// int len = fis.read(bs);
// System.out.println("本次读取"+len+"个字节!");
// System.out.println("内容是:"+ new String(bs,0,len));
//=========一次读取一个字节数组的标准循环代码==========
byte[] bs = new byte[4];
int len = 0;
/**
* (len = fis.read(bs)) != -1
* 以上代码干了三件事!
* a.读取 fis.read(bs)
* b.赋值 len = 实际读取的个数
* c.判断 len != -1
*/
while ((len = fis.read(bs)) != -1) {
System.out.print(new String(bs,0,len));
}
//3.释放资源
fis.close();
}
}
- 字节流练习:复制图片[笔试题]
a.复制文件的过程(画图)
b.代码实现(代码演示)
public class CopyFileDemo {
public static void main(String[] args) throws Exception {
//源文件:G:\\upload\\444.png
//目标文件: copy.png
long start = System.currentTimeMillis();
copy02();
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end-start)+"毫秒");
}
/**
* 一次读取一个字节数组
* 耗时:8毫秒
*/
public static void copy02() throws IOException {
//1.创建 两个流
FileInputStream fis = new FileInputStream("G:\\upload\\444.png");
FileOutputStream fos = new FileOutputStream("copy.png");
//2.复制
byte[] bs = new byte[1024];
int len = 0;
while ((len = fis.read(bs)) != -1) {
fos.write(bs,0,len);
}
//3.释放资源
fos.close();
fis.close();
}
/**
* 一次读取一个字节
* 耗时:4401毫秒
*/
public static void copy01() throws Exception {
//1.创建 两个流
FileInputStream fis = new FileInputStream("G:\\upload\\444.png");
FileOutputStream fos = new FileOutputStream("copy.png");
//2.复制
int b = 0;
while ((b = fis.read()) != -1) {
fos.write(b);
}
//3.释放资源
fos.close();
fis.close();
}
}