Java中的IO流(上)——File文件类、字节输入输出流详解

导读:本篇文章讲解 Java中的IO流(上)——File文件类、字节输入输出流详解,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

IO流,即用来操作文件内容的技术。所以再讲IO流之前,要先认识一下File类。

一、File文件类

1、File类介绍

File是Java用来表示文件/文件夹(目录),可以通过File类在程序中操作硬盘上的文件/文件夹。

File类只是用来表示文件/文件夹的信息(大小、名称)等,而不能用来对文件的读写。

注意:
new File():创建出来的文件/文件夹只在内存中,而不在硬盘里。
file.createNewFile():根据file的路径,在硬盘中创建文件。
file.mkdir():根据file的路径,在硬盘中创建文件夹。
file.exsts():判断file对应的路径里是否有指定的文件/文件夹存在。

2、创建文件以及对文件的操作

(1)在指定路径上创建文件(3中方式):

public class Test {
	public static void main(String[] args) throws IOException {
		//1、默认路径,也就是当前项目下
		File file1 = new File("test01.txt");
		file1.createNewFile();
		
		//2、包中的文件路径
		File file2 = new File("src/test02/test.txt");
		file2.createNewFile();
		
		//3、绝对路径
		File file3 = new File("D:/test/test.txt");
		file3.createNewFile();
		//File file3 = new File("D:\\test\\test.txt");
	}
}

PS:
使用2、3创建文件对象,路径写错时会报错不存在。
(2)对文件对象的操作

public class Test {
	public static void main(String[] args) throws IOException {
		//默认路径,也就是当前项目下
		File file = new File("test01.txt");
		
		boolean ok = file.createNewFile();
		System.out.println(ok);
		//1、获取文件名
		String fileName = file.getName();
		//2、获取该文件的绝对路径
		String filePath = file.getAbsolutePath();
		//3、获取该文件的相对路径
		String path = file.getPath();
		//4、获取文件的父目录(在哪个目录下)
		String parentPath = file.getParent();
		//5、获取文件是否被隐藏
		boolean flag = file.isHidden();
		//6、获取该文件中的字节数
		long len = file.length();
		//7、获取该文件最后的修改时间
		long tempTime = file.lastModified();
		//8、删除文件
		boolean flag2 = file.delete();
		//9、查看文件是否存在
		boolean flag1 = file.exists();
		
		System.out.println("===================");
		
		//固定操作	
		if(!file.exists()) {//文件不存在
			System.out.println("未在指定目录下找到文件名为“test”的文本文件,正在创建");
			try {
				file.createNewFile();
			}catch(IOException e) {
				e.printStackTrace();
			}
			System.out.println("文件创建成功");
		}else {//文件存在
			System.out.println("找到文件名为“test”的文本文件");
			//可以继续继续对文件的操作
		}
	}
}

3、创建文件夹以及对文件夹的操作

(1)创建文件夹
与创建文件基本类似。

public class Test {
	public static void main(String[] args) {
		//1、创建单个文件夹
		File dir1 = new File("dir");
		boolean flag1 = dir1.mkdir();
		//2、创建多个文件夹
		File dir2 = new File("dir1/dir2/dir3/dir4");
		boolean flag2 = dir2.mkdirs();
	}
}

(2)对文件夹的操作

public class Test {
	public static void main(String[] args) throws IOException {
		File dir = new File("dir1/dir2/dir3/dir4");
		boolean flag = dir.mkdirs();
		//删除文件路径的最后一个文件夹
		boolean del =dir.delete();
	}
}

在文件夹下创建文件

public class Test {
	public static void main(String[] args) throws IOException {
		File dir = new File("dir");
		dir.mkdir();
		File file = new File(dir,"demo.txt");
		file.createNewFile();
	}
}

(3)遍历文件夹内的内容

public class Test {
	public static void main(String[] args) throws IOException {
		File dir = new File("E:/");
		//获取E盘下所有的文件和文件夹,返回文件数组
		File[] fs = dir.listFiles();
		//遍历
		for(File f:fs) {
			if(f.isFile()) {//判断是否为文件
				System.out.println(f.getName()+"是文件");
			}
			if(f.isDirectory()) {//判断是否为文件夹
				System.out.println(f.getName()+"是文件夹");
			}
		}
	}
}

二、IO流(水管)

1、IO流概况

(1)定义:

IO流是用来操作文件内容的技术,输入输出都是针对程序来说的。
I(in)输入:向程序中输入数据,一般是从文件中读取内容到程序中。
O(out)输出:程序向外输送数据,一般是将数据写入到文件中。
在这里插入图片描述
在这里插入图片描述

(2)用途:

读写文件
乱码问题
框架的底层技术使用
文件的上传下载

(3)分类:

按照数据类型:字节流、字符流。
字节流:二进制0101(最小单位),以字节为单位进行。是通用的,任何文件都可以操作。
字符流:操作中文字符方便(用记事本打开没有乱码,可以使用字符流)

按照数据的流向:输入流、输出流。

<1>输入流
字节流:Stream(每次读取一个字节)
InputStream:抽象的类
FileInputStream:文件输入流(是InputStream的子类)
BufferedInputStream:字节缓冲输入流
——————————————————————–
字符流:Reader(每次读取一个字符)
InputStreamReader(可以直接创建对象,子类是 FileReader)
BufferedReader:字符缓冲输入流(每次读取一行)

<2>输出流
字节流:Stream
OutputStream:抽象的类
FileOutputStream:文件输出流(是OutputStream的子类)
BufferedOutputStream:字节缓冲输出流
———————————————————————
字符流:Writer(每次写入一个字符)
OutputStreamWriter(可以直接创建对象,子类是 FileWriter)
BufferedWriter:字符缓冲输出流(每次写入一行)
PrintWriter

在这里插入图片描述
注意:
1、字节缓冲流要比字节流效率高。
2、字节缓冲流不能直接操作文件,必须包装字节流,通过字节流访问。(观察字节缓冲流的构造方法)

2、字节输入流与字节输出流

InputStream与OutputStream

OutputStream(程序->外界)

在这里插入图片描述
(1)基本框架

package test02;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
	public static void main(String[] args){
		File file = new File("test.txt");
		OutputStream out = null;
		try {
			//OutputStream为抽象类,
			//所以需要通过其子类FileOutputStream来创建对象
			out = new FileOutputStream(file);//相当于打开水管
			//是以字节形式去写入文件
			out.write('b');//b
			out.write(98);//b
			System.out.println("写入成功!");//作为提示
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//如果输出流不为空
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

注意:
1、IOException是IO流中所有异常的父类。
2、FileOutputStream中的文件如果不存在,会自动在对应路径下创建文件。
3、OutputStream是以字节形式写入文件,所以
‘b’->b;48->0;98->b(根据相应的编码规则
英文占一个字节,中文占2/3个字节(取决于编码方式)。

举例子,感受一个字节一个字节写入:

public class Demo7 {
	public static void main(String[] args) {
		byte[] bs = "98".getBytes();
		System.out.println(Arrays.toString(bs));//[57, 56]
		byte[] bs1 = "b".getBytes();//[98]
		System.out.println(Arrays.toString(bs1));
	}
}

4、操作文件后,一定要关闭流,否则会消耗系统资源。在关闭流之前,可以先判断其是否为空,为空则没有关的必要。

(2)追加or覆盖?

OutputStream out = new FileOutputStream(file,true);

如果第二个参数的位置上是true,则会追加;如果为false,则会覆盖。加入没有写上第二个参数,则默认为false。
(3)String类型要如何写入?

String str = "1234567";
byte[] bs = str.getBytes();//利用getBytes()得到字节数组
out.write(bs);//参数的类型为字节数组
out.write("\n".getBytes());//输出一个空格

小结:
(1)如果想利用字节输出流往文件中写入“1234”、“大王”或者是进行回车,可以利用 str.getBytes() 将它们解析为字节数组,再写入到文件中即可。(参数为byte[ ] bs)
(2)假如直接写入97、98等数字,你们则会根据ASCII码对照表,将对应的字符写入。(参数为int i)
(3)加入以字符的形式写入到文件中,即‘b’,那么在文件中出现的也是b。

InputStream(外界->程序)

在这里插入图片描述
(1)基本框架

test.txt文件内的内容:
在这里插入图片描述

package test02;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Test {
	public static void main(String[] args){
		File file = new File("test.txt");
		InputStream in = null;
		try {
			in = new FileInputStream(file);
			System.out.println(in.read());//98
			System.out.println(in.read());//98
			System.out.println(in.read());//180
			System.out.println(in.read());//243
			System.out.println(in.read());//205
			System.out.println(in.read());//245
			System.out.println(in.read());//13
			System.out.println(in.read());//10
			System.out.println(in.read());//54
			System.out.println(in.read());//-1
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

注意:
1、在utf-8编码方式下,中文占3个字节数;GBK编码方式下,中文占2个字节数。此处的编码方式为GBK编码方式。
2、文件一旦读取完,就会输出-1(byte类型)作为标志。
3、文件的内容也是一次输出一个字节,根据对应的编码规则进行输出。
4、可以将重复读取的代码替换为:

int b = -1;//定义b是有意义的
while((b = in.read()) != -1) {
	System.out.println(b);
}

(2)每次读取一个字节数组

public class Test {
	public static void main(String[] args){
		File file = new File("test.txt");
		InputStream in = null;
		try {
			in = new FileInputStream(file);
			//定义一个字节数组
			byte[] bs = new byte[3];
			//定义length表示读取到的有效数据的长度
			int length = 0;
			//in.read(byte[] byte)返回值为读取的有效字节个数,
			//一个都没有时,没有就返回-1
			while((length = in.read(bs)) != -1) {
				//第一种方式:直接输出字节数组
				System.out.println(Arrays.toString(bs));
				//第二种方式:字节数组转为String,并且输出String类型的数据
				String str = new String(bs);
//				String str1 = new String(bs,0,length);
				System.out.println(str);
//				System.out.println(str1);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

在这里插入图片描述
说明:
(1)第二次出现的-48其实是第一次出现的那个-48顺延下来的,因为到-46时,就已经没有内容可以读取了,所以-48就没有被覆盖。
(2)in.read(byte[] byte)返回值为读取的有效字节个数,一个都没有时,没有就返回-1。
(3)在以String类型输出时,如果将代码换为:

in = new FileInputStream(file);
//定义一个字节数组
byte[] bs = new byte[3];
//定义length表示读取到的有效数据的长度
int length = 0;
while((length = in.read(bs)) != -1) {
//		String str = new String(bs);
		String str1 = new String(bs,0,length);
		//主要看最后一行的?不再出现了
//		System.out.println(str);
		System.out.println(str1);
}

在这里插入图片描述
(3)根据文件总的字节长度整体读取
file.length():获取文件的字节长度

in = new FileInputStream(file);
byte[] bs = new byte[(int)file.length()];
in.read(bs);//从文件中读取信息,并将信息存入到字节数组bs中
//将字节数组转换成字符串
String str = new String(bs);
System.out.println(str);

available():可以一次性获取文件的剩余的字节数。

in = new FileInputStream(file);
int num = in.available();
byte[] bs = new byte[num];
in.read(bs);//从文件中读取信息,并将信息存入到字节数组bs中
//将字节数组转换成字符串
String str = new String(bs);
System.out.println(str);

综合:复制粘贴图片

一边读,一边写。
1、一个一个字节的去读写。
2、以字节数组的形式去读写。
如果指定字节数组的长度,可以取1024的整数倍。

注意:
在关流时,遵循原则——先开的后关。

package day20200614;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Homework_1 {
	public static void main(String[] args) {
		FileInputStream in = null;
		FileOutputStream out = null;
		try {
			in = new FileInputStream("src/day20200614/timg.jpg");
			out = new FileOutputStream("src/day20200614/timg1.jpg");
			//定义一个字节数组
			byte[] bs = new byte[1024];
			//定义每次读取的有效字节长度
			int length = 0;
			while((length = in.read(bs))!= -1) {
				//写入
				out.write(bs,0,length);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {//注意关流,应该还要判断out\in是否为空
				out.close();
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

总结:

1、InputStream
read(int b);
read(byte[] bs);
read(b, off, len);

2、OutputStream
创建对象,构造方法里面第二个参数用于判断文件是否要追加。
write(int b);
write(byte[] bs);
write(b, off, len);
一般读文件:
write(byte[] bs,0,length);

3、String<—>字节数组
String—>字节数组
str.getBytes();

字节数组—>String
new String(byte[] bs);

3、字节缓冲输入、输出流

BufferedInputStream和BufferedOutpotStream
基本上与字节输入、输出流相似,创建对象有所不同。
(相当于自己再复习了一遍操作)

BufferedInputStream

举例:
文件内容:
在这里插入图片描述

public class Demo01 {
	public static void main(String[] args) {
		BufferedInputStream bis = null;
		try {
			bis = new BufferedInputStream
					(new FileInputStream("test.txt"));
			//以字节数组进行读取
			byte[] bs = new byte[bis.available()];
			int length = -1;
			//开始整体读取
			length = bis.read(bs);
			//将字节数组转为字符串输出
			String str = new String(bs);
			System.out.println(str);
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if(bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

控制台显示:
在这里插入图片描述
对比另外一种方式:

BufferedInputStream bis = new BufferedInputStream
		(new FileInputStream("test.txt"));
//以字节数组进行读取(随便定义的长度)
byte[] bs = new byte[8];
int length = -1;
//开始读取
while((length = bis.read(bs))!=-1) {
//将字节数组转为字符串输出
String str = new String(bs);
System.out.println(str);
}

控制台显示:
在这里插入图片描述
PS: 这种方式就会产生顺延的现象。

BufferedOutpotStream

public class Demo01 {
	public static void main(String[] args) throws IOException {
		BufferedOutputStream bos = new BufferedOutputStream
				(new FileOutputStream("test.txt"));
		//写入内容
		String str = "时间有泪";
		byte[] bs = str.getBytes();
		bos.write(bs);
		System.out.println("写入成功");
		bos.close();
		//这里如果没有写的话,在test文件中是没有显示"时间有泪"
	}
}

综合:复制粘贴文件

package day2020061401;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Homework_1 {
	public static void main(String[] args) {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		long time1 = 0;
		long time2 = 0;
		try {
			bis = new BufferedInputStream
					(new FileInputStream("src/day2020061401/xiaoshuo.txt"));
			bos = new BufferedOutputStream
					(new FileOutputStream("src/day2020061401/xiaoshuo1.txt"));
			time1 = System.currentTimeMillis();
			//开始读取
			byte[] bs = new byte[1024];
			int length = -1;
			while((length = bis.read(bs)) != -1) {//读到的内容放在了bs中
				bos.write(bs,0,length);
			}
			time2 = System.currentTimeMillis();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {//应该判断bos\bis是否为空
				bos.close();
				bis.close();
				System.out.println((time2-time1));//测试时间
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

以上就是字节输入输出流的全部内容。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/16899.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!