简述java IO流
目录
- I/O是Input/Output的缩写, I/O技术是非常实用的技术,如读/写文 件,网络通讯等等。
- 流(Stream)是指从源节点到目标节点的数据流动。
- 源节点和目标节点可以是文件、网络、内存、键盘、显示器等等。
- 源节点的数据流称为输入流(用来读取数据)。
- 目标节点的数据流称为输出流(用来写入数据)
一、IO 流的分类
1、按流向不同:
输入流
输出流(以程序为主体)
2、按数据不同:
字节流(字符流用于操作文本文件 .txt .java)
字符流(字节流用于操作非文本文件 .avi .jpg )
3、按角色不同:
节点流
处理流
字节与字符的区别
**字节(**Byte)是计量单位,表示数据量多少,是计算机信息技术用于计量存储容量的一种计量单位,通常情况下一字节等于八位。
字符(Character)计算机中使用的字母、数字、字和符号,比如’A’、‘B’、’$’、’&'等。
Java中字符是采用Unicode标准,Unicode 编码中,一个英文为一个字节,一个中文为两个字节,而在UTF-8编码中,一个中文字符是3个字节
其实字节流可以处理一切文件,而字符流只能处理纯文本文件,因为字字符的底层也是字节
二、IO 流体系
抽象基类 节点流
InputStream FileInputStream
OutputStream FileOutputStream
Reader FileReader
Writer FileWriter
例子:用 FileInputStream读取文本 先创建文件li.text ,内容为 you are beautiful
public void test1(){
FileInputStream file = null;
try {
//1. 创建 FileInputStream 的实例,同时打开指定的文件
file = new FileInputStream("D:\\Programming\\Code\\day01\\exer003\\src\\li.text");
//2. 读取指定文件的内容
byte[] bytes = new byte[3]; //指定读取字节数
int len=0;
while ((len=file.read(bytes)) != -1) //read()读取的一定数量字节数,并将它们存储到bytes中,返回读取字节的个数,若没有数据读取则返回-1
{
System.out.print(new String(bytes,0,len)); //将bytes中0,到len长度的字符转为String
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (file != null)
{
//3. 关闭流
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
you are beautiful
用 FileOutputStream 写入文件
@Test
public void test2()
{
String s="人面桃花相映红";
FileOutputStream file = null;
try {
//1. 创建 FileInputStream 的实例,同时打开指定的文件
file = new FileOutputStream("./li2.text"); // ./表示当前目录下的先对路径,用@Test则为当前模块的路径,
//若是用main方法,则为当前工程的路径
//2. 将文件内容写到指定位置
file.write(s.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (file!=null)
{
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
非文本文件的复制
@Test
public void test3(){
String src = "C:\\Users\\library\\Desktop\\7.jpg"; //自己硬盘上的文件地址
String dest = "C:\\Users\\library\\Desktop\\9.jpg"; //复制后的地址
copyFile(src, dest);
}
private void copyFile(String src, String dest) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//1. 创建 FileInputStream 的实例,同时打开指定文件
fis = new FileInputStream(src);
//2. 创建 FileOutputStream 的实例,同时打开指定文件
fos = new FileOutputStream(dest);
//3. 读取指定文件的内容
byte[] b = new byte[1024];
int len = 0;
while ((len=fis.read(b))!=-1)
{
fos.write(b,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (fos != null)
{
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null)
{
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、节点流和处理流
节点流:直接操作数据读写的流类,比如FileInputStream
处理流:对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能
通常很少使用单个流对象,而是将一系列的流以包装的形式链接起来处理数据。 包装可以在不改变被包装流的前提下,获得更强的流处理功能。
1)处理流之一:缓冲流
-
为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流 类时,会创建一个内部缓冲区数组
-
根据数据操作单位可以把缓冲流分为:
➢BufferedInputStream 和 BufferedOutputStream
➢BufferedReader 和 BufferedWriter
-
缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高 了读写的效率,同时增加了一些新的方法
-
对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中 的数据立刻写出
简单来说,缓冲流的作用就是为了提高节点流的效率
抽象基类 节点流 缓冲流
InputStream FileInputStream BufferedInputStream
OutputStream FileOutputStream BufferedOutputStream(flush()-强制清空缓冲区)
Reader FileReader BufferedReader(readLine())
Writer FileWriter BufferedWriter(newLine())
//使用缓冲流完成非文本文件的复制
@Test
public void test1()
{
String src = "C:\\Users\\library\\Desktop\\7.jpg";
String dest = "C:\\Users\\library\\Desktop\\9.jpg";
copyFile(src, dest);
}
private void copyFile(String src, String dest) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1. 创建 FileReader 的实例,同时打开指定文件
FileInputStream fis = new FileInputStream(src);
//2. 创建 FileWriter 的实例,同时打开指定文件
FileOutputStream fos = new FileOutputStream(dest);
//3. 创建 BufferedReader 包装对应的节点流,用于提高效率
bis = new BufferedInputStream(fis);
//4. 创建 BufferedWriter 包装对应的节点流,用于提高效率
bos = new BufferedOutputStream(fos);
//5. 读取指定文件的内容
byte[] b = new byte[1024];
int len=0;
while ((len= bis.read(b))!=-1)
{
bos.write(b,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性从 文件中读取8192个(8Kb),存在缓冲区中,直到缓冲区装满了,才重新从文件中 读取下一个8192个字节数组。
向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法 flush()可以强制将缓冲区的内容全部写入输出流
关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也 会相应关闭内层节点流
flush()方法的使用:手动将buffer中内容写入文件
如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷 新缓冲区,关闭后不能再写出
在文件够大的时候可以明显的看到缓冲流的效率会远大于字节流,提高效率的原因是缓冲流提供了一个大小为 8192字节的缓冲区
private static int DEFAULT_BUFFER_SIZE = 8192;
至于文本文件的复制,其实都一样,就不写了哈
2)处理流之二:标准输入、输出流(了解)
System.in和System.out分别代表了系统标准的输入和输出设备
默认输入设备是:键盘,输出设备是:显示器
System.in的类型是InputStream
System.out的类型是PrintStream,其是OutputStream的子类 FilterOutputStream 的子类
重定向:通过System类的setIn,setOut方法对默认设备进行改变。
public static void setIn(InputStream in)
public static void setOut(PrintStream out)
3)处理流之二:转换流
转换流提供了在字节流和字符流之间的转换
Java API提供了两个转换流:
InputStreamReader:将InputStream转换为Reader
OutputStreamWriter:将Writer转换为OutputStream
字节流中的数据都是字符时,转成字符流操作更高效。
InputStreamReader
实现将字节的输入流按指定字符集转换为字符的输入流。
需要和InputStream“套接”。
构造器:
public InputStreamReader(InputStream in)
public InputSreamReader(InputStream in,String charsetName)
如: Reader isr = new InputStreamReader(System.in,”gbk”);
OutputStreamWriter
用于将要写入到字节流中的字符按指定字符集编码成字节。
需要和 OutputStream“套接”。
构造器 :
public OutputStreamWriter(OutputStream out)
public OutputSreamWriter(OutputStream out,String charsetName)
/**
* 编码
*/
@Test
public void test2()
{
String s="弱水三千,只取一瓢";
BufferedWriter bfr = null;
try {
FileOutputStream fis = new FileOutputStream("./July.txt");
OutputStreamWriter osw = new OutputStreamWriter(fis);
bfr = new BufferedWriter(osw);
bfr.write(s);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bfr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 解码
*/
@Test
public void test3()
{
BufferedReader bur = null;
try {
FileInputStream fis = new FileInputStream("./July.txt");
InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
bur = new BufferedReader(isr);
String s=null;
while ((s=bur.readLine())!=null)
{
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bur.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四、对象流
-
ObjectInputStream和OjbectOutputSteam
用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可 以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
-
序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
-
反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
ObjectOutputStream和ObjectInputStream不能序列化static和 transient修饰的成员变量
对象的序列化
将内存中的对象永久的以二进制形式保存到磁盘中
步骤:
①创建节点流的实例,同时打开指定文件
②(可选)创建缓冲流包装对应的节点流,用于提高传输效率
③创建对象流,包装对应的缓冲流,用于完成对象的序列化
④通过 wirteXxx() 方法完成序列化操作
⑤关闭流
⑥需要序列化对象的类必须实现 java.io.Serializable 接口
⑦提供序列号 private static final long serialVersionUID = 2983723325345L;
-
若某个类实现了 Serializable 接口,该类的对象就是可序列化的:
创建一个 ObjectOutputStream
调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化 对象。注意写出一次,操作flush()
-
反序列化
创建一个 ObjectInputStream 调用 readObject() 方法读取流中的对象
-
强调:如果某个类的字段不是基本数据类型或 String 类型,而是另一个引用 类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也 不能序列化
@Data
class person implements Serializable
{
private Integer age;
private String name;
}
//对象的序列化
@Test
public void test2() {
Person p1 = new Person("张三", 18);
Person p2 = new Person("李四", 20);
ObjectOutputStream oos = null;
try {
FileOutputStream fos = new FileOutputStream("./persons.dat");
BufferedOutputStream bos = new BufferedOutputStream(fos);
oos = new ObjectOutputStream(bos);
oos.writeObject(p1);
oos.writeObject(p2);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//对象的反序列化
@Test
public void test3() {
ObjectInputStream ois = null;
try {
FileInputStream fis = new FileInputStream("./persons.dat");
BufferedInputStream bis = new BufferedInputStream(fis);
ois = new ObjectInputStream(bis);
Person p1 = (Person) ois.readObject();
Person p2 = (Person) ois.readObject();
System.out.println(p1);
System.out.println(p2);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
要实现对象的序列化必须要让对象类实现Serializable
注意:
- 序列化与反序列化的顺序要一致,序列号也要相等
- transient 和 static 修饰的属性不能被序列化
五、File类的使用
java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关
- File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。 如果需要访问文件内容本身,则需要使用输入/输出流。
- 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对 象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
- File对象可以作为参数传递给流的构造器
常用构造器
-
public File(String pathname) 以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果 pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
绝对路径:是一个固定的路径,从盘符开始
相对路径:是相对于某个位置开始
-
public File(String parent,String child) 以parent为父路径,child为子路径创建File对象。
-
public File(File parent,String child) 根据一个父File对象和子文件路径创建File对象
-
路径中的每级目录之间用一个路径分隔符隔开。
常用方法
File类的获取功能
public String getAbsolutePath():获取绝对路径
public String getPath() :获取路径
public String getName() :获取名称
public String getParent():获取上层文件目录路径。若无,返回null
public long length() :获取文件长度(即:字节数)。不能获取目录的长度。
public long lastModified() :获取最后一次的修改时间,毫秒值
public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组
public boolean renameTo(File dest):把文件重命名为指定的文件路径(剪切到指定路径)
@Test
public void test6()
{
File file = new File("./July.txt");
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsoluteFile());
System.out.println(file.getAbsolutePath());
System.out.println(file.getParent());
System.out.println(file.length());
}
July.txt
.\July.txt
D:\Pro\code\day02\exer001\.\July.txt
D:\Pro\code\day02\exer001\.\July.txt
.
27
File类的判断功能
public boolean isDirectory():判断是否是文件目录
public boolean isFile() :判断是否是文件
public boolean exists() :判断是否存在
public boolean canRead() :判断是否可读
public boolean canWrite() :判断是否可写
public boolean isHidden() :判断是否隐藏
File类的创建功能
public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。 如果此文件目录的上层目录不存在,也不创建。
public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
File类的删除功能
public boolean delete():删除文件或者文件夹 删除注意事项: Java中的删除不走回收站。 要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录
这些都是类似的用法,就不一 一罗列了哈
list() 获取目录中所有文件的 String 类型的列表
listFiles() 获取目录中所有文件 File 对象
这两个比较有意思,来看看
list()
File file = new File("D:\\");
String[] list = file.list();
for (String s : list)
{
System.out.println(s);
}
14-Ajax
14ajax课程
360Chrome
360极速浏览器下载
360驱动大师目录
aDrive
listFiles()
File file1=new File("D:\\");
File[] files = file1.listFiles();
for (File f : files)
{
System.out.println(f);
}
D:\14-Ajax
D:\14ajax课程
D:\360Chrome
D:\360极速浏览器下载
D:\360驱动大师目录
D:\aDrive
好了好了,IO流就暂且写到这了,好累啊,学基础真的是太枯燥了,以前学的时候基本就是看个热闹,看完了其实啥也不懂,现在回过头来再把基础的复习一下感觉清晰了不少,就先这样了,还有好多东西要补列,算法,设计模式,MySQL…