文件
保存数据的地方
文件流
文件在程序中是以流的形式来操作的
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:文件->内存
输出流:内存->文件
常用的文件操作
创建文件的三个方法

方式1
//方式1
@Test
public void create01(){
String filepath = "d:\\create01.txt";//也可以d:/create01.txt
File file = new File(filepath);
try {
file.createNewFile();
System.out.println("创建文件成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
方式2
//方式2
@Test
public void create02(){
File parentFile = new File("d:\\");
String fileName = "create02.txt";
File file = new File(parentFile, fileName);
try {
file.createNewFile();
System.out.println("创建文件成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
方式3
//方式3
@Test
public void create03(){
String parentPath = "d:\\";
String fileName = "create03.txt";
File file = new File(parentPath, fileName);
try {
file.createNewFile();
System.out.println("创建文件成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
补充:
1.想直接执行某个方法,可以不用在main方法里创建对象再调用,可以在方法上一行加上@Test
(单元测试)


2.创建文件路径的两个不同写法
"d:\\create01.txt"
"d:/create01.txt"
总结:
1.方式1和方式3很像,只不过方式3把路径和文件名分开写了,而方式2需要创建一个父目录路径对象
2.直接写 file.createNewFile();会报错,需要try-catch
获取文件的信息

1.先创建文件对象
File file = new File("e:\\create01.txt");
2.调用方法即可

方法什么意思看方法名就知道了,这里略过
目录操作和文件删除

删除文件
1.创建文件对象
File file = new File("e:\\create01.txt");
2.调用delete方法
@Test
public void delete(){
File file = new File("d:\\create01.txt");
if(file.exists()){//先判断文件存不存在
if(file.delete()){
System.out.println("文件删除成功");
}else {
System.out.println("文件删除失败");
}
}else {
System.out.println("文件不存在");
}
}
删除目录
(目录在java编程中也被当成文件)
1.创建文件对象
File file = new File("e:\\demo01");
2.调用delete方法
@Test
public void delete(){
File file = new File("d:\\demo01");
if(file.exists()){//先判断目录存不存在
if(file.delete()){
System.out.println("目录删除成功");
}else {
System.out.println("目录删除失败");
}
}else {
System.out.println("目录不存在");
}
}
创建多级目录
@Test
public void create01(){
File file = new File("d:\\a\\b\\c");
if(file.exists()){
System.out.println("目录存在");
}else {
if(file.mkdirs()){//创建多级目录,创建一级目录用mkdirs即可
System.out.println("创建成功");
}else{
System.out.println("创建失败");
}
}
}
IO流分类
按流向分类:输入流,输出流
按操作的数据单位:字符流(用于文本文件(有中文,英文...)),字节流(二进制文件)
可以得到4个不同的操作
InputStream//字节输入流
OutputStream//字节输出流
Reader//字符输入流
Writer//字符输出流
这4个都是抽象基类,IO流大部分类都是这4个类派生出来的

InputStream(字节输入流)
主要有3个常用子类
1.FileInputStream文件输入流
2.BufferedInputStream缓冲字节输入流
3.ObjectInputStream对象输入流
1.FileInputStream
@Test
public void readFile01(){
String filePath = "d:\\hello.txt";
int readData = 0;
FileInputStream fileInputStream = null;
try {
//创建FileInputStream对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
//read方法:从该输入流中读取一个字节的数据,如果没有输入可用,该方法将会被阻止
//如果返回-1,表示读取完毕
while ((readData = fileInputStream.read()) != -1){
System.out.print((char)readData);//读的是int类型,强转成char才能显示
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件流
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
详解:
1.创建fileInputStream 对象的时候,会报一次异常

相关解释:
说明某个方法在方法声明上已经声明了会抛异常,那么在调用这个方法的时候,就必须做异常处理,处理的方式有2种,要么try-catch这个异常,要么继续往上一层抛出这个异常,这是java语法要求的,必须这么做
所以我们try-catch一下就好了
2.read方法

我们可以看到int是类型,所以我们要定义一个int类型来接他的返回值
int readData = 0;
readData = fileInputStream.read()
此时又会报一个异常

根据前面异常那一章,我们可以把catch里的FileNotFoundException换成更高一级的异常IOException,这样就不会报错了
3.因为要输出字符,所以把readData强转成char类型
System.out.print((char)readData);
然后用while循环不停的从文件读取内容即可
4.最后我们要在finally用对象名.close()关闭这个流,避免浪费
会发现

这是因为我们的对象fileInputStream是在try语句内创建的,他的作用域只在try里,我们只要在try外创建对象,然后分别在try和finally里使用就好了
此时又会报错,再try-catch一下就好了

优化读取效率
换一个方法
read(byte[] b)
@Test
public void readFile02() {
String filePath = "d:\\hello.txt";
FileInputStream fileInputStream = null;
int readLen = 0;
//字符数组,一次读取8个字符
byte[] buf = new byte[8];
try {
fileInputStream = new FileInputStream(filePath);
while((readLen = fileInputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
补充:这里的new String方法是把数组转成字符串
2.FileOutputStream
配对着讲了,输入对输出
其实大致差不多,就改一些细节位置

- write第一个方法,输出一个字节
@Test
public void writeFile01(){
String filePath = "D:\\test.txt";
//创建FileOutputStream对象
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filePath);
fileOutputStream.write('x');
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- write第二个方法 输入一整个字节数组
@Test
public void writeFile01(){
String filePath = "D:\\test.txt";
//创建FileOutputStream对象
FileOutputStream fileOutputStream = null;
String str = "hello, my world!";
try {
fileOutputStream = new FileOutputStream(filePath);
fileOutputStream.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
补充:getBytes()方法把字符串->字节数组
- write第三个方法 输入指定长度的字节数组
@Test
public void writeFile01(){
String filePath = "D:\\test.txt";
//创建FileOutputStream对象
FileOutputStream fileOutputStream = null;
String str = "hello, my world!";
try {
fileOutputStream = new FileOutputStream(filePath);
fileOutputStream.write(str.getBytes(),0 ,3);//off是开头位置,len是输出长度
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
如果每次输入不想覆盖原来的,那就在改为
fileOutputStream = new FileOutputStream(filePath, true);

小练习--实现复制黏贴
public class FileCopy {
public static void main(String[] args) {
//创建地址
String oriFilePath = "d:\\3.mp4";
String desFilePath = "d:\\4.mp4";
//创建输入输出流对象
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
//创建储存字节数组
byte[] buf = new byte[1024];
int readLen = 0;
try {
//读取地址
fileInputStream = new FileInputStream(oriFilePath);
fileOutputStream = new FileOutputStream(desFilePath);
while((readLen = fileInputStream.read(buf)) != -1){
//这里用 fileOutputStream.write(buf, 0, readLen)都可以,都是一边输入一边输出
fileOutputStream.write(buf);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
补充:关于 fileOutputStream.write();用哪一个write方法,韩顺平老师推荐的是用fileOutputStream.write(buf, 0, readLen)方法,但我两个方法都试过好几次了,并没有出现打不开的情况,所以我觉得都应该是没问题的
字符IO流
相比于字节流,字符流是按字符读取数据,所以可以拷贝中文了
1.FileReader

练习--读取一个含有中文的文档
public class FileReaderTest {
public static void main(String[] args) {
//创建地址
String filePath = "d:\\test.txt";
//创建文件对象
FileReader fileReader = null;
//创建容量为8的字符数组
char[] arr = new char[8];
int readLen = 0;
try {
fileReader = new FileReader(filePath);//读取地址
//读取到文件末尾返回-1,停止读取
while((readLen = fileReader.read(arr)) != -1){
System.out.print(new String(arr, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
补充:
1.创建java文档时候别起和类相同的名字,避免遇到不必要的麻烦
2.读取txt文档没问题,但读取其他格式的文档会乱码如docx
2.FileWriter

练习--写入一段话到文档中
public class FileWriterTest {
public static void main(String[] args) {
//创建地址
String filePath = "d:\\test.txt";
//创建FileWriter对象
FileWriter fileWriter = null;
String info = "英特纳雄耐尔,就一定要实现";
try {
fileWriter = new FileWriter(filePath,true);
fileWriter.write(info);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
总结
感觉JavaIO流都差不多,掌握格式然后注意方法的用法就行了,可能是我学的不精吧哈哈,剩下的以后再补,去学多线程了
