IO流的使用
File类的使用:
-
File类的一个对象,代表了一个文件或一个文件夹
-
File类生命在java.io包下
1、如何创建File类的实例:
File(String filePath); File(String parentPath,String childPath); File(File parentFile,String childPath);
2、相对路径和绝对路径
3、路径的分隔符windows:\\ Unix:/
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 isDirectory():判断是否是文件目录 public boolean isFile():判断是否是文件 public boolean exists():判断是否存在
File类的创建功能
public boolean createNewFile():创建文件,若文件存在,则不创建,返回false public boolean mkdir():创建文件目录,如果此文件目录存在,就不创建了 public boolean mkdirs():创建文件目录,如果上层文件目录不存在,一并创建
File类的删除功能
public boolean delete():删除文件或文件夹 注意事项:Java中的删除不走回收站
-
File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,并未涉及到写入或读取文件内容的操作。如需读入或写入内容,必须使用IO流完成
-
后续File类的对象常会作为参数传递到流的构造器中,知名读取或写入的“终点”。
IO流
处理流之六:对象流
ObjectInputStream 和 ObjectOutputStream
- 序列化:用ObjectInputStream类保存基本类型或对象的机制
- 反序列化:用ObjectOutputStream类读取基本类型数据或对象的机制
注意:ObjectInputStream 和 ObjectOutputStream 不能序列化static 和 transient 修饰的成员变量
对象的序列化机制:
- 允许把内存中的Java对象转化成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其他程序获取了这种二进制流,就可以恢复成原来的Java对象
序列化过程:
- 将内存中的Java对象保存到磁盘中或通过网络传输出去。使用ObjectOutputStream实现
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hello.dat"));
oos.writeObject(new String("I'm a Chinese!"));
oos.flush();//刷新操作
oos.close();
反序列化
- 将磁盘文件中的对象还原成内存中的一个java对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hello.dat"));
Object obj = ois.readObject();
String str = (String)obj;
System.out.println(str);
ois.close();
自定义类的序列化和反序列化
想要一个java对象是可序列化的,需要满足相应的要求,以Person类为例:
Person需要满足如下的要求,方可序列化:
-
需要实现接口:Serializable
-
当前类提供一个全局常量:serialVersionUID
public static final long serialVersionUID = 48545485215L;
-
除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性,也必须是可序列化的(默认情况下,基本数据类型可序列化)
补充:ObjectOutputStream 和 ObjectInputStream不能序列化static 和 transient 修饰的成员变量
随机存取文件流:
RandomAccessFile类:
RandomAccessFile的使用
-
RandomAccessFile直接继承于java.lang.Object类,实现了两个接口,DataInput 和 DataOutput
-
RandomAccessFile既可以作为输出流,又可以作为输入流
RandomAccessFile raf1 = new RandomAccessFile(new File("11.jpg"),"r"); RandomAccessFile raf2 = new RandomAccessFile(new File("22.jpg"),"rw");
-
如果RandomAccessFile作为输出流时,写入到的文件如果不存在,则执行过程中自动创建,如果写出的文件存在,则会对原来的文件内容进行覆盖。(默认情况下,从头覆盖)
-
可以通过相关的操作,实现RandomAccessFile"插入"数据的效果
StringBuilder builder = new StringBuilder((int)new File("hello.txt").length()); byte[] buffer = new byte[20]; int len; while((len = raf1.read(buffer)) != -1){ builder.append(new String(buffer,0,len)); } //调回指针,写入"xyz" raf1.seek(3); raf1.write("xyz".getBytes()); //将StringBuilder中的数据写入到文件中 raf1.write(builder.toString().getBytes()); raf1.close();
IO流原理及流的分类
Input / Output 的缩写,用于处理设别之间的数据传输
- 输入:读取外部数据(磁盘,光盘等存储设备的数据)到程序内存中
- 输出:将程序(内存)数据输出到磁盘,光盘等存储设备中
流的分类:
- 按操作数据单位不同:字节流(8bit),字符流(16bit)
- 按数据流的流向不同:输入流,输出流
- 按流的角色的不同:节点流,处理流
抽象基类 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
将hello.txt读入到控制台:
1、实例化File类的对象,指明要操作的文件
File file = new File("hello.txt");
2、提供具体的流
FileReader fr = new FileReader(file);//可能还会异常
3、数据的读入
read():返回读入的一个字符。如果达到文件的末尾,返回-1
int data = fr.read();
while(data != -1){
System.Out.println((char)data);
data = fr.read();
}//可能会异常
4、流的关闭
fr.close();//可能会异常
//第3步可以优化为:
int data;
while((data = fr.read()) != -1){
System.Out.print((Char)data);
}
注意:对于异常的处理,选择try—catch—finally
说明:
- read() 的理解:返回读入的一个字符,如果达到文件的末尾,返回-1
- 异常的处理:为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally处理
- 读入的文件一定要存在,否则就会FileNotFoundException
对read()操作的升级:使用read的重载方法
read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1
读入操作:
方式1:
char[] cbuf = new char[5];
int len;
while((len = fr.read(cbuf)) != -1){
for(int i = 0;i < len;i++){//不可以写i < cbuf.length;
System.Out.print(cbuf[i]);
}
}
方式2:
while((len = fr.read(cbuf)) != -1){
String str = new String(cbuf,o,len);
System.Out.print(str);
}
从内存中写入数据到硬盘的文件中
1、提供File类的对象,指明写出到的文件
File file = new File("hello.txt");
2、提供FileWrite的对象,用于数据的写出
FileWriter fw = new FileWriter(file);//FileWrite(file,true(追加) / fasle(覆盖));
3、写出操作
fw.write("I have a dream");
4、关闭流资源
fw.close();
说明:
-
输出操作,对应的File可以不存在,并不会报异常
-
File对应的硬盘中的文件若不存在,输出的过程中,会自动创建此文件
File对应的硬盘中的文件若存在:
- 如果哦流使用的构造器:FileWriter(file) / FileWriter(file , false),则会对原存文件覆盖
- 如果使用的时FileWriter(file,true)则为追加
将文件读出来再写出去:
1、创建File类的对象,指明读入和写出的文件
File srcFile = new File("Hello.txt");
File destFile = new File("Hello1.txt");
2、创建输入流和输出流的对象
fr = new FileReader(srcFile);
fw = new FileWriter(destFile);
3、数据的读入和写出操作
char[] cbuf = new char[5];
int len;//记录每次读入到cbuf数组中字符个数
while((len = fr.read(cbuf)) != -1){
//每次写出len个字符
fw.writer(cbuf,0,len);
}
4、关闭流资源
fw.close();
fr.close();
字节流的读取:
结论:
- 对于文本文件(.txt .java .c .cpp)使用字符流
- 对于非文本文件(.jpg .mp3 .mp4 .avi .doc .ppt …)使用字节流处理
- 使用字节流FileInputStream处理文本文件,可能出现乱码
实现对图片的复制操作:
1、指定文件
File srcFile = new File("图片1.jpg");
File destFile = new File("图片2.jpg");
2、造流
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new fileOutputStream(destFile);
3、复制的过程
byte[] buffer = new byte[5];
int len;
while((len = fis.read(buffer)) != -1){
fos.write(buffer,0,len);
}
4、关闭流资源
fos.close();
fis.close();
处理流之一:缓冲流:
-
BufferedInputStream
-
BufferedOutputStream
-
BufferedReader
-
BufferedWriter
作用:提供流的读取,写入的速度
1、造文件
File srcFile = new File("图片1.jpg");
File destFile = new File("图片2.jpg");
2、造流
2.1造文件流
FileInputStream fis = new FileInputStream(srcFile);
FileOuutputStream fos = new FileOutputStream(destFile);
2.2造缓冲流
BufferedInputStream bis = new BufferInputStream(fis);
BufferedOutputStream bos = new BufferOutputStream(fos);
3、复制:读取、写入
byte[] buffer = new byte[10];
int len;
while((len = bis.read(buffet)) != -1){
bos.write(buffer,0,len);
}
4、资源的关闭
要求:先关闭外层的流,再关闭内层的流
bos.close();
bis.close();
说明:关闭外层流的同时,内层流也会自动关闭,关于内层流的关闭可以省略
//fos.close();
//fis.close();
处理流,就是“套接”在已有的流的基础上
使用BufferReader 和 BufferWriter 处理文本文件
1、创建文件和相应的流
br = new BufferedReader(new FileReader(new File("dbcp.txt")));
bw = new Bufferediter(new FileWriter(new File("dbcp1.txt")));
2、读写操作
char[] cbuf = new char[1023];
int len;
while((len = br.read(cbuf)) != -1){
bw.write(cbuf,0,len);
}
3、关闭流资源
bw.close();
br.close();
读写的方式二:使用String
String data;
while((data = br.readline()) != -1){
bw.write(data + "/n");//data不包含换行
//也可以
bw.write(data);
bw.newLine();
}
总结:
流的体系结构
抽象基类 节点流(或文件流) 缓冲流(处理流的一种)
InputStream FileInputStream ->byte[] BufferedInputStream
OutputStream FileOutputStream ->byte[] BufferedOutputStream
Reader FileReader ->read(char[] cbuf) BufferedReader
Writer FileWriter ->write(char[] cbuf,0,len) BufferedWriter
转换流(处理流的一种)
-
InputStreamReader 、 OutputStreamWriter 属于字符流
utf-8.txt(字节流) -->(字节流)InputstreamReader -->程序 -->(字符流)OutputStreamWriter -->(字符流)gbk.txt
-
作用:提供字符流和字节流之间的转换
InputStreamReader:将一个字节的输入流转换为字符的输入流 OutputStreamWriter:将一个字符的输出流转换为字节的输出流
-
解码:字节、字节数组----------> 字符数组、字符串
编码:字符数组、字符串------------> 字节、字节数组
-
字符集:
FileInputStream fis = new FileInputstream("dbcp.txt"); InputStreamReader isr = new InputStreamReader(fis,"utf-8"); char[] cbuf = new char[20]; int len; while((len = isr.read(cbuf)) != -1){ String str = new String(cbuf,0,len); System.Out.print(str); } isr.close();
综合使用InputStreamReader 和 OutputStreamWriter
File file1 = new File("dbcp_utf.txt");
File file2 = new File("dbcp_gbk.txt");
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
cahr[] cbuf = new char[20];
int len;
while((len = isr.read(cbuf)) != -1){
osw.write(cbuf,0,len);
}
isr.close();
osw.close();
字符集:
- ASCII:美国标准信息交换码,用一个字节的7位可以表示
- ISO8859-1:拉丁码表,欧洲码表。用一个字节的8位表示
- GB2312:中国的中文编码表。最多两个字节编码所有字符
- GBk:中国的中文编码表升级,融合了更多的中文文字符号。最对两个字节
- Unicode:国际标准码,融合了目前人类使用的所有字符。位每个字符分配唯一的字符码
- UTF-8:变长的编码方式,可用1-4个字节表示一个字符