本文已参与「新人创作礼」活动,一起开启掘金创作之路。
文件的基础知识
基本概念
文件:保存文字,视频,音频,图片等内容
文件流:文件在程序中以流的形式来操作
Java程序(内存)---输出流-->文件(磁盘)
Java程序(内存)<-输入流----文件(磁盘)
个人理解:程序员操作的是程序,数据到了程序中,也就是到了我们可以操作的范围内,就是输入流,反之就是输出流
常用文件操作
创建文件的几种方式
总结:三种方式只是创建文件时的构造器传入参数不同,方式1是传路径加文件名(一个String),方式3是将路径和文件名分开(两个String),方式2是将文件路径封装为一个对象,文件名还是String
public static void main(String[] args) {
new UseFile().create01();//方式1创建文件
new UseFile().create02();//方式2创建文件
new UseFile().create03();//方式3创建文件
}
//方式1:new File();
public void create01(){
String filePath = "D:\演示.txt";
File file = new File(filePath);//一个文件对象就代表着一个文件,这里的对象只是在内存中
try {
file.createNewFile(); //去创建这个文件,现在这个文件才进入了磁盘
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
//方式2:new File (File parent,String child) 根据父目录文件+子路径构建
public void create02(){
File parentFile = new File("D:\");
String fileName = "演示2.txt";
File file = new File(parentFile,fileName);
try {
file.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
//方式3:new File(String parent,String child) 根据父目录+子路径构建
public void create03(){
String parentPath = "D:\";//这样写e:/也可以
String fileName = "演示3.txt";
File file = new File(parentPath,fileName);
try {
file.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
获取文件相关的信息
public void info(){
File file = new File("D:\演示2.txt");
//调用相应方法去得到相应信息
System.out.println("文件名:"+file.getName());
System.out.println("绝对路径:"+file.getAbsolutePath());
System.out.println("文件父级目录:"+file.getParent());
System.out.println("文件大小(字节):"+file.length());
System.out.println("文件是否存在:"+file.exists());
System.out.println("是不是一个文件:"+file.isFile());
System.out.println("是不是一个目录:"+file.isDirectory());
}
常用的文件操作(删除创建)
File file = new File("D:\演示.txt");
//1.判断D:\演示.txt是否存在,若存在则删除
if (file.exists()) {
if (file.delete())
System.out.println("删除成功");
else
System.out.println("删除失败");
} else
System.out.println("文件不存在");
//2.判断目录是否存在,若存在则删除,否则提示不存在,这里说明目录也看作是文件对象的一种
File directory = new File("D:\demo");
if (directory.exists()) {
if (directory.delete())
System.out.println("删除成功");
else
System.out.println("删除失败了");
} else
System.out.println("目录不存在");
//3.判断目录是否存在,如果不存在则创建
File directorys = new File("D:\A\B");
if (directorys.exists()) {
System.out.println("目录存在");
} else {
if (directorys.mkdirs()) {//mkdir是创建单级目录
System.out.println("创建成功");
} else {
System.out.println("创建失败");
}
}
文件的创建和删除,目录的创建和删除
IO流分类
流的介绍
按照流向
输入input:读取外部数据(磁盘)到程序(内存)中
输出output:将程序(内存)数据输出到磁盘
按照流处理的数据单位
字节流:按字节(8bit),常处理二进制文件
字符流:按字符,常处理文本文件
按照流的角色
节点流:
处理流(包装流):
体系图
FileInputStream 文件输入流
PipedInputStream
InputStream ObjectInputStream 对象字节输入流
ByteArrayInputStream
FilterInputStream BufferedInputStream 缓冲字节输入流
字节流 DigestInputStream
DateInputStream
FileOutputStream
PipedOutputStream
OutputStream ObjectoutputStream
ByteArrayoutputStream
FilteroutputStream BufferedOutStream
DigestOutputStream
DateOutputStream
PrintfStream
InputStreamReader FileReader
BufferedReader LineNumberReader
CharArrayReader
Reader FilerReader PushBackReader
PipedReader
StringReader
字符流
OutputStreamWriter FileWriter
BufferedWriter
Writer CharArrayWriter
FilerWriter
PipedWriter
PrintWriter
StringWriter
| 分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 | 结点/处理流 |
| 抽象基类 | InputStream | OutputStream | Reader | Writer | |
| 访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter | 节点流 |
| 访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter | 节点流 |
| 访问管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter | 节点流 |
| 访问字符串 | 节点流 | ||||
| 缓冲流 | 处理流 | ||||
| 转换流 | 处理流 | ||||
| 对象流 | 处理流 | ||||
| 抽象基类 | 处理流 | ||||
| 打印流 | 处理流 | ||||
| 推回输入流 | 处理流 | ||||
| 特殊流 | 处理流 |
这些流都继承自这四个抽象类:Reader,Writer,InputStream,OutStream
FileInputStream
//要求:读取一个text文件,并将文件内容显示在控制台
public void readFile01(){
int readData;
String filePath = "D:\演示2.txt";
FileInputStream fileInputStream = null;
try {
//创建流的对象,可以看作是负责物流的外卖小哥
fileInputStream = new FileInputStream(filePath);
while((readData=fileInputStream.read()) != -1){
//返回一个字节,如果到达文件末尾返回-1
/*
read是一个字节一个字节的读,效率较低
*/
System.out.print((char)readData);//将读的内容转成char显示
/*
只能打印英文,因为一个字母一个字节,不能打印汉字,一个汉字三个字节如果一个字节
一个字节打印,不能打印出汉字
*/
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//关闭文件流,流是一种资源,要释放该资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
简述代码:在控制台中输出文件内的内容,利用字节文件输入流的read的方法,读方法返回字符ASCII码,用一个int类型变量接收并将之转换成char类型,输出在控制台,缺点是只能一个字节一个字节读,且不能读汉字,效率低。
public void readFile02(){
int readData;
String filePath = "D:\演示2.txt";
byte[]b = new byte[8];//一次读8个字节
int readLen = 0;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(filePath);
while((readLen = fileInputStream.read(b)) != -1){
/*
read方法传入数组b,如果读取正常,返回实际读取的字节数
如果返回-1,表示读取完毕
*/
System.out.println(new String(b,0,readLen));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//关闭文件流,流是一种资源,要释放该资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码简述:创建一个数组,fileInputStream = new FileInputStream(filePath);这句代码相当于将流怼到了文件上,fileInputStream.read(b)相当于流的另一端怼到了一个数组上,这样就能一组一组的读,这个方法的返回值是每次新读取的字节数,假如不够数组的长度,就返回小于数组长度的实际个数,所以在转成字符串时,只把新读取的转换成字符串再输出。
编辑
FileOutputStream
//将数据写到文件中
public void write(){
String filePath = "D:\demo.txt";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filePath,true);
//写入一个字节(字符)
fileOutputStream.write('a');
//写入一个字符串,字符串的getBytes可以将字符串转成字节数组
String str = "hi xiaozhouaa";
fileOutputStream.write(str.getBytes());
fileOutputStream.write(str.getBytes(),0,str.length());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码简述:如果想要将一个字符写入文件中,则直接fileOutputStream.write('a');如果想要将一个字符串写入文件,则fileOutputStream.write(str.getBytes());将该字符串先转成一个字节数组(一个下标位置存一个字节的数据)这里区别读入时是将字符数组转换为字符串输出,fileOutputStream.write(str.getBytes(),0,str.length());这个方法是将这个字节数组中的第0个下标位置到第str.length写入到文件,写入的时候还有个小细节,在创建FileOutputStream时,构造器第二个参数是追加还是重写,如果是true,则每次执行程序内容会在文件里追加,这里的追加是在每次执行时追加,不是每次while时追加
编辑
这幅图里数组转字符串是用的new String(b,0,readLen),将b数组的0到某个长度转为字符串
字符串到数组是str.getBytes()转成字节数组
小应用之文件的拷贝
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
String readFilePath = "D:\boy.png";
String writeFilePath = "D:\copyBoy.png";
int readLen = 0;
String copyStr = new String();
byte []b = new byte[8];
try {
fileInputStream = new FileInputStream(readFilePath);
fileOutputStream = new FileOutputStream(writeFilePath);
while((readLen = fileInputStream.read(b))!=-1){
fileOutputStream.write(b,0,readLen);//一定要用这个方法,数组中的内容只写入最新的
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码简述:创建输入流,输出流,将输入流和文件连接,将输出流和文件连接,将输入流与字节数组连接并将数据读到数组中,将数组中的内容直接读到目标文件中,可以直接省略转换为字符串的过程。
FileReader
String filePath = "d:\演示2.txt";
FileReader fileReader = null;
int data;
try {
fileReader = new FileReader(filePath);
//用字符数组
System.out.println("字符数组输出:");
while((data = fileReader.read())!=-1) {
//返回的是实际读取到的字符数,返回-1说明到了文件结尾
System.out.print((char)data);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码简述: 一个字符一个字符读出
String filePath = "d:\演示2.txt";
FileReader fileReader = null;
char []b = new char[8];
int readLen;
try {
fileReader = new FileReader(filePath);
//用字符数组
System.out.println("字符数组输出:");
while((readLen = fileReader.read(b))!=-1) {
//返回的是实际读取到的字符数,返回-1说明到了文件结尾
System.out.print(new String(b,0,readLen));
System.out.print(new String(b));//是将一个数组全部转为字符串
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
代码简述: 读出字符数组
FileWriter
String filePath = "D:\演示.txt";
FileWriter fileWriter = null;
char []b = new char[]{'1','2','3'};
try {
fileWriter = new FileWriter(filePath);
//输入一个字符
fileWriter.write('B');
//写入指定数组
fileWriter.write(b);
//写入指定数组的指定部分
fileWriter.write(b,0,2);
//写入字符出串
fileWriter.write("找寻春天");
//写入字符串指定部分
fileWriter.write("找寻春天",0,2);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileWriter.close();//关闭或者flush,不然数据不能写入文件
} catch (IOException e) {
e.printStackTrace();
}
}
小细节:
1.FileWriter使用后,必须关闭(close)或刷新(flush),否则写入不到指定的文件,关闭会自动刷新,不刷新的话,数据还只在文件中
节点流和处理流的理解
节点流:数据源是存放数据的地方,数据源可以是文件,可以是数组等,结点流就是直接处理数据源的流,根据数据源的不同有不同的处理流,直接对数据源操作,比较底层,所以功能不是很强大。
处理流:也叫包装流,对节点流进行包装,如BufferedReader中有个属性是Reader in,可以传入Reader基类下的任何一个节点流类,从而功能会更强大,包装流既可以消除不同节点流的实现差异,也可以提供更方便的方法。
BufferedInputStream
借助内存中的缓冲区提升读操作的效率,给InputStream增加了缓冲区,所有读到的数据先进入缓冲区,然后再逐个取出,就好像长途汽车不是一个个运送乘客,而是利用车站作为缓冲区,等到乘客坐满了才发车。
构造方法
//参数类型为InputStream类
BufferedInputStream(InputStream in)
//创建具有指定缓冲区大小的BufferedInputStream实例
BufferedInputStream(InputStream in,int size)
使用实例
public class Demo1 {
public static void main(String[] args) {
String s = "This is a BufferedInputStream Demo Program";
byte buf[] = s.getBytes();
try(ByteArrayInputStream in = new ByteArrayInputStream(buf);
BufferedInputStream f = new BufferedInputStream(in)){
int c;
while((c = f.read())!= -1){
System.out.print((char)c);
}
}catch(IOException e){
System.out.println(e);
}
}
}
代码简述: 使用BufferedInputStream
BufferedOutputStream
构造方法
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out,int size)
常用方法
使用实例
public class Demo2 {
public static void main(String[] args) throws IOException {
try(BufferedOutputStream bo = new BufferedOutputStream(System.out)){
String s = "This is a BufferedOutputStrea Demo Program";
byte buf[] = s.getBytes();
bo.write(buf);
bo.flush();
}catch (IOException e){
System.out.println(e);
}
}
}
输出:This is a BufferedOutputStrea Demo Program
BufferedReader
对字符流进行包装
构造方法
BufferedReader(Reader in)
BufferedReader(Reader in,int sz)
常用方法
使用实例
public class Demo2 {
public static void main(String[] args) throws IOException {
try(BufferedReader br = new BufferedReader(new InputStreamReader(System.in))){
System.out.println("Enter First number");
String s = br.readLine(); //接收用户输入并存储在s1中
System.out.println("Enter Second number");
String s1 = br.readLine(); //接收用户输入并存储在s1中
int i = Integer.parseInt(s); //将字符串值转换为整数值
int i1 = Integer.parseInt(s1);
int i3 = i+i1;
System.out.println("sum="+i3);
}
}
}
BufferedWriter
构造方法
BufferedWriter(Writer out)
BufferedWriter(Writer out,int size)
常用方法
使用示例
public class Demo3 {
public static void main(String[] args) {
try(BufferedOutputStream b = new BufferedOutputStream(System.out)){
String s = "This is a BufferedOutputStream Demo Program";
byte buf[] = s.getBytes();
b.write(buf);
b.flush();
}catch (IOException e){
System.out.println(e);
}
}
}
输出:This is a BufferedOutputStream Demo Program
对象与流
不借助数据库实现存储功能 ,借助java.io.Serializable接口
序列化
将用户对象存储到文件中即将Java对象转为字节流存储到文件的过程叫序列化Java transient关键字使用小记 - Alexia(minmin) - 博客园
public class Demo4 {
public static void main(String[] args) throws Exception{
User tom = new User("tom","niit1234","tom@niit.com");
//字节输出流
OutputStream outputStream = new FileOutputStream("D:\演示.txt");
//对象输出流
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
//序列化
objectOutputStream.writeObject(tom);
//关闭对象流
objectOutputStream.close();
}
}
class User implements Serializable{
private String account;
private transient String password;
private String email;
public User(String accountInput,String passwordInput,String emailInput){
account = accountInput;
password = passwordInput;
email = emailInput;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
反序列化
把文件中的内容转成Java对象
public class Demo4 {
public static void main(String[] args) throws Exception{
//字节输入流
InputStream inputStream = new FileInputStream("D:\演示.txt");
//创建对象输入流
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
//反序列化
User tom = (User)objectInputStream.readObject();
//关闭对象流
objectInputStream.close();
//确认
System.out.println(tom.getAccount());
System.out.println(tom.getEmail());
System.out.println(tom.getPassword());
}
}
class User implements Serializable{
private String account;
private transient String password;
private String email;
public User(String accountInput,String passwordInput,String emailInput){
account = accountInput;
password = passwordInput;
email = emailInput;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
输出:
tom
tom@niit.com
null
\