IO流-2
1. IO流概述
当需要进行数据的传输的时候可以使用IO流来进行。例如:把磁盘中文件的数据读取到内存中。把内存中的数据写入到磁盘中。把网络中的数据读取到内存中。
2. IO流分类
IO流根据处理数据类型的不同分为字符流和字节流,根据数据流向不同分为输入流和输出流,对输入流只能进行读操作,对输出流只能进行写操作。
数据类型 | 流向 | 顶层父类 |
---|---|---|
字节流 | 输入(读) | java.io.InputStream |
字节流 | 输出(写) | java.io.OutputStream |
字符流 | 输入(读) | java.io.Reader |
字符流 | 输出(写) | java.io.Writer |
3. 字节输入流
所有字节输入流的父类是 java.io.InputStream ,它是以字节为单位的输入流 。
我们就以FileInputStream为例进行学习。
3.1 FileInputStream概述
FileInputStream是用来读取文件数据的字节输入流。
3.2 FileInputStream对象创建
构造方法如下:
FileInputStream(String name) throws FileNotFoundException //传入文件路径创建对象
FileInputStream(File file) throws FileNotFoundException //传入文件路径的File对象来创建流对象
范例:
public static void main(String[] args) throws FileNotFoundException {
//创建对象
FileInputStream fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt");
System.out.println(fis);
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt");
FileInputStream fis2 = new FileInputStream(file);
System.out.println(fis);
}
3.3 读取数据
我们可以使用FileInputStream来读取文件中的字节数据。
3.3.1 一次读取一个字节
核心方法如下:
public int read() throws IOException // 读取一个字节的数据作为返回值返回 返回值为-1时代表以及没有内容了
范例:
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt");
//读取数据
int b;
while((b=fis.read())!=-1){
System.out.println(b);
}
//释放资源
fis.close();
}
3.3.2 一次读取一个字节数组
核心方法如下:
public int read(byte b[]) throws IOException //传入一个字节数组,最多读取一个字节数组的数据,并且会把数据存入数组中,返回值代表本次读取到的字节的个数。 如果返回值为-1代表没有数据了
范例:
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt");
//读取数据 一次读一个字节数组
byte[] bytes = new byte[1024*2];
int len;
while ((len=fis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
//释放资源
fis.close();
}
3.4 资源释放
我们在前面处理异常的时候都同意做了声明抛出的处理。但是这很可能导致在出现了异常时资源没有被正确的释放。所以我们要更合理的处理异常,尤其是处理资源释放的问题。
3.4.1 JDK6版本
private static void test() {
FileInputStream fis = null;
try{
fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt");
//读取数据 一次读一个字节数组
byte[] bytes = new byte[1024*2];
int len;
while ((len=fis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
}catch (IOException e){
e.printStackTrace();
}finally {
//释放资源
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.4.2 JDK7版本
可以使用try…catch…resource的写法,在try的后面可以加小括号,把需要释放的资源在小括号中定义。我们就不需要自己去释放资源,jvm会帮我们再最后调用close方法释放资源的。
private static void test2() {
try(FileInputStream fis =new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt"); ){
//读取数据 一次读一个字节数组
byte[] bytes = new byte[1024*2];
int len;
while ((len=fis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
}catch (IOException e){
e.printStackTrace();
}
}
3.4.3 JDK9版本
资源的定义也可以不放在try的小括号中,只要在try的小括号中声明要释放的资源即可。
private static void test3() throws FileNotFoundException {
FileInputStream fis =new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt");
try(fis ){
//读取数据 一次读一个字节数组
byte[] bytes = new byte[1024*2];
int len;
while ((len=fis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
}catch (IOException e){
e.printStackTrace();
}
}
4. 字节输出流
所有字节输出流的父类是 java.io.OutputStream ,它是以字节为单位的输出流 。
我们就以FileOutputStream为例进行学习。
4.1 FileOutputStream概述
FileOutputStream是用来往文件中写入数据的字节输出流。
4.2 FileOutputStream对象创建
常用构造方法如下:
FileOutputStream(String name) throws FileNotFoundException //传入文件路径创建对象
FileOutputStream(File file) throws FileNotFoundException //传入文件路径的File对象来创建流对象
示例:
public static void main(String[] args) throws FileNotFoundException {
FileOutputStream fos = new FileOutputStream("C:\\Users\\root\\Desktop\\test\\11.txt");
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt");
FileOutputStream fos2 = new FileOutputStream(file);
}
4.3 写数据
我们可以使用FileOutputStream来往文件中写入字节数据。
4.3.1 一次写一个字节
核心方法如下:
public void write(int b) throws IOException //传入一个字节数据,把字节数据写入文件
范例:
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt");
FileOutputStream fos = new FileOutputStream(file);
fos.write('a');
fos.close();
}
4.3.2 一次写一个字节数组
核心方法如下:
public void write(byte b[]) throws IOException // 存入一个字节数组,把字节数组中的数据全部写入文件
public void write(byte b[], int off, int len) throws IOException //存入一个字节数组,把字节数组中从off索引开始len个元素写入文件
范例:
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt");
FileOutputStream fos = new FileOutputStream(file);
byte[] bytes = "abc".getBytes();
// fos.write(bytes);
fos.write(bytes,0,2);
fos.close();
}
4.4文件续写
如果用之前的构造方法创建的流对象,每次流对象创建的时候就会把文件中的内容情况。所以没有办法实现续写的效果。如果需要续写就需要使用另外的构造方法。
FileOutputStream(String name, boolean append) throws FileNotFoundException //第二个参数代表是否续写
FileOutputStream(File file, boolean append) throws FileNotFoundException //第二个参数代表是否续写
使用什么的构造创建流对象,并且第二个参数传入true,就不会清空文件中原有的内容。实现文件续写的效果。
范例:
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt");
FileOutputStream fos = new FileOutputStream(file,true);
byte[] bytes = "abc".getBytes();
// fos.write(bytes);
fos.write(bytes,0,2);
fos.close();
}
5.练习
5.1 文件复制
要求定义一个方法,该方法能够实现文件的复制
public static void main(String[] args) throws IOException {
// 要求定义一个方法,该方法能够实现文件的复制
// 文件的复制就是循环的读写,直到操作完所有数据为止
File src = new File("C:\\Users\\root\\Desktop\\test\\11.txt");
File destDir = new File("C:\\Users\\root\\Desktop\\test\\a");
copyFile(src,destDir);
}
//源文件的路径 File srcFile
//目标文件的存放目录路径 File destDir
public static void copyFile(File srcFile,File destDir) throws IOException {
//在destDir下创建一个和srcFile同名的文件
File destFile = new File(destDir,srcFile.getName());
//读取源文件 把读到的数据写入目标文件destFile
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
byte[] bytes = new byte[1024];
int len;
while((len=fis.read(bytes))!=-1){
//把读到的内容写入新文件中
fos.write(bytes,0,len);
}
//释放资源
fis.close();
fos.close();
}
5.2 文件夹复制
要求定义一个方法,该方法能够实现文件夹的复制
public class Test09 {
public static void main(String[] args) throws IOException {
//要求定义一个方法,该方法能够实现文件夹的复制,考虑有子文件夹的情况
File srcDir = new File("C:\\Users\\root\\Desktop\\test");
File dest = new File("C:\\Users\\root\\Desktop\\test2");
copyDir(srcDir,dest);
}
//File srcDir 源文件夹
//File dest要复制到哪个目录
public static void copyDir(File srcDir,File dest ) throws IOException {
if(!(srcDir.exists()&&srcDir.isDirectory())){
throw new RuntimeException("源文件夹必须存在并且是一个文件夹");
}
if(!dest.isDirectory()){
throw new RuntimeException("目标文件夹必须是一个文件夹");
}
//1.在目标文件夹下创建一个和源文件夹同名的文件夹destDir
File destDir = new File(dest,srcDir.getName());
destDir.mkdirs();
//2.获取源文件夹下的所有子文件
File[] files = srcDir.listFiles();
if(files!=null){
//3.遍历数组,复制每一个文件到目标文件夹destDir下
for (File file : files) {
if(file.isFile()){
copyFile(file,destDir);
}else {
//复制文件夹
copyDir(file,destDir);
}
}
}
}
//源文件的路径 File srcFile
//目标文件的存放目录路径 File destDir
public static void copyFile(File srcFile,File destDir) throws IOException {
//在destDir下创建一个和srcFile同名的文件
File destFile = new File(destDir,srcFile.getName());
//读取源文件 把读到的数据写入目标文件destFile
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
byte[] bytes = new byte[1024];
int len;
while((len=fis.read(bytes))!=-1){
//把读到的内容写入新文件中
fos.write(bytes,0,len);
}
//释放资源
fis.close();
fos.close();
}
}