一、file类
1.文件、目录
文件:内存中存放的数据爱计算机关机后就会消失,要长久地保存数据,就要使用硬盘光盘,U盘等设备,为了便于数据的管理和索引,引入了“文件”的概念,操作系统已文件为单位管理磁盘中的数据。
文件夹(目录):成千上万个文件夹为了方便使用和索引,引入了树形目录的机制,可以吧文件放在不同的文件夹中。
2.在Java程序中操纵文件/目录
盘符上的文件目录将各种信息进行了封装,封装成了一个对象,对象属于File类的对象,就可以对这个对象获取各种信息,还可以对文件进行创建,删除。
3.File类对文件的操作
创建对象
public static void main(String[] args) throws IOException {
//将文件封装为一个file类的对象
File f=new File("d:\\test.txt");
File f2=new File("d:/test.txt");
//File.separator属性帮助我们获取当前操作系统的路径拼接符
File f3=new File("d:mycode"+File.separator+"test.txt");
}
常用方法
//常用方法
System.out.println("文件是否可读:"+f.canRead());
System.out.println("文件是否可写"+f.canWrite());
System.out.println("文件的名字"+f.getName());
System.out.println("上级目录"+f.getParent());
System.out.println("是否是一个目录"+f.isDirectory());
System.out.println("是否是一个文件"+f.isFile());
System.out.println("是否隐藏"+f.isHidden());
System.out.println("文件的大小"+f.length());
System.out.println("是否存在"+f.exists());
/*if(f.exists()){//存在就删除
f.delete();
}else{//不存在就创建这个文件
f.createNewFile();
}
*/
路径相关
System.out.println(f=f2);//比较俩个对象的地址
System.out.println(f.equals(f2));//比较俩个对象的路径是否相同
File f4=new File("demo.txt");
if(!f4.exists()){
f4.createNewFile();
}
//绝对路径指的是精确的完整的
//相对位置指的是得相对于mai法存在的盘符下的
System.out.println("绝对n方路径;"+f4.getAbsolutePath());
System.out.println("相对路径:"+f4.getPath());
System.out.println("to.String"+f4.toString());
4.File类对目录的操作
基本方法
File f1=new File("D:\\mycode\\IDEA-workspace");
System.out.println(f1.exists());
System.out.println(f1.getPath());
System.out.println(f1.canWrite());
System.out.println(f1.canRead());
System.out.println(f1.isFile());
System.out.println(f1.isDirectory());
System.out.println(f1.isHidden());
System.out.println(f1.toString());
System.out.println(f1.getAbsolutePath());
System.out.println(f1.getPath());
与目录有关的方法
//与目录相关的方法
File f2=new File("d:\\A\\b\\c");
//创建目录
/*f2.mkdir();//创建单层目录
*/
f2.mkdirs();//创建多层目录
//删除目录
f2.delete();//删除低一层目录,且内容是空的,有内容不会删除
//查看
String[] list = f1.list();//文件夹下的目录
for(String s:list){
System.out.println(s);
}
File[] files = f1.listFiles();
for(File file:files){
System.out.println(file.getName()+","+file.getAbsolutePath());
}
二、IO流
File类:封装文件\目录的各种信息,对文件\目录进行操作,但不能获取文件\目录中的内容
IO:用于处理设备之间的数据传输
1.FileReader读取文件内容
创建一个file对象
//文件---->程序
//创建一个file对象
File f=new File("d:\\test.txt");
创建一个FileReader流的作用
FileReader fr=new FileReader(f);
读取
/*int read = fr.read();
System.out.println(read);
*/
int n=fr.read();
while(n!=-1){
System.out.print((char) n);
n=fr.read();
}
关闭流
流,数据库,网络资源,jvm不会自动关闭,需要手动关闭
fr.close();
快速读取
//读取
//引入快递员
char[] ch=new char[5];
int len = fr.read(ch);//一次读取五个,返回值是数组中的有效长度
while(len!=-1){
/*for (int i = 0; i <ch.length ; i++) {
System.out.println(ch[i]);
}
*/
String str=new String(ch,0,len);
System.out.print(str);
len=fr.read(ch);
}
2.FileWriter写出数据操作
//1.有一个目标文件
File f=new File("d://demo.text");
//新建一个字符流
FileWriter fw=new FileWriter(f);
//输入
String str="hello,java";
for (int i = 0; i <str.length() ; i++) {
fw.write(str.charAt(i));
}
//关闭流
fw.close();
}
char[] chars = str.toCharArray();//转换为数组写出
fw.write(chars);
FileWriter fw=new FileWriter(f):默认覆盖
FileWriter fw=new FileWriter(f,false):默认覆盖
FileWriter fw=new FileWriter(f,true):追加
3.文件复制
原文件
//1.原文件
File f1=new File("d:\\text.txt");
目标文件
//2.目标文件
File f2=new File("d:\\demo.txt");
读入
//3.输入的对象
FileReader fd=new FileReader(f1);
读出
//4.输出对象
FileWriter fw=new FileWriter(f2);
复制
//5.开始写入
//方式一
/*int read = fd.read();
while (read!=-1){
//一次读一个
fw.write(read);
read=fd.read();
}
*/
//方式二 缓冲数组一次读五个
/* char[] chars = new char[5];
int len = fd.read(chars);
while (len!=-1){
fw.write(chars,0,len);//将缓冲数组中的有效长度读出
len=fd.read(chars);
}
*/
//方式三:缓冲数组转换成字符
char[] chars = new char[5];
int len=fd.read(chars);//每次读入5个
while (len!=-1){
String s=new String(chars,0,len);//转为字符串输出
fw.write(s);
len=fd.read(chars);
}
关闭流
//关闭流,倒着关闭
fw.close();
fd.close();
4.利用try-catch-finally处理异常机制(实际上更多使用)
public static void main(String[] args) {
//1.原文件
File f1=new File("d:\\text.txt");
//2.目标文件
File f2=new File("d:\\demo.txt");
//3.输入的对象
FileReader fd= null;
FileWriter fw=null;
try {
fd = new FileReader(f1);
char[] chars = new char[5];
int len=fd.read(chars);//每次读入5个
while (len!=-1){
String s=new String(chars,0,len);//转为字符串输出
fw.write(s);
len=fd.read(chars);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fw!=null)//防止空指针异常
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fd!=null)//防止空指针异常
fd.close();
} catch (IOException e) {
e.printStackTrace();
}
}
5.FileInputStream读取文件内容
【1】利用字节流读文本文件
a. 文件是utf-8进行存储的,英文字符占一个字节,中文字符占三个字节
b.文本文件应使用字符流读取,不应该使用字节流读取
c.read()读取一个字节,返回值应为int类型,而不是byte类型
dread方法底层做了处理,让返回值的类型都为正数,为了避免返回值为-1时,分清楚是到文件结尾还是读入字节
public static void main(String[] args) throws IOException {
//功能利用字节流将文件中的内容读到文件中
//1.一个原文件
File f1=new File("d:\\text.txt");
FileInputStream fis=new FileInputStream(f1);
/*
文件是utf-8进行存储的,英文字符占一个字节,中文字符占三个字节
文本文件应使用字符流读取,不应该使用字节流读取
read()读取一个字节,返回值应为int类型,而不是byte类型
read方法底层做了处理,让返回值的类型都为正数,为了避免返回值为-1时,分清楚是到文件结尾还是读入字节
*/
int i = fis.read();
while (i!=-1){
System.out.println(i);
i=fis.read();
}
//关闭流
fis.close();
}
【2】利用字节流复制
一个一个复制
public static void main(String[] args) throws IOException {
//完成图片的复制
//1.原文件
File f1=new File("d:\\WS.jpg");
//2.目标文件
File f2=new File("d:\\sw.jpg");
//3.输入管道
FileInputStream fis=new FileInputStream(f1);
//4、输出管道
FileOutputStream fos=new FileOutputStream(f2);
//5.复制(一个一个复制)
int i = fis.read();
while (i!=-1){
fos.write(i);
i=fis.read();
}
//6.关闭流倒着关闭流
fos.close();
fis.close();
}
添加字节缓冲数组
public static void main(String[] args) throws IOException {
//1.原文件
File f1=new File("d:\\WS.jpg");
//2、目标文件
File f2=new File("d:\\wer.jpg");
//3.输入管道
FileInputStream fis=new FileInputStream(f1);
//4.输出管道
FileOutputStream fos=new FileOutputStream(f2);
//5、复制
byte[] b = new byte[1024 * 8];
int len = fis.read(b);
while (len!=-1){
fos.write(b,0,len);
len=fis.read();
}
//6、关闭流
fos.close();
fis.close();
}
【3】缓冲流
缓冲字节流(处理流)BufferedInputStream/ BufferedOutputStream
public static void main(String[] args) throws IOException {
//1.原文件
File f1=new File("d:\\WS.jpg");
//2、目标文件
File f2=new File("d:\\wer.jpg");
//3.输入管道
FileInputStream fis=new FileInputStream(f1);
//4.输出管道
FileOutputStream fos=new FileOutputStream(f2);
//5.功能加强,在FileInputStream外面套一个管子
BufferedInputStream bis=new BufferedInputStream(fis);
//6.功能加强,在FileoutputStream外面套一个管子
BufferedOutputStream bos=new BufferedOutputStream(fos);
//7.复制
//5、复制
byte[] b = new byte[1024 * 8];
int len = bis.read(b);
while (len!=-1){
bos.write(b,0,len);
/* bos.flash(),底层已经帮助我们刷新了缓冲区,不需要手动清除*/
len=bis.read();
}
//6、关闭流
//如果处理流包裹着节点流的话,只需要关闭高级流,里面的字节流随之就会被关闭
bos.close();
bis.close();
//fos.close();
//fis.close();
}
缓冲字符流(处理流) BufferedReader/BufferedWriter
public static void main(String[] args) throws IOException {
//1.原文件
File f1=new File("d:\\text.txt");
//2、目标文件
File f2=new File("d:\\demo1.txt");
//3.输入管
FileReader fr=new FileReader(f1);
//4.输出管
FileWriter fw=new FileWriter(f2);
//5.输入字符流外面的管
BufferedReader br=new BufferedReader(fr);
//6、输出字符流外面的管
BufferedWriter bw=new BufferedWriter(fw);
//7.复制
//方式一:一个一个删
int n = br.read();
while (n!=-1){
bw.write(n);
n=br.read();
}
//方式二:缓冲数组
char[] ch=new char[20];
int len = br.read(ch);
while (len!=0){
bw.write(ch,0,len);
len=br.read();
}
//方式三:一行一行读
String str = br.readLine();
while (str!=null){
bw.write(str);
bw.newLine();//每次写出一行后换行
str=br.readLine();
}
//8、关闭流
bw.close();
br.close();
}
【4】转换流
作用:将字节流和字符流进行转换
属于字符流,由后缀得出
inputStreamReader:字节输入流---->字符输入流
outputStreamWriter:字符输出流---->字节输出流
将输入的字节流转换为输入芙蓉字符流,然后完成文件复制到程序
public static void main(String[] args) throws IOException {
//1.原文件
File f1=new File("d:\\text.txt");
//2.输入字节流接触文件
FileInputStream fis=new FileInputStream(f1);
//3.讲字节流转换为字符流
//讲字节转换为字符的时候需要按照原文件的编码格式进行转化,否则会出现乱码
InputStreamReader isr=new InputStreamReader(fis,"utf-8");
//4.复制
char[] ch=new char[20];
int len = isr.read(ch);
while (len!=-1){
//将缓冲字符转换为字符串在控制台上打印出来
System.out.print(new String(ch,0,len));
len=isr.read(ch);
}
//5.关闭流
isr.close();
}
文本文件的复制
public static void main(String[] args) throws IOException {
//1.原文件
File f1=new File("d:\\text.txt");
//2.目标文件
File f2=new File("d:\\demo3.txt");
//3.输入方向
FileInputStream fis=new FileInputStream(f1);
InputStreamReader isr=new InputStreamReader(fis,"utf-8");
//4.输出方向
FileOutputStream fos=new FileOutputStream(f2);
OutputStreamWriter osw=new OutputStreamWriter(fos,"gbk");
//5.复制
char[] ch=new char[20];
int len = isr.read(ch);
while (len!=-1){
osw.write(ch,0,len);
len=isr.read();
}
//6.关闭流
osw.close();
isr.close();
}
三、Systen类对IO流的支持
1.System的属性
System.in(字节流):标准输入流,默认情况下从键盘输入
public static void main(String[] args) throws IOException {
//得到的是标准的输入流
/*InputStream in = System.in;
int n = in.read();//等待键盘的录入,这个方法是一个阻塞方法
System.out.println(n);
Scanner sc=new Scanner(System.in);
String s = sc.next();
System.out.println(s);
//Scanner相当于一个扫描器,不一定可以扫描System.in扫进来的东西
*/
Scanner sd=new Scanner(new FileInputStream(new File("d:\\text.txt")));
while(sd.hasNext()){
System.out.println(sd.next());
}
}
System.out(字节流):标准输出流,默认情况下输出到控制台
public static void main(String[] args) {
//写到控制台
PrintStream out = System.out;
//调用方法
out.print("这既是爱");
out.print("张杰");
out.println("你好");//直接在控制台写出,并且换行操作
out.println("你好2");
}
}
2.键盘内容输出到文件中
public static void main(String[] args) throws IOException {
//1.输入方向
//键盘录入
InputStream in = System.in;//字节流
//转换为字符流
InputStreamReader isr=new InputStreamReader(in);
//在字符流外面加一个缓冲流
BufferedReader br=new BufferedReader(isr);
//2.输出方向
//目标文件
File f=new File("d:\\demo5.txt");
//字符输出流
FileWriter fw=new FileWriter(f);
//缓冲流
BufferedWriter bw=new BufferedWriter(fw);
//3.开始动作
String s = br.readLine();
while (!s.equals("exit" )){
bw.write(s);
bw.newLine();//换行
s = br.readLine();
}
//4.关闭流
bw.close();
br.close();
}
四、数据流
数据流:用来操作基本数据类型和字符串的
DataInputStream:将文件中存储的基本数据类型和字符串写入内存的变量中
public static void main(String[] args) throws IOException {
/* //1.文件
File f=new File("d:\\text.txt");
//2.字节输出流
FileOutputStream fos=new FileOutputStream(f);
//3.数据流
DataOutputStream dos=new DataOutputStream(fos);
*/
DataOutputStream dos=new DataOutputStream(new FileOutputStream(new File("d:\\text.txt")));
//写出
dos.write(11);
dos.writeBoolean(false);
dos.writeChar('s');
dos.writeUTF("hello");
//关闭流
dos.close();
DateOutputStream:将内存的基本数据类型和字符串的变量写出到文件中
public static void main(String[] args) throws IOException {
//
File f=new File("d:\\text.txt");
//字节输入流
FileInputStream fis=new FileInputStream(f);
DataInputStream dis=new DataInputStream(fis);
//将文件中的内容读取到程序中
System.out.println(dis.read());
System.out.println(dis.readBoolean());
System.out.println(dis.readChar());
System.out.println(dis.readUTF());
dis.close();
}
五、对象流(ObjectInputStream,ObjectInputStream)
用于存储和读取基本数据类型的数据或对象的处理流,可以将Java中的对象写到数据源中,也可以把对象从数据源中还原
将字符串对象写到文件中去<序列化>
public static void main(String[] args) throws IOException {
//讲一个对象写入到文件中
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("d:\\text01.txt")));
oos.writeObject("hello");
oos.close();
}
将字符串从文件中读到控制台<反序列化>
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("d:\\text01.txt")));
String s = (String) ois.readObject();
System.out.println(s);
ois.close();
}
序列化:爸爸内存中的Java对象转换成平台无关的二进制数据,从而允许把这种二进制数据持久的保存在磁盘上
反序列化:当其他的程序获取了这种二进制数据,就可以恢复成原来的Java对象
五、操作自定义的类
1.
public class Person {
private int age;
private String name;
private double weight;
//构造器
public Person(int i, String lili, double v) {
}
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 double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
public class Test01 {
public static void main(String[] args) throws IOException {
Person p=new Person(19,"lili",123.2);
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("d:\\text02.txt")));
oos.writeObject(p);
oos.close();
}
}
2.按照已经学习的操作,实现将类写出到文件中会出现错误,因为没有进行序列化
必须要实现一个接口
public interface Serializable{
}
标识接口:接口内部什么都没有
作用:起标识作用,只有实现这个接口的类的对象才能序列化
3.将要写出的类实现标识接口
实现接口:public class Person implements Serializable {
反序列化:
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("d:\\text02.txt")));
Person p=(Person)ois.readObject();
System.out.println(p);
ois.close();
}
4.反序列化会出现异常的原因:
序列化:Person对象---->文件中
当时的Person类没有toString方法
在Person中加入toString方法,然后再进行反序列化,读进来的对象的类不带toString,所以出现了类不匹配的问题
解决:加入一个序列号
private static final long serialVersionUID=123L;
5.serialVersionUID
凡是实现serialVersionUID的类都有一个表示序列化版本标识符的静态常量
private static final long serialVersionUID=123L;
serialVersionUID用来表明类的不同版本间的兼容性,其目的是以序列化对象进行版本控制,有关各版本反序列化是是否兼容
如果类没有显示定义这个静态变量,它的值是Java运行时环境更具内的内部细节自动生成的,若类的实例变量做了修改,serialVersionUID可能发生变化
6.序列化
(1)被序列化的类的内部的所有属性必须是可序列化的(基本数据类型都是可序列化的)
(2)static,transient修饰的属性,不可以被序列化