16. Java IO 流
16.1 文件及其常用操作
16.1.1 文件的基本介绍
-
什么是文件
-
文件流
16.1.2 常用的文件操作
1. 相关构造器和方法
-
创建文件对象相关构造器和方法
-
举例讲解
注意:
这是创建文件对象后,通过文件对象在指定路径创建一个文件,如果找不到指定路径的文件就会抛出异常
public class FileCreate { public static void main(String[] args) { } //方式1 new File(String pathname) @Test public void create01() { String filePath = "d:\\news1.txt"; File file = new File(filePath); try { file.createNewFile(); //创建一个新文件 System.out.println("文件创建成功"); } catch (IOException e) { e.printStackTrace(); } } //方式2 new File(File parent,String child) //根据父目录文件+子路径构建 //e:\\news2.txt @Test public void create02() { File parentFile = new File("d:\\"); String fileName = "news2.txt"; //这里的file对象,在java程序中,只是一个对象 //只有执行了createNewFile 方法,才会真正的,在磁盘创建该文件 File file = new File(parentFile, fileName); try { file.createNewFile(); System.out.println("创建成功~"); } catch (IOException e) { e.printStackTrace(); } } //方式3 new File(String parent,String child) //根据父目录+子路径构建 @Test public void create03() { //String parentPath = "e:\\"; String parentPath = "d:\\"; String fileName = "news4.txt"; File file = new File(parentPath, fileName); try { file.createNewFile(); System.out.println("创建成功~"); } catch (IOException e) { e.printStackTrace(); } } //下面四个都是抽象类 // //InputStream //OutputStream //Reader //字符输入流 //Writer //字符输出流 }
2. 获取文件的相关信息
方法 | 作用 |
---|---|
getName | 获取文件名 |
getAbsolutePath | 获取文件的绝对路径 |
getParent | 获取父级目录 |
length | 获取文件的大小 |
exists | 判断文件是否存在 |
isFile | 判断是否是文件 |
isDirectory | 判断是否是目录 |
public class FileInformation {
//获取文件的信息
@Test
public void info() {
//先创建文件对象
File file = new File("d:\\news1.txt");
//调用相应的方法,得到对应信息
System.out.println("文件名字=" + file.getName());
//getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory
System.out.println("文件绝对路径=" + file.getAbsolutePath());
System.out.println("文件父级目录=" + file.getParent());
System.out.println("文件大小(字节)=" + file.length());
System.out.println("文件是否存在=" + file.exists());//T
System.out.println("是不是一个文件=" + file.isFile());//T
System.out.println("是不是一个目录=" + file.isDirectory());//F
}
}
3. 目录的操作和文件删除
public class Directory_ {
public static void main(String[] args) {}
//判断 d:\\news1.txt 是否存在,如果存在就删除
@Test
public void m1() {
String filePath = "e:\\news1.txt";
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println(filePath + "删除成功");
} else {
System.out.println(filePath + "删除失败");
}
} else {
System.out.println("该文件不存在...");
}
}
//判断 D:\\demo02 是否存在,存在就删除,否则提示不存在
//这里我们需要体会到,在java编程中,目录也被当做文件
@Test
public void m2() {
String filePath = "D:\\demo02";
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println(filePath + "删除成功");
} else {
System.out.println(filePath + "删除失败");
}
} else {
System.out.println("该目录不存在...");
}
}
//判断 D:\\demo\\a\\b\\c 目录是否存在,如果存在就提示已经存在,否则就创建
@Test
public void m3() {
String directoryPath = "D:\\demo\\a\\b\\c";
File file = new File(directoryPath);
if (file.exists()) {
System.out.println(directoryPath + "存在..");
} else {
if (file.mkdirs()) { //创建一级目录使用mkdir() ,创建多级目录使用mkdirs()
System.out.println(directoryPath + "创建成功..");
} else {
System.out.println(directoryPath + "创建失败...");
}
}
}
}
16.2 IO 流原理及流的分类
16.2.1 IO流原理
-
IO是 Input/Output 的缩写,IO技术是非常实用的技术,用于处理数据传输,如读写文件,网络通讯等
-
Java 程序中,对于数据的输入/输出操作以 "
流(stream)
" 的方式进行 -
Java.io 包下提供了各种 “流” 类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
-
Input 与 Output
-
输入 Input:读取外部数据(磁盘,光盘等储存设备的数据)到程序(内存)中
-
输出 output:将程序(内存)数据输出到磁盘,光盘等储存设备中
-
16.2.2 IO流体系结构及分类
-
按操作数据单位不同分为:
字节流(8 bit)二进制文件
,字符流(按字符)文本文件
-
按数据流的流向不同分为:输入流,输出流
-
按流的角色的不同分为:
节点流
,处理流
,包装流
-
分类表格
字节流:8 bit = 1 Byte,按字节来传输
- Java 的 IO 流共涉及到40多个子类,实际上非常规则,都是从如上
4个抽象基类派生
的 - 由这四个派生类出来的子类名称都是以父类名作为子类名后缀
- Java 的 IO 流共涉及到40多个子类,实际上非常规则,都是从如上
-
IO体系图
16.3 文件IO–常用的类
16.3.1 FileInputStream 类
-
基本介绍及注意事项
- FileInputStream 是以字节的方式从文件中进行读取
- 读文本文件时最好使用字符流,因为汉字一般占两到三个字节,可能会导致乱码
-
常用方法
-
举例说明
public class FileInputStream_ { public static void main(String[] args) {} /** * 演示读取文件... * 单个字节的读取,效率比较低 * -> 使用 read(byte[] b) */ @Test public void readFile01() { String filePath = "e:\\hello.txt"; int readData = 0; FileInputStream fileInputStream = null; try { //创建 FileInputStream 对象,用于读取 文件 fileInputStream = new FileInputStream(filePath); //从该输入流读取一个字节的数据。 如果没有输入可用,此方法将阻止。 //如果返回-1 , 表示读取完毕 while ((readData = fileInputStream.read()) != -1) { System.out.print((char)readData);//转成char显示 } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源. try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 使用 read(byte[] b) 读取文件,提高效率 */ @Test public void readFile02() { String filePath = "e:\\hello.txt"; //字节数组 byte[] buf = new byte[8]; //一次读取8个字节. int readLen = 0; FileInputStream fileInputStream = null; try { //创建 FileInputStream 对象,用于读取 文件 fileInputStream = new FileInputStream(filePath); //从该输入流读取最多b.length字节的数据到字节数组。 此方法将阻塞,直到某些输入可用。 //如果返回-1 , 表示读取完毕 //如果读取正常, 返回实际读取的字节数 while ((readLen = fileInputStream.read(buf)) != -1) { // 注意这里不能直接new String(buf),因为读的时候不一定就 // 读了八个字符,可能只读了3个字符 // new String(byte[])底层 // public String(byte bytes[]) { // this(bytes, 0, bytes.length); // } System.out.print(new String(buf, 0, readLen));//显示 } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源. try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
对于
readFile02()
通过一次性读多个字节的方式读取,可通过调试观察字节数组的读入情况
16.3.2 FileOutputStream 类
-
常用方法
-
举例说明
使用FileOutputStream时:
如果文件不存在,会创建文件(注意:前提是目录已经存在)
public class FileOutputStream01 { public static void main(String[] args) {} /** * 演示使用FileOutputStream 将数据写到文件中, * 如果该文件不存在,则创建该文件 */ @Test public void writeFile() { //创建 FileOutputStream对象 String filePath = "e:\\a.txt"; FileOutputStream fileOutputStream = null; try { //得到 FileOutputStream对象 对象 //老师说明 //1. new FileOutputStream(filePath) 创建方式,当写入内容是,会覆盖原来的内容 //2. new FileOutputStream(filePath, true) 创建方式,当写入内容是,是追加到文件后面 fileOutputStream = new FileOutputStream(filePath, true); //写入一个字节 //fileOutputStream.write('H');// //写入字符串 String str = "hsp,world!"; //str.getBytes() 可以把 字符串-> 字节数组 //fileOutputStream.write(str.getBytes()); /* write(byte[] b, int off, int len) 将 len字节从位于偏移量 off的指定字节数组写入此文件输出流 */ fileOutputStream.write(str.getBytes(), 0, 3); } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
16.3.3 FileIO应用案例–FileCopy
文件拷贝FileCopy: 编程完成图片/音乐 的拷贝
public class FileCopy {
public static void main(String[] args) {
//完成 文件拷贝,将 e:\\Koala.jpg 拷贝 c:\\
//思路分析
//1. 创建文件的输入流 , 将文件读入到程序
//2. 创建文件的输出流, 将读取到的文件数据,写入到指定的文件.
String srcFilePath = "e:\\Koala.jpg";
String destFilePath = "e:\\Koala3.jpg";
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(srcFilePath);
fileOutputStream = new FileOutputStream(destFilePath);
//定义一个字节数组,提高读取效果
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = fileInputStream.read(buf)) != -1) {
//读取到后,就写入到文件 通过 fileOutputStream
//即,是一边读,一边写
fileOutputStream.write(buf, 0, readLen);//一定要使用这个方法
}
System.out.println("拷贝ok~");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//关闭输入流和输出流,释放资源
if (fileInputStream != null) {
fileInputStream.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
16.3.4 FileReader与FileWriter类
-
基本介绍
- FileReader 与 FileWriter 是按照字符对文件进行输入输出
- 注意:在使用FileWriter写数据时,最后一定要flush(刷新)或者close(关闭),数据才会被写进去,否则只是写到了缓冲区里面
-
相关方法
-
FileReader 相关方法
方法 作用 FileReader(File/String)
构造函数 read()
每次读取单个字符,返回该字符,如果到文件末尾返回-1 read(char[])
批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1 public class FileReader_ { @Test public void readFile01() { String filePath = "e:\\story.txt"; FileReader fileReader = null; int data = 0; //1. 创建FileReader对象 try { fileReader = new FileReader(filePath); //循环读取 使用read, 单个字符读取 while ((data = fileReader.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } finally { //.... } } @Test public void readFile02() { String filePath = "e:\\story.txt"; FileReader fileReader = null; int readLen = 0; char[] buf = new char[8]; //1. 创建FileReader对象 try { fileReader = new FileReader(filePath); //循环读取 使用read(buf), 返回的是实际读取到的字符数 //如果返回-1, 说明到文件结束 while ((readLen = fileReader.read(buf)) != -1) { System.out.print(new String(buf, 0, readLen)); } } catch (IOException e) { e.printStackTrace(); } finally { //..... } } }
-
FileWriter 相关方法
方法 作用 FileWriter(File/String)
覆盖模式,相当于流指针在首端 FileWriter(File/String,true)
追加模式,相当于流指针在尾端 write(int)
写入单个字符 write(char[])
写入指定字符数组 write(char[], off, len)
写入数组指定部分 write(string)
写入字符串 write(string, off, len)
写入字符串指定部分 public class FileWriter_ { public static void main(String[] args) { String filePath = "e:\\note.txt"; FileWriter fileWriter = null; char[] chars = {'a', 'b', 'c'}; try { fileWriter = new FileWriter(filePath);//默认是覆盖写入 fileWriter.write('H'); fileWriter.write(chars); fileWriter.write("韩顺平教育".toCharArray(), 0, 3); fileWriter.write(" 你好北京~"); fileWriter.write("风雨之后,定见彩虹"); fileWriter.write("上海天津", 0, 2); } catch (IOException e) { e.printStackTrace(); } finally { //对应FileWriter , 一定要关闭流,或者flush才能真正的把数据写入到文件 //自己追到下面这个方法的源码就知道原因,在close或flush过程中 /* private void writeBytes() throws IOException { ...... } */ try { //fileWriter.flush(); //关闭文件流,等价 flush() + 关闭 fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
-