文章目录
一、IO流简介
1、IO
- 输入input
- 输出output
- java.io包为我们提供了相关的API,实现了对所有外部系统的输入输出操作,这就是我们所要学习的技术
2、数据源
数据源分为:
- 源设备:为程序提供数据,一般对应输入流
- 目标设备:程序教程的目的地,一般对应输出流
3、Java中四大IO抽象类
InputStream/OutputStream和Read/Writer类是所有IO流类的抽象父类
InputStream:
(1)简介
- 此抽象类是表示字节输入流的所有类的父类。InputSteam是一个抽象类,它不可以实例
化。 - 数据的读取需要由它的子类来实现。根据节点的不同,它派生了不同的节点流子类,
- 继承自InputSteam的流都是用于向程序中输入数据,且数据的单位为字节(8 bit)。
(2)常用方法:
- int read():
读取一个字节的数据,并将字节的值作为int类型返回(0-255之间的一个值),如果未读出字节则返回-1(返回值为-1表示读取结束). - void close():
关闭输入流对象,释放相关系统资源。
OutputStream:
(1)简介
- 此抽象类是表示字节输出流的所有类的父类,输出流接收输出字节并将这些字节发送到某个目的地。
(2)常用方法
- void write(int n):
向目的地中写入一个字节。 - void close():
关闭输出流对象,释放相关系统资源。
Reader
(1)简介
- 用于读取的字符流抽象类,数据单位为字符。
(2)常用方法
- int read():
读取一个字符的数据,并将字符的值作为int类型返回(0-65535之间的一个值,即Unicode值),如果未读出字符则返回-1(返回值为-1表示读取结束). - void close() :
关闭流对象,释放相关系统资源。
Writer
(1)简介
- 用于输出的字符流抽象类,数据单位为字符
(2)常用方法
- void write(int n):
向输出流中写入一个字符 - void close():
关闭流对象,释放相关系统资源。
4、Java中流的概念细分
(1)按流的方向分类
- 输入流
- 输出流
(2)按处理的数据单元分类
- 字节流
以字节为单位获取数据,命名上以Stream结尾的流,如FileInputStream、FileOutputStream - 字符流
以字符为单位获取数据,命名以Reader/Write结尾的流,如FileReader、FileWriter
(3)按处理对象不同分类
- 节点流
可以直接从数据源或目的地读写数据 ,如FileInputStream、FileReader、DataInputStream - 处理流
不直接连接到数据源或目的地,是处理流的流。通过对其他流的处理提高程序的性能,如BufferedInputStream、BufferedReader,处理流也叫包装流
注意:
节点流处于IO操作的第一线,所有操作必须通过它们进行,处理流可以对节点流进行包装,提高性能或提高程序的灵活性
5、Java中IO流类的体系
- InputStream/OutputStream
字节流的抽象类。 - Reader/Writer
字符流的抽象类。 - FalelnputStream/FileOutputStream
节点流:以字节为单位直接操作*文件"。 - ByteArrayinputStream/ByteArra,OutputStream
节点流:以字节为单位直接操作"字节数组对象"。 - ObjectInputStream/ObjectOutputStream
处理流:以字节为单位直接操作对象”. - DatallnputStream/DataOutputStream
处理流:以字节为单位直接操作"基本数据类型与字符串类型”。 - FaleReader/FileWriter
节点流:以字符为单位直接操作“文本文件”(注意:只能读写文本文件)。 - BufferedReader/BufferedWriter
处理流:将Reader/Writer对象进行包装,增加缓存功能,提高读写效率。 - BufferedlnputStrean/BufferedOutputStream
处理流:将lnputStream/OutputStream对象进行包装。增加缓存功能,提高读写效率。 - lnputStreamReader/OutputStreamwriter
处理流:将字节流对象转化成字符流对象。 - PrintStream
处理流:将OutputStream进行包装,可以方便地输出字符,更加灵活。
二、IO入门案例
1、第一个简单的IO流程序
import java.io.FileInputStream;
public class N1 {
public static void main(String[] args) {
//创建字节输入流对象
FileInputStream fis= null;
try {
fis = new FileInputStream("d:/a.txt");
int s1=fis.read();//打印输入字符a对应的ASCII码值97
int s2=fis.read();
int s3=fis.read();
int s4=fis.read();//由于文件内容已经读取完毕,则返回-1
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
}catch(Exception e) {
e.printStackTrace();
}finally{ //用finally关闭字节流,好处是及时上面出现异常,也会被关闭
if(fis!=null){
try{
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
2、改造入门案例
import java.io.FileInputStream;
public class N2 {
public static void main(String[] args) {
//创建字节输入流对象
FileInputStream fis= null;
try {
fis = new FileInputStream("d:/a.txt");
StringBuilder sb=new StringBuilder(); //1
int temp=0;
while((temp=fis.read())!=-1){
System.out.println(temp);
sb.append((char)temp); //2
}
System.out.println(sb.toString()); //3 字符串的拼接会产生一个StringBuilder的类型,通过StringBuilder调用toString方法转变为String类
}catch(Exception e) {
e.printStackTrace();
}finally{ //用finally关闭字节流,好处是及时上面出现异常,也会被关闭
if(fis!=null){
try{
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
三、File类的使用
1、File类简介
1.1 File类的作用
File类是Java提供的针对磁盘中的文件或目录转换对象的包装类。一个File对象可以代表一个文件或目录,File对象可以实现获取文件和目录属性等功能,可以实现对文件和目录的创建,删除等功能。
1.2 File类操作目录与文件的常用方法
1.2.1针对文件操作的方法
- createNewFile()//创建新文件
- delete()//直接从磁盘上删除文件或目录
- exists()//查询磁盘中的文件是否存在
- getAbsoiutrPath()//获取绝对路径
- getPath()//获取相对路径
- getName()//获取文件名,相当于调用了一个toString方法
- isFile()//判断是否是文件
- length()//查看文件中的字节数
- isHldden()//测试文件的这个抽象路径名是否是一个隐藏文件
import java.io.File;
public class N1 {
public static void main(String[] args)throws Exception {//直接将异常抛出去
//创建File对象
File file=new File("d:/aa.txt");
System.out.println(file.createNewFile());
System.out.println(file.delete());
System.out.println(file.exists());
System.out.println(file.getName());
System.out.println(file.isFile());
System.out.println(file.isHidden());
}
}
1.2.2针对目录操作的方法
- exists()//查询目录是否存在
- isDirectory()//判断当前路径是否为目录
- mkdir()/ /创建目录
- mkdirs()//创建多级目录
- getParentFile()/ /获取当前目录的父级目录。
- list()//返回一个字符串数组,包含目录中的文件和目录的路径名。
- listFiles()/ /返回一个File数组,表示用此抽象路径名表示的目录中的文件。
import java.io.File;
public class N2 {
public static void main(String[] args) {
//创建一个File对象
// File file=new File("d:/a");//创建单极目录
File file=new File("d:/b/c"); // 创建多级目录用mkdirs()
// System.out.println(file.mkdir());
// System.out.println(file.mkdirs());
// System.out.println(file.exists());
//System.out.println(file.isDirectory());
// System.out.println(file.getParent());
//System.out.println(file.getParentFile().getName());
File file2=new File("d:/");//获取d盘下所有的文件目录
String[]arr=file2.list();
for(String temp:arr) {
System.out.println(temp);
}
System.out.println("-----------------");
File[]arr2=file2.listFiles();
for(File temp:arr2){
System.out.println(temp);
}
}
}
四、常用流对象
1、文件字节流
- FileInputstream 通过字节的方式读取文件,适合读取所有类型的文件(图像.视频、文本文件等)。Java也提供了FileReader专门读取文本文件。
- FileOutputStream 通过字节的方式写数据到文件中,适合所有类型的文件。Java 也提供了Filewriter专门写入文本文件。
1.1文件字节输入流
import java.io.FileInputStream;
public class N1 {
public static void main(String[] args) {
FileInputStream fis=null;
try {
//创建文件字节输入流对象
fis = new FileInputStream("d:/6.jpg");//读取的是图片
int temp=0;
while((temp=fis.read())!=-1){
System.out.println(temp);
}
} catch(Exception e){
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
1.2文件字节输出流
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class N2 {
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
try {
//创建文件字节输入流对象
fis = new FileInputStream("d:/6.jpg");
//创建文件字节输出流对象
fos =new FileOutputStream("d:/aa.jpg");
int temp=0;
while((temp=fis.read())!=-1){
fos.write(temp);
}
fos.flush();//将数据从内存中写入到磁盘中
} catch(Exception e){
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
if(fos!=null){
fos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
1.3通过缓冲区提高读写效率
1.3.1方式一
- 通过创建一个指定长度的字节数组作为缓冲区,以此来提高 Io流的读写效率。该方式适用于读取较大图片时的缓冲区定义。
- 注意:缓冲区的长度一定是2的整数幂。一般情况下1024长度较为合适。
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class N3 {
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
try {
//创建文件字节输入流对象
fis = new FileInputStream("d:/6.jpg");
//创建文件字节输出流对象
fos =new FileOutputStream("d:/aa.jpg");
//创建一个缓冲区,提高读写效率
byte[]buff=new byte[1024];
int temp=0;
while((temp=fis.read(buff))!=-1){//
fos.write(buff,0,temp);//
}
fos.flush();//将数据从内存中写入到磁盘中
} catch(Exception e){
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
if(fos!=null){
fos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
1.3.2方式二
- 通过创建一个字节数组作为缓冲区,数组长度是通过输入流对象的availablel()返回当前文件的预估长度来定义的。
- 在读写文件时,是在一次读写操作中完成文件读写操作的。
- 注意:如果文件过大,那么对内存的占用也是比较大的。所以大文件不建议使用该方法。(效率高,占用空间大,用效率换空间)
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class N4{
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
try {
//创建文件字节输入流对象
fis = new FileInputStream("d:/6.jpg");
//创建文件字节输出流对象
fos =new FileOutputStream("d:/aa.jpg");
//创建一个缓冲区,提高读写效率
byte[] buff=new byte[fis.available()];
fis.read(buff);
fos.write(buff);
fos.flush();//将数据从内存中写入到磁盘中
} catch(Exception e){
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
if(fos!=null){
fos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
1.4通过字节缓冲流提高读写效率
- Java缓冲流本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流)上加上缓冲功能提高效率,就像是把别的流包装起来一样,因此缓冲流是一种处理流(包装流)。
- 当对文件或者其他数据源进行频繁的读写操作时,效率比较低,这时如果使用缓冲流就能够更高效的读写信息。因为缓冲流是先将数据缓存起来,然后当缓存区存满后或者手动刷新时再一次性的读取到程序或写入目的地。
- 因此,缓冲流还是很重要的,我们在IO操作时记得加上缓冲流来提升性能。
- BufferedInputStream和 BufferedOutputStream这两个流是缓冲字节流,通过内部缓存数组来提高操作流的效率。
import java.io.*;
public class N5{
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null
try {
//创建文件字节输入流对象
fis = new FileInputStream("d:/6.jpg");
bis = new BufferedInputStream(fis);
fos =new FileOutputStream("d:/aa.jpg");
bos = new BufferedOutputStream(fos);
int temp=0;
while((temp=bis.read())!=-1){
bos.write(temp);
}
bos.flush();
} catch(Exception e){
e.printStackTrace();
}finally{
try {//关闭流的顺序:后开的先关闭
if(bis!=null){
bis.close();
}
if(fis!=null){
fis.close();
}
if(bos!=null){
bos.close();
}
if(fos!=null){
fos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
1.5定义文件拷贝工具类
public class N6{
public static void main(String[] args){
copyFile("d:/6.jpg","d:/abc.jpg");
}
/**
*文件拷贝方法
*/
public static void copyFile(String src,String des){
FileInputStream fis=null;
FileOutputStream fos=null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null
try {
//创建文件字节输入流对象
fis = new FileInputStream(src;
bis = new BufferedInputStream(fis);
fos =new FileOutputStream(des);
bos = new BufferedOutputStream(fos);
int temp=0;
while((temp=bis.read())!=-1){
bos.write(temp);
}
bos.flush();
} catch(Exception e){
e.printStackTrace();
}finally{
try {//关闭流的顺序:后开的先关闭
if(bis!=null){
bis.close();
}
if(fis!=null){
fis.close();
}
if(bos!=null){
bos.close();
}
if(fos!=null){
fos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
2、文件字符流
- 前面介绍的文件字节流可以处理所有文件,如果我们处理的是文本文件,也可以使用文件字符流,它以字符为单位进行操作
2.1文件字符输入输出流
public class N1 {
public static void main(String[] args) {
FileReader frd=null;
try {
//创建文件字节输入流对象
frd = new FileReader("d:/6.txt");
int temp=0;
while((temp=frd.read()) !=-1){
System.out.println(temp);
} catch(Exception e){
e.printStackTrace();
}finally{
try {
if(frd!=null){
frd.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public class N1 {
public static void main(String[] args) {
FileWriter fw=null;
try {
//创建文件字节输入流对象
fw = new FileWriter("d:/6.txt");
fw.write("hello");
fw.write("hello\r\n");// \r\n 回车换行
fw.flush();
} catch(Exception e){
e.printStackTrace();
}finally{
try {
if(fw!=null){
fw.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
2.2使用字符流实现文件的拷贝处理
- 第一种:
frd=new FileReader("d:/a.txt");
//创建文件字符输出流对象
fw =new FileWriter("d:/b.txt");
int temp=0;
while((temp=frd.read()) !=-1){
fw.write(temp);
}
fw.flush();
- 第二种:
//创建文件字符输入流对象
frd=new FileReader("d:/a.txt");
//创建文件字符输出流对象
fw =new FileWriter("d:/b.txt");
char[] buffer=new char[1024];
int temp=0;
while((temp=frd.read()) !=-1){
fw.write(buffer,0,1024);
}
fw.flush();
2.3字符缓冲流
- BufferedReader/BufferedWriter增加了缓存机制,大大提高了读写文本文件的效率。
2.3.1字符输入缓冲流
- BufferedReader是针对字符输入流的缓冲流对象,提供了更方便的按行读取的方法:readLine();在使用字符流读取文本文件时,我们可以使用该方法以行为单位进行读取。
fr = new FileReader("d:/a.txt");
br = new BufferedReader(fr);
String temp ="";
while((temp = br.readLine())!=null){
System.out.println(temp);I
}
2.3.2字符输出缓冲流
- BufferedWriter是针对字符输出流的缓冲流对象,在字符输出缓冲流中可以使用newLine()方法实现换行处理。
fw = new FileWriter("d:/a.txt");
bw =new BufferedWriter(fw);
bw.write("hello");
bw.newLine();
bw.write("hi");
bw.flush();
2.3.3通过字符缓冲流实现文本文件的拷贝
public static void copyFile(String src,String des) {
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader (new FileReader(src));
bw = new BufferedWriter(new FileWriter(des));
String temp ="";
while((temp =br.readLine()) != null){
}bw.write(temp);
bw.newLine();
}
bw.flush();
2.3.4通过字符缓冲流为文件中的内容添加行号
br = new BufferedReader(new FileReader("d:/sxt2");
bw = new BufferedWriter(new FileWriter("d:/sxt3");
String temp="";
int i=1;
while((temp =br.readLine())!= null){
bw.write(i+","+temp);
bw.newLine();
i++;
}
bw.flush();
2.4转换流
- InputStreamReader/OutputStreamWriter用来实现将字节流转化成字符流。比如,如下场景:
- System.in是字节流对象,代表键盘的输入,如果我们想按行接收用户的输入时,就必须用到缓冲字符流 BufferedReader 特有的方法 readline(),但是经过观察会发现在创建BufferedReader 的构造方法的参数必须是一个Reader对象,这时候我们的转换流InputStreamReader就派上用场了。
- 而 System.out 也是字节流对象,代表输出到显示器,按行读取用户的输入后,并且要将读取的一行字符串直接显示到控制台,就需要用到字符流的 write(String str)方法,所以我们要使用OutputStreamWriter将字节流转化为字符流。
2.4.1、通过转换流实现键盘输入屏幕输出
try(
br =new BufferedReader (new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
while(true){
bw.write("请输入:");
String input =br.readLine();
bw.write("你输入的是:"+input);
bw.newLine();
i++;
bw.flush();
}
2.4.2、通过字节流读取文本并添加行号
try{
br = new BufferedReader (new InputStreamReader (new FileInputStream("d:/a.txt")));
bw =new BufferedWriter(new OutputStreamWriter(new FileOutputSteam("d:/b.txt")));
String temp ="";
int i=1;
while((temp =br.readLine())!= null){
bw.write(str:i+","+temp);
bw.newLine();
i++;
} I
bw.flush();
2.5、字符输出流
- 在Java的1O流中专门提供了用于字符输出的流对象 PrintWriter。该对象具有自动行刷
- 新缓冲字符输出流,特点是可以按行写出字符串,并且可通过println()方法实现自动换行。
try{
br =new BufferedReader (new InputStreamReader (new FileInputStream("d:/a.txt")));
pw =new PrintWriter("d:/sxt4.txt");
String temp ="";
int i= 1;
while((temp = br.readLine())!=null)(
pw.println(i+","+temp);
i++;
}
2.6、字节数组流
- ByteArrayInputStream和 ByteArrayOutputStream经常用在需要流和数组之间转化的情况。
2.6.1、字节数组输入流
- FilelnputStream是把文件当做数据源。ByteArrayInputStream则是把内存中的”字节数组对象”当做数据源。
byte[] arr="abcdefg".getBytes();
ByteArrayInputStream bis = null;
StringBuilder sb = new StringBuilder();
try{
//该构造方法的参数是一个字节数组,这个字节数组就是数据源
bis = new ByteArrayInputStream(arr);
int temp =0;
while((temp = bis.read()) !=-1){
sb.append((char)temp);
}
System.out.println(sb.toString());
}
2.6.2、字节数组输出流
- ByteArrayOutputStream流对象是将流中的数据写入到字节数组中。
try{
StringBuilder sb = new StringBuilder();
bos = new ByteArrayOutputStream();
bos.write('a');
bos.write('b');
bos.write('c');
byte[] arr = bos.toByteArray();
for(int i=0;i<arr.length;i++){
sb.append((char)arr[i]);
}
System.out.println(sb.toString());
}
2.7、 数据流
- 数据流将其基本数据类型与字符串类型作为数据源,从而允许程序以与机器无关的方式从底层输入输出流中操作Java基本数据类型与字符串类型
- DatalnputStream和 DataOutputStream提供了可以存其基本数据类型与字符类型取与机器无关的所有Java基础类型数据(如:int、double、String等)的方法。
2.7.1、数据输出流
DataOutputStream dos=null;
try{
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("d:/a.txt")));
dos.writeChar('a');
dos.writeInt(10);
dos.writeDouble(Math.random());
dos.writeBoolean(true);
dos.writeUTF("你好");
dos.flush();
}
2.7.2、数据输入流
DataInputStream dis = null;
try{
dis = new DataInputStream(new BufferedInputStream(new FileInputStream("d:/a.txt")));
//直接读取数据,注意:读取的顺序要与写入的顺序一致,否则不能正确读取System.out.println("char:"+dis.readChar());
System.out.println("int: "+dis.readInt());
System.out.println("double: "+dis.readDouble());
System.out.println("boolean:"+dis.readBoolean());
System.out.println("String: "tdis.readUTF());
}
2.8 、对象流
- 对象的本质是用来组织和存储数据的,对象本身也是数据。那么,能不能将对象存储到硬盘上的文件中呢?能不能将对象通过网络传输到另一个电脑呢?我们可以通过序列化和反序列化来实现这些需求。
2.8.1、Java对象的序列化和反序列化
-
序列化和反序列化是什么
-
当两个进程远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。比如,我们可以通过http 协议发送字符串信息;我们也可以在网络上直接发送Java对象。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象才能正常读取。
-
把Java对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为Java对象的过程称为对象的反序列化
-
对象序列化的作用有如下两种:
口持久化:把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中。
网络通信:在网络上传送对象的字节序列。比如:服务器之间的数据通信、对象传递。 -
序列化涉及的类和接口
ObjectOutputStream代表对象输出流,它的 writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
ObjectInputStream 代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
只有实现了Serializable接口的类的对象才能被序列化。Serializable接口是一个空接口,只起到标记作用。
2.8.2、操作基本数据类型
- 我们前边学到的数据流只能实现对基本数据类型和字符串类型的读写,并不能对Java对象进行读写操作(字符串除外),但是在对象流中除了能实现对基本数据类型进行读写操作以外,还可以对Java对象进行读写操作。
基本数据类型数据
ObjectOutputStream oos = null;
try{
oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("d:/a.txt")));
oos.writeInt( 10);
oos.writeDouble(Math.random());
oos.writeChar('a');
oos.writeBoolean( true);
oos.writeUTF("你好");
oos.flush();
}
读取基本数据类型数据
ObjectInputStream ois=null;
try{
ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("d:/a.txt")));
//必须要按照写入的顺序读取数据
System.out.println("int: "+ois.readInt());
System.out.println("double:"tois.readDouble());
System.out.println("char: "tois.readChar());
System.out.println("boolean:"+ois.readBoolean()); Svstem.out.println("String:"tois,readUTF();
}
2.8.3、操作对象将对象序列化到文件
- ObjectOutputStream可以将一个内存中的Java对象通过序列化的方式写入到磁盘的文件中。被序列化的对象必须要实现Serializable序列化接口,否则会抛出异常。
- 1 创建对象
public class Users implements Serializable {
private int userid;
privateString username;
privateString userage;
public Users(int userid, String username, String userage) {
this.userid = userid;
this.username = username;
this.userage = userage;
}
public Users(){
}
public int getUserid() {
return userid;
}
- 2 序列化对象
ObjectOutputStream oos = null;
try{
oos = new ObjectOutputStream(new FileOutputStream("d:/a.txt")));
Users users = new Users(1,"xz","18");
oos.writeObject(users);
oos.flush();
}
- 3 将对象反序列化到内存中
ObjectInputStream ois =null;
try{
ois = new ObjectInputStream(new FileInputStream("d:/a.txt")));
Users users = (Users)ois.readObject();
System.out.println(users.getUserid()+"\t"+users.getUsername()+"\t"+users.getUserage());
}
2.9、随机访问流
-
RandomAccessFile 可以实现两个作用:
-
实现对一个文件做读和写的操作。
可以访问文件的任意位置。不像其他流只能按照先后顺序读取. -
RandomAccessFile(String name, String mode) name 用来确定文件;mode取r(读)或rw(可读写),通过 mode可以确定流对文件的访问权限。
-
seek(long a)用来定位流对象读写文件的位置,a确定读写位置距离文件开头的字节个数。
-
getFilePointer() 获得流的当前读写位置。
RandomAccessFile raf = null;
try{
raf = new RandomAccessFile("d:/a.txt", "rw");
//将若干数据写入到文件中
int[] arr = new int[] (10, 20, 30,40, 50, 60, 70,80,90,1001);
for(int i=0;i<arr.length;i++){
raf.writeInt(arr[i]);
raf.seek(4);
System.out.println(raf.readInt());}
//隔一个读一个数据
for(int i=0;i<10;i+=2){
raf.seek(i*4);
System.out.print(raf.readInt()+"\t");}
//在第8个字节位置插入一个新的数据45,替换之前的数据30
raf.seek(8);
raf.writeInt(45);
for(int i=0;i<10;i+=2){
raf.seek(i*4);
System.out.print(raf.readInt()+"\t");
}
}
五、Apache IO包
- JDK中提供的文件操作相关的类,但是功能都非常基础,进行复杂操作时需要做大量编程工作。实际开发中,往往需要你自己动手编写相关的代码,尤其在遍历目录文件时,经常用到递归,非常繁琐。Apache-commons工具包中提供了IOUtils/FileUtils,可以让我们非常方便的对文件和目录进行操作。
- Apache lOUtils和 FileUtils类库为我们提供了更加简单、功能更加强大的文件操作和IO流操作功能。
- Apache官方网址:www.apache.org
1、FileUtils的使用
(1)FileUtils类中常用方法:
- cleanDirectory:清空目录,但不删除目录。
- contentEquals:比较两个文件的内容是否相同。
- copyDirectory:将一个目录内容拷贝到另一个目录。可以通过 FileFilter 过滤需要拷贝的文件。
- copyFile:将一个文件拷贝到一个新的地址
- copyFileToDirectory:将一个文件拷贝到某个目录下。
- copyInputStreamToFile:将一个输入流中的内容拷贝到某个文件。
- deleteDirectory:删除目录。
- deleteQuietly:删除文件。
- listFiles:列出指定目录下的所有文件。
- openInputSteam:打开指定文件的输入流。
- readFileToString:将文件内容作为字符串返回。
- readLines:将文件内容按行返回到一个字符串数组中。
- size:返回文件或目录的大小。
- write:将字符串内容直接写到文件中。 - writeByteArrayToFile:将字节数组内容写到文件中。
- writeLines:将容器中的元素的toString方法返回的内容依次写入文件中。
- writeStringToFile:将字符串内容写到文件中。
(2)FileUtils类的使用
- 例一
public class N1 {
public static void main(String[] args) throws Exception{
// new InputStreamReader(new FileInputStream("e:/666.txt"),"utf-8");
//读取文件按照utf-8的编码读出来,返回一个字符串
String content= FileUtils.readFileToString(new File("e:/666.txt"),"utf-8");
//charsetName指定编码的意思
//content这个字符串就是文本文件中的所有的内容
System.out.println(content);//返回文本文件中所有的内容
}
}
- 例二
public class N2 {
public static void main(String[] args) throws Exception{
//将E盘中a目录中的b目录和a.txt文件拷贝到D盘中
//D盘中可以没有a目录,拷贝过程中会自动创建 //new了一个接口
FileUtils.copyDirectory(new File("e:/a"), new File("d:/a"), new FileFilter() {
@Override//匿名内部类来实现接口中的抽象方法
public boolean accept(File pathname) {//决定在文件拷贝时,哪些文件需要拷贝,哪些不需要拷贝(过滤条件)
if(pathname.isDirectory()||pathname.getName().endsWith("txt")){
return true;
}
return false;
}
});
}
}
2、 IOUtils的使用
IOUtils类中常用方法:
- buffer方法:将传入的流进行包装,变成缓冲流。并可以通过参数指定缓冲大小。
- closeQueitly 方法:关闭流。
- contentEquals方法:比较两个流中的内容是否一致。
- copy 方法:将输入流中的内容拷贝到输出流中,并可以指定字符编码。
- copyLarge 方法:将输入流中的内容拷贝到输出流中,适合大于2G内容的拷贝。
- linelterator方法:返回可以迭代每一行内容的迭代器
- read方法:将输入流中的部分内容读入到字节数组中。
- readFully方法:将输入流中的所有内容读入到字节数组中。
- readLine方法:读入输入流内容中的一行。
- toBufferedInputStream,toBufferedReader:将输入转为带缓存的输入流
- toString:将输入流或数组中的内容转化为字符串
- toByteArray,toCharArray:将输入流的内容转为字节数组、字符数组。
- write方法:向流里面写入内容。
- writeLine 方法:向流里面写入一行内容。
public class N {
public static void main(String[] args)throws Exception {
String content= IOUtils.toString(new FileInputStream("e:/666.txt"),"utf-8");
System.out.println(content);
}
}