按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流
1.Java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。
2.由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。
(抽象基类) | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
节点流(或文件流):FileInputStream、FileOutputStream、FileReader、FileWriter
方法:
FileInputStream:read(byte[ ] buffer)
FileOutputStream:write(byte[ ] buffer, 0, len)
FileReader:read(char[ ] cbuf)
FileWriter:write(char[ ] cbuf, 0, len)
缓冲流(处理流的一种):BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
方法:
BufferedInputStream:read(byte[ ] buffer)
BufferedOutputStream:write(byte[ ] buffer, 0, len)、flush()
BufferedReader:read(char[ ] cbuf)、readLine()
BufferedWriter:write(char[ ] cbuf, 0, len)、flush()
将hello.txt文件内容读入程序中,并输出到控制台。
说明:
1.read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1。
2.异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理。
3.读入的文件一定要存在,否则就会报FileNotFoundException。
@Test
public void testFileReader() {
FileReader fr = null;
try {
//1.实例化File类的对象,指明要操作的文件
File file = new File("hello.txt"); //相较于当前Module
//2.提供具体的流
fr = new FileReader(file);
//3.数据的读入
//read():返回读入的一个字符。如果达到文件末尾,返回-1
//方式一:
// int data = fr.read();
// while (data != -1) {
// System.out.print((char) data);
// data = fr.read();
// }
//方式二:语法上针对于方式一的修改
int data;
while ((data = fr.read()) != -1) {
System.out.println((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流的关闭操作
try {
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//对read()操作升级:使用read的重载方法
@Test
public void testFileReader1() {
FileReader fr = null;
try {
//1.File类的实例化
File file = new File("hello.txt");
//2.FileReader流的实例化
fr = new FileReader(file);
//3.读入的操作
//read(char[] cbuf):返回每次读入到cbuf数组中的字符的个数。如果达到文件末尾,返回-1。
char[] cbuf = new char[5];
int len;
while ((len = fr.read(cbuf)) != -1) {
//方式一:
//错误的写法:
// for (int i = 0; i < cbuf.length; i++) {
// System.out.print(cbuf[i]);
// }
// }
//正确的写法:
// for (int i = 0; i < len; i++) {
// System.out.print(cbuf[i]);
// }
//方式二:
//错误的写法:对应着方式一的错误的写法;
// String str = new String(cbuf);
// System.out.println(str);
//正确的写法:
String str = new String(cbuf, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fr != null) {
//4.资源的关闭
try {
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
从内存中写出内存到硬盘的文件里。
说明:
1.输出操作中对应的File是可以不存在的,并不会报异常。
2.
File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。
File对应的硬盘中的文件如果存在:
如果流使用的构造器是:FileWriter(file, false) 或 FileWriter(file),那么将会对原有文件进行覆盖。
如果流使用的构造器是:FileWriter(file, true),那就不会对原有文件进行覆盖,而是在原有的内容上继续追加内容。
@Test
public void testFileWriter() {
FileWriter fw = null;
try {
//1.提供File类的对象,指明写出到的文件。
File file = new File("hello1.txt");
//2.提供FileWriter的对象,用于数据的写出。
fw = new FileWriter(file);
//3.写出的操作
fw.write("I hava a dream!\n");
fw.write("you need to have a dream!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流资源的关闭
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void testFileReaderFileWriter() {
FileReader fr = null;
FileWriter fw = null;
try {
//1.创建File类的对象,指明读入和写出的文件。
File srcFile = new File("hello.txt");
File destFile = new File("hello2.txt");
//不能使用字符流来处理图片等字节数据
// File srcFile = new File("1.jpg");
// File destFile = new File("2.jpg");
//2。创建输入流和输出流的对象
fr = new FileReader(srcFile);
fw = new FileWriter(destFile);
//3.数据的读入和写出操作
char[] cbuf = new char[5];
int len; //记录每次读入到cbuf数组中的字符的个数
while ((len = fr.read(cbuf)) != -1) {
//每次写出len个字符
fw.write(cbuf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流资源
//方式一:
// try {
// if (fw != null)
// fw.close();
// } catch (IOException e) {
// e.printStackTrace();
// } finally {
// try {
// if (fr != null)
// fr.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//方式二:
try {
if (fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
对于文本文件(.txt、.java、.c、.cpp),使用字符流处理。
对于非文本文件(.jpg、.mp3、.mp4、.avi、.doc、.ppt、…),使用字节流处理。
public class FileInputOutputTest {
//使用字节流FileInputStream处理文本文件,可能出现乱码。
@Test
public void testFileInputStream() {
FileInputStream fis = null;
try {
//1.造文件
File file = new File("hello.txt");
//2.造流
fis = new FileInputStream(file);
//3.读数据
byte[] buffer = new byte[5];
int len; //记录每次读取的字节的个数
while ((len = fis.read(buffer)) != -1) {
String str = new String(buffer, 0, len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
//4.关闭资源
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
实现对图片的复制操作
*/
@Test
public void testFileReaderFileWriter() {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//1.创建File类的对象,指明读入和写出的文件。
File srcFile = new File("2022.06.25.jpg");
File destFile = new File("wowo.jpg");
//2.创建输入流和输出流的对象
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
//3.数据的读入和写出操作
byte[] buffer = new byte[5];
int len; //记录每次读入到cbuf数组中的字符的个数
while ((len = fis.read(buffer)) != -1) {
//每次写出len个字符
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流资源
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//指定路径下文件的复制操作
public void copyFile(String srcPath, String destPath) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//1.创建File类的对象,指明读入和写出的文件。
File srcFile = new File(srcPath);
File destFile = new File(destPath);
//2.创建输入流和输出流的对象
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
//3.数据的读入和写出操作
byte[] buffer = new byte[1024];
int len; //记录每次读入到cbuf数组中的字符的个数
while ((len = fis.read(buffer)) != -1) {
//每次写出len个字符
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流资源
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testCopyFile() {
long start = System.currentTimeMillis();
String srcPath = "";
String destParh = "";
copyFile(srcPath, destParh);
long end = System.currentTimeMillis();
System.out.println("复制操作花费的时间为:" + (end - start));
}
}