Java中IO流的使用

IO流的使用

File类的使用:
  1. File类的一个对象,代表了一个文件或一个文件夹

  2. 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中的删除不走回收站
    
  3. File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,并未涉及到写入或读取文件内容的操作。如需读入或写入内容,必须使用IO流完成

  4. 后续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的使用
  1. RandomAccessFile直接继承于java.lang.Object类,实现了两个接口,DataInput 和 DataOutput

  2. RandomAccessFile既可以作为输出流,又可以作为输入流

    RandomAccessFile raf1 = new RandomAccessFile(new File("11.jpg"),"r");
    RandomAccessFile raf2 = new RandomAccessFile(new File("22.jpg"),"rw");
    
  3. 如果RandomAccessFile作为输出流时,写入到的文件如果不存在,则执行过程中自动创建,如果写出的文件存在,则会对原来的文件内容进行覆盖。(默认情况下,从头覆盖)

  4. 可以通过相关的操作,实现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
说明:
  1. read() 的理解:返回读入的一个字符,如果达到文件的末尾,返回-1
  2. 异常的处理:为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally处理
  3. 读入的文件一定要存在,否则就会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();

说明:

  1. 输出操作,对应的File可以不存在,并不会报异常

  2. 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

转换流(处理流的一种)
  1. InputStreamReader 、 OutputStreamWriter  属于字符流
    
    utf-8.txt(字节流) -->(字节流)InputstreamReader -->程序 -->(字符流)OutputStreamWriter -->(字符流)gbk.txt
  2. 作用:提供字符流和字节流之间的转换

    InputStreamReader:将一个字节的输入流转换为字符的输入流
    OutputStreamWriter:将一个字符的输出流转换为字节的输出流
    
  3. 解码:字节、字节数组----------> 字符数组、字符串

    编码:字符数组、字符串------------> 字节、字节数组

  4. 字符集:

    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个字节表示一个字符
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牧码文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值