Java基础-IO流
一、概述
java的io可以方便的实现数据的输入和输出操作。在java中把不同的输入源、输出源(键盘,鼠标,网络连接等)抽象表述为“流”。java可以通过流的方式访问,修改这些源。
分类:
- 按流向分
- 输入流
- 输出流
- 按操作单元分
- 字节流(8位)
- 字符流(16位)
二、File类
1、常用构造方法
File(String pathname)
通过给定路径名创建file实例
File(String parent, String child)
通过parent、child路径名创建file实例
2、构造实例
使用第一种构造方法构造
public static void main(String[] args) throws IOException {
File jj = new File("E:\\test\\cc.txt");
final boolean newFile = jj.createNewFile();
}
之后在E盘的test目录下会出现cc.txt文件
使用第二种方法构造
public static void main(String[] args) throws IOException {
File jj = new File("E:\\test","mm.txt");
final boolean newFile = jj.createNewFile();
}
这种方式第一个参数要传入父路径,第二个是子路径,执行完后在test目录下出现mm.txt文件
3、常用方法
getpath,getAbsolutePath,getCanonicalPath的区别。
下面举个例子
File lily = new File("../zz.txt");
System.out.println(lily.getPath());
System.out.println(lily.getAbsolutePath());
System.out.println(lily.getCanonicalPath());
getpath中获得的就是你file中给他传的路径
getAbsolutePath是当前目录+你给其传的路径
getCanonicalPath是真正的路径
4、相对路径与绝对路径
绝对路径
绝对路径就是你的主页上的文件或目录在硬盘上真正的路径,(URL和物理路径)例如:
C:\zjj\test.txt 代表了test.txt文件的绝对路径。
http://www.sun.com/index.htm也代表了一个URL绝对路径。
相对路径
相对与某个基准目录的路径。包含Web的相对路径(HTML中的相对目录),例如:在
Servlet中,"/“代表Web应用的根目录。和物理路径的相对表示,例如:”./" 代表当前目录,
"…/"代表上级目录。这种类似的表示,也是属于相对路径。
5、遍历目录内所有文件
public static void main(String[] args) throws IOException {
File mm = new File("E:\\l");
File[] list = mm.listFiles(); //拿到所有下一级的File文件
GetAllFiles(list);
}
public static void GetAllFiles(File[] jj) throws IOException {
if(jj==null){
throw new IllegalArgumentException("dir not found dir");
}
for (File file : jj) {
if(file.isFile()){
System.out.println(file.getCanonicalPath());
}
else{
GetAllFiles(file.listFiles());
}
}
}
删除所有文件
public static void main(String[] args) throws IOException {
File mm = new File("E:\\l");
File[] list = mm.listFiles(); //拿到所有下一级的File文件
delAllfiles(list);
}
public static void delAllfiles(File[] jj){
if(jj==null){
throw new IllegalArgumentException("dir not found dir");
}
for (File file : jj) {
if(file.isFile()){
file.delete();
}
else{
File[] files = file.listFiles();
delAllfiles(files);
file.delete();
}
}
}
三、OutputStream和InputStream
1、outputstream
OutputStream是许多我们常用的输出流的父类,比如说FileOutputstream。
(一)FileOutputstream
一般来说其常见的构造方法是以下几种
其中第一、第二种传入String类型的串,串中是文件的地址,第二种构造后面的布尔值决定在输出时是对文件进行重新写入还是继续接着之前文件的末尾追加写入。true则为追加,false则为默认。
第三种和第四种是直接给文件输出流传递File类的对象。
常用的方法是以下几种
void write(int b): 向文件中写入一个字节。
void write(byte[] b): 向文件中写入一个字节数组。
void write(byte[] b, int off, int len): 向文件中写入字节输入的一部分。
void close(): 释放资源.
下面举个例子!
FileOutputStream ops = new FileOutputStream("zz.txt");
ops.write(65);//写入A进去
ops.write("脏丽丽有点帅哟!".getBytes());//写入脏丽丽有点帅
ops.write("真心帅嘞".getBytes(),3,9);//UTF-8编码下一个中文三个字节,输出心帅嘞到文件
ops.close();//关闭流
最后zz.txt中的内容如下
2、inputstream
下面我们依然使用FileInputStream来进行举例!
(一)FileInputStream
常用的构造方法由以下两种
在这里要注意的是不同于输出流,在这里输入流中如果文件不存在的话系统不会自动为你创建,所以我们要在参数中填写实际存在的文件。
一般我们经常使用以下方法。
public int read() throws IOException//从输入流中读取一个字节返回int型变量,若到达文件末尾,则返回-1
public int read(byte[] b) throws IOException//从输入流中读取b.length个字节到字节数组中,返回读入缓冲区的总字节数,若到达文件末尾,则返回-1
我们读一下刚才我们写的文件!
public class InputStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("zz.txt");
byte[] reader = new byte[fis.available()];//通过available方法获取文件大小
int length = 0;
while((length=fis.read(reader))!=-1){
//循环写入,当方法返回值为-1时代表已写到文件尾
String v = new String(reader);
//输出!
System.out.println(v);
}
fis.close();
}
}
程序输出结果
这样我们写一个文件复制的方法吧!
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream("E:\\test\\xjn.jpg");
FileOutputStream outputStream = new FileOutputStream("xjn.jpg",true);
byte[] r = new byte[1024];//建一个大小为1024的缓冲区!
int length = 0;
while ((length=inputStream.read(r))!=-1){
outputStream.write(r,0,length);
}
inputStream.close();
outputStream.close();
}
四、FileReader和FileWriter
(一)FileReader
常用构造如下:
FileReader(File file)
FileReader(String fileName)
常用方法有以下两个!
下面我们使用FileReader读一下之前写过的zz.txt!
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("zz.txt");
char[] z = new char[2];
int length =0;
while((length = fileReader.read())!=-1){
System.out.println((char)length);
}
}
结果:
(二)FileWriter
常用构造如下:
FileWriter(File file)
FileWriter(File file, boolean append)//append为true,从后面写,false前面写
常用方法:
在这里要注意的是,FileWriter默认是写入进缓冲区,当执行flush或close方法时会将缓冲区内的所有信息写入文件中。
下面测试下代码。
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("zzz.txt");
String s ="丽丽真心有点小帅哟!";
fw.write(s);
fw.flush();
fw.write("小俊男MVP",1,5);
fw.close();
}
最终结果
五、ObjectInputStream和ObjectOutputStream
这两种类一般是用于序列化某一对象所使用,可以实现一个对象持久化的操作。
看源码发现二者构造分别需要传入一个inputstream和outputstream
这里我们还是举个例子!!
首先我们先写一个User类
User类中定义了三个属性,num,age以及name,定义好其中的构造以及getter setter方法。
这里如果要实现序列化的话需要实现序列化接口,这是一个标记接口,里面没有任何的方法。
在类中也要生成一个序列化的编号
使用transient关键字可以在序列化时不考虑该属性
package com.ObjectStream;
import java.io.Serializable;
import java.util.Objects;
public class User implements Serializable {//需要添加序列化接口
private static final long serialVersionUID = 1105883575844948448L;//序列化编号
private int num;
private transient int age;//使用transient关键字时序列化时不考虑该属性
private String name;
public User() {
}
public User(int num, int age, String name) {
this.num = num;
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"num=" + num +
", age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return num == user.num &&
age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(num, age, name);
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试下
public class OutPut {
public static void main(String[] args) {
try (ObjectOutputStream op = new ObjectOutputStream(new FileOutputStream("obj.obj"))) {
User lily = new User(1001, 5, "lily");
op.writeObject(lily);//输出
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行代码后 其生成了一个obj.obj文件
public class Input {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream oi = new ObjectInputStream(new FileInputStream("obj.obj"));
User i = (User) oi.readObject();
System.out.println(i);
}
}
读入obj.obj,最后运行结果如下
因为当初我们在age属性前添加了transient关键字,所以这里属性值为0
六、GZIPInputStream和GZIPOutputStream
我们在操作文件的时候经常要将他们压缩或是解压,这里我们常用GZIPInputStream和GZIPOutputStream对文件进行压缩以及解压,我们还是通过一个例子来聊一聊。
压缩:
public class Input {
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream("E:\\新版演示.avi");//要进行压缩的文件
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new FileOutputStream("E:\\新版演示.zip"));//要解压的
int length = 0;
byte[] jj = new byte[1024];
while ((length=inputStream.read(jj))!=-1){
gzipOutputStream.write(jj);
}
inputStream.close();
gzipOutputStream.close();
}
}
运行结束后就出现了压缩好的文件
解压:
public class Unzip {
public static void main(String[] args) throws IOException {
GZIPInputStream gzipInputStream = new GZIPInputStream(new FileInputStream("E:\\新版演示.zip"));
FileOutputStream fileOutputStream = new FileOutputStream("E:\\新版s演示.wvi");
int length =0;
byte[] jj = new byte[1024];
while((length=(gzipInputStream.read(jj)))!=-1){
fileOutputStream.write(jj,0,length);
}
gzipInputStream.close();
fileOutputStream.close();
}
}
解压结束后出现了相应的解压文件