[ java IO ] 文件传输中的输入输出(流)
目录
一.File类
1.定义:
2.注意:
3.方法及代码
2.输入和输出
1.定义:
3.流的分类:
(1)按读取单位分:
(2)按流的流向分:
4.字节流:
1.字节流常用类 :
2. 抽象类: InputStream 和 OutputStream
3.方法及代码:
5.字符流
1.定义:
6.节点流和处理流
1.定义:
2.处理流常用类
(1)缓冲字节流:
(2)缓冲字符流
(3)数据处理流
(4)对象序列化(输出)和反序列化(输入)
一.File类
1.定义:
在java.io包中,File类的对象表示一个计算机中的文件或目录(文件夹)
2.注意:
File对象可以对文件或目录的属性进行操作 例如 文件名 最后修改日期 文件大小.....
但是File对象无法操作文件的具体数据,即不能直接对文件进行 读/写 操作
3.方法及代码
package file;
import java.io.File;
import java.io.FileDescriptor;
import java.sql.SQLOutput;
import java.util.Date;public class FileDemo1 {public static void main(String[] args) {File file = new File("D:/a.txt");//(pathname:文件路径地址)//获取System.out.println(file.length());//获取 文件内容的长度System.out.println(new Date(file.lastModified()));//获取 最后修改文件的时间System.out.println(file.getName());//获取 文件名字System.out.println(file.getPath());//获取 文件路径//判断System.out.println(file.isHidden());//是否隐藏System.out.println(file.canWrite());//是否可写System.out.println(file.canRead());//是否可读System.out.println(file.isFile());//是否为文件System.out.println(file.isDirectory());//是否为文件夹System.out.println(file.exists());//存在}
}
package file;
import java.io.File;
import java.io.IOException;
public class FileDemo2 { //抛出------异常public static void main(String[] args) throws IOException {//创建文本File file = new File("D:/b.txt");if (!file.exists()){//判断 文件是否存在file.createNewFile();//创建文件}//创建文件夹File file1 = new File("D:/demo/a/b/c");if(!file1.exists()){//file1.mkdir();//创建单级文件夹file1.mkdirs();//创建多级文件夹}//删除文件夹File file2 = new File("D:/demo");file2.delete();//文件夹必须为空才能被删除}
}
package file;
import java.io.File;
public class FileDemo3 {public static void main(String[] args) {File file = new File("D:/demo");//注意:要么使用/ 要么使用\\//返回给定目录所有的子目录 是字符串(有可能是文件,也有可能是文件夹)String[] files = file.list();for(String f :files){System.out.println(f);}//返回文件实例的对象 可以对拿到的文件进行操作(删除...)File[] files1 = file.listFiles();for (File f:files1){System.out.println(f);}}
}
2.输入和输出
1.定义:
输入(input):把电脑上的数据读取(read)到程序中
输出(output):把读取到程序中的数据写到(write)目标位置
注意:输入和输出都是相对程序而言
3.流的分类:
(1)按读取单位分:
字符流(char):读取时以字符为单位 可以读取纯文本文件 例如文本文档
字节流(byte):读取时以字节为单位,可以读取任何文件 例如图片 音频 歌曲
(2)按流的流向分:
1.输入流 : 往程序中读
FileInputStream(字节流) 是InputStream(抽象类)的子类
Reader(字符流) : FileReader 实现类
2.输出流:从程序中往外写
FileOutputStream(字节流)是OutputStream(抽象类)的子类
Writer(字符流) : FileWriter 实现类
3.转换流:
InputStreamReader 把字节流转为字符流
OutputStreamWriter 把字符流转为字节流
4.字节流:
1.字节流常用类 :
FileInputStream----输入流 FileOutputStream----输出流
2. 抽象类: InputStream 和 OutputStream
3.方法及代码:
package byteStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class Demo1 {public static void main(String[] args) throws IOException {//创建一个输入管道,对接到我们要读取的文件上FileInputStream inputStream = new FileInputStream("D:/a.txt");//创建一个输出管道FileOutputStream outputStream = new FileOutputStream("D:/c.txt");//循环读取 返回-1时读取结束int b= 0;while ((b=inputStream.read()) != -1){outputStream.write(b);//输出(写)}//断开所连接的文件inputStream.close();outputStream.close();file.delete();//如果要删除文件,必须放在close()方法之后}
}
package byteStream;
import java.io.*;
public class Demo2 {public static void main(String[] args) throws IOException {//创建一个输入流管道,给定输入的文件地址,输入的文件必须存在,如果不存在,则抛出异常File file = new File("D:/a.txt");FileInputStream inputStream = new FileInputStream(file);//创建一个输出管道,目标文件不需要我们自己创建,输出管道会自动创建FileOutputStream outputStream = new FileOutputStream("D:/c.txt");int b=0;while((b=inputStream.read())!=-1){//无参//read()方法每次读取一个字节outputStream.write(b);}//断开所连接的文件inputStream.close();outputStream.close();file.delete();//如果要删除文件,必须放在close()方法之后}
}
package byteStream;
import java.io.*;
public class Demo3 {public static void main(String[] args) throws IOException {//创建一个输出流管道,给定输出的文件地址,文件必须存在,如果不存在,则抛出异常FileInputStream inputStream = new FileInputStream("D:/c.txt");FileOutputStream outputStream = new FileOutputStream("D:/a.txt");/* inputStream.read(bytes):每次读取的个数是byte数组的字节长度,返回值(int),返回的是每次往数组中装入的 实际字节个数,读取完后返回-1;*/byte[] bytes = new byte[10];//储存每次读取的字节内容int length = 0 ;//记录 实际向数组装入的 字节个数while((length=inputStream.read(bytes))!=-1){//有参System.out.println(length);outputStream.write(bytes,0,length);//每次往后写byte数组个字节内容,从0开始,写length个}inputStream.close();outputStream.close();}
}
注意 : read()和read(数组) write()和write(数组,0,length) 的区别
5.字符流
1.定义:
字符流只能读取纯文本文件 举例 : 如果读取图片,可能会发生格式转换,损毁图片
package charStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;public class Demo1 {public static void main(String[] args) throws IOException {FileReader reader = new FileReader("D:/非凡英才/运行事例/a.txt");//读取纯文本FileWriter writer = new FileWriter("D:/非凡英才/运行事例/b.txt");System.out.println(reader.read());//读取的是字符所对应的编码 20320System.out.println((char)reader.read());//强制转换返回字符 好System.out.println((char)reader.read());//中System.out.println(reader.read());System.out.println(reader.read());//-1 你好中国是4个字符,读到第5次就会返回-1int c = 0;while((c=reader.read())!=-1){writer.write(c);}/* char[] chars = new char[20];int length = 0;while((length=reader.read(chars))!=-1){writer.write(chars,0,length);}*/reader.close();writer.close();}
}
6.节点流和处理流
1.定义:
节点流:直接对接文件,上述介绍的字符流和字节流都是节点流
处理流:不直接对接文件(在节点流的基础上处理,相当于管道套管道)
2.处理流常用类
(1)缓冲字节流:
内部存在一个默认长度为8192的字节数组(缓冲区),对数据进行缓冲,减少向硬盘输出的次数 , 但是当输出数据的大小大于缓冲区的大小, 缓冲区就会失效. 同时必须刷新缓冲区 flush()把缓冲区里的数据全部输出,防止数据丢失
package node_dealStream.dealStream;
import java.io.*;
public class BufferdStreamDemo {public static void main(String[] args) throws IOException {FileInputStream inputStream = new FileInputStream("D:/HashMap.png");//节点流,直接对接文件BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream,2048);//处理流,不直接对接文件(在节点流的基础上处理,相当于管道套管道)FileOutputStream outputStream = new FileOutputStream("D:/HashMap.png");BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream,2048);//缓冲区的大小(默认为8192)byte[] bytes= new byte[1024];//每次输出数据的大小//但是当输出数据的大小大于缓冲区的大小, 缓冲区就会失效int length = 0;while ((length=bufferedInputStream.read(bytes))!=-1){bufferedOutputStream.write(bytes,0,length);}bufferedInputStream.close();bufferedOutputStream.flush();//刷新缓冲区 把缓冲区里的数据全部输出,防止数据丢失bufferedOutputStream.close();}}
(2)缓冲字符流
readLine()一次读一行,相当于缓冲
package node_dealStream.dealStream;import java.io.*;
//处理流常用类----缓冲字符流
public class BufferedDemo {public static void main(String[] args) throws IOException {FileReader fileReader = new FileReader("D:/a.txt");BufferedReader bufferedReader = new BufferedReader(fileReader);// bufferedReader.readLine();//一次读一行,相当于缓冲FileWriter fileWriter = new FileWriter("D:/e.txt",true);//append是追加,会保留上一次的内容,true表示下一次内容在此基础添加BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);String line = "";while((line = bufferedReader.readLine())!=null){bufferedWriter.write(line);bufferedWriter.newLine();//换行}bufferedReader.close();bufferedWriter.flush();//刷新缓冲区bufferedWriter.close();}}
(3)数据处理流
因为byte数组中储存的是经编码的字符数据(如UTF-8编码的字节)
将byte数组转为String字符串时,需要通过String构造方法(不可以使用toString(),获取的是地址)
使用起来不方便,故使用数据处理流类中的方法 writeUTF() 和 readUTF()
package node_dealStream.dealStream;
import java.io.*;
public class DataStreamDemo {/*处理流常用类----数据处理流*/public static void main(String[] args) throws IOException {//模拟聊天,一个人发消息,一个人接收消息/*String msg= "你好,吃饭了吗";//将这据话写在文件中FileOutputStream fileOutputStream = new FileOutputStream("D:/msg.txt");fileOutputStream.write(msg.getBytes());//将字符串转为byte编码fileOutputStream.close();FileInputStream fileinputStream = new FileInputStream("D:/msg.txt");//byte[] bytes = new byte[50];int length = fileinputStream.read(bytes);//因为byte数组中储存的是经编码的字符数据(如UTF-8编码的字节)//通过String构造方法 将byte数组转为String字符串(不可以使用toString方法,获取的是地址)System.out.println(new String(bytes,0,length));*///数据处理流String msg= "你好,吃饭了吗";FileOutputStream fileOutputStream = new FileOutputStream("D:/msg.txt");DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);dataOutputStream.writeUTF(msg);//将编码类型的byte转为字符串dataOutputStream.flush();dataOutputStream.close();FileInputStream fileinputStream = new FileInputStream("D:/msg.txt");DataInputStream dataInputStream = new DataInputStream(fileinputStream);String s= dataInputStream.readUTF();System.out.println(s);}
}
(4)对象序列化(输出)和反序列化(输入)
java中的对象都储存在内存中,一旦程序结束,内存中的对象都会消失
有时需要在程序停止时,将对象长久保存下来,下次启动程序时,继续使用 这就需要使用对象序列化和反序列化中的方法
package node_dealStream.dealStream;
import java.io.*;
import java.util.Calendar;
import java.util.Date;
public class ObjectStreamDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {//对象的输出(序列化)String s1 = "abc";Date date1 = new Date();FileOutputStream outputStream = new FileOutputStream("D:/a.txt");ObjectOutputStream objectOutputStream =new ObjectOutputStream(outputStream);objectOutputStream.writeObject(s1);objectOutputStream.writeObject(date1);objectOutputStream.flush();objectOutputStream.close();//对象的输入(反序列化)FileInputStream inputStream = new FileInputStream("D:/a.txt");ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);String s2 = (String) objectInputStream.readObject();//向下转型Date date2 = new Date();//重新创建的时间对象,只不过把date1还原了System.out.println(s2);System.out.println(date2);objectInputStream.close();}
}
注意 : 当一个类需要被序列化(输出)时,该类需要实现 Serializable接口,会为我们的类自动生成一个唯一编号(类的身份编号) 但是一旦类的信息发生改变,类自动生成的编号就会自动改变,一般情况下,需要我们生成一个固定的编号
package node_dealStream.dealStream;
import java.io.*;
import java.util.Date;
public class ObjcetStreamDemo2 implements Serializable {public static void main(String[] args) throws IOException, ClassNotFoundException {/* Car car = new Car("宝马",10);FileOutputStream outputStream = new FileOutputStream("D:/a.txt");ObjectOutputStream objectOutputStream =new ObjectOutputStream(outputStream);objectOutputStream.writeObject(car);objectOutputStream.flush();objectOutputStream.close();
*/FileInputStream inputStream = new FileInputStream("D:/a.txt");ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);Car car = (Car) objectInputStream.readObject();//向下转型Date date2 = new Date();//重新创建的时间对象,只不过把date1还原了System.out.println(car);objectInputStream.close();}
}
固定的编号如下:
package node_dealStream.dealStream;
import java.io.Serializable;
public class Car implements Serializable {//创建类的固定编号private static final long serialVersionUID = 8714794513665685524L;String name;int age;//String color;public Car(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Car{" +"name='" + name + '\'' +", age=" + age +'}';}
}
固定编号的生成方法: