2.6字节流读数据(一次读一个数据)
需求:把文件fos.txt中的内容读取出来在控制台输出
FileInputStream:从文件系统中的文件获取输出字节
- FileInputStream(String name) :通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
使用字节输入流读数据的步骤:
- 创建字节输入流对象
- 调用字节输入流对象的读数据方法
- 释放资源
方法 | 说明 |
---|---|
int read() | 从该输入流读取一个字节的数据 |
int read(byte[] b) | 从该输入流读取最多 b.length个字节的数据为字节数组。 |
int read(byte[] b, int off, int len) | 从该输入流读取最多 len字节的数据为字节数组 |
2.7 字节缓冲流
字节缓冲流:
- BufferedOutputStream :该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。
- BufferedInputStream:当创建BufferedInputStream时,将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次有多个字节。
构造方法:
- 字节缓冲输入流:BufferedOutputStream(OutputStream out)
- 字节缓冲输出流:BufferedInputStream(InputStream in)
为什么构造方法要的是字节流,而不是具体的文件或路径呢?
- 字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作
3.1为什么会出现字符流
由于字节流操作中文不是特别方便,使用java就提供字符流
- 字符流 = 字节流 + 编码表
用字节流复制文本时,文本文件也会有中文,但是没有问题,原因是因为最终底层操作会自动进行字节拼接成中文,那如何识别中文呢?
- 汉字在存储的时候,无论选择哪种编码,第一个字节都是负数
- 使用GBK编码:中文为两个字节
- 使用UTF-8编码:中文为三个字节
3.2 字符流中的解码编码问题
字符流抽象基类
- Reader:字符输入流的抽象类
- Writer:字符输出流的抽象类
字符流中和编码解码问题相关的两个类:
- InputStreamReader
- OutputStreamWriter
3.3 字符流写数据的五种方式
方法名 | 说明 |
---|---|
void write(int c) | 写一个字符 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入一个字符数组的一部分 |
void write (String str) | 写入一个字符串 |
void write(String str,int off,int len) | 写入一个字符串的一部分 |
flush() | 刷新流,还可以继续写数据 |
close() | 关闭流,释放资源,但在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
3.4字符流读数据的两种方式
方法名 | 说明 |
---|---|
int read() | 一次读一个字符 |
int read(char[] cbuf) | 一次读一个字符数组数据 |
例题1:复制单级文件夹
需求:
- 把G:\itcast 这个文件夹复制到模块目录下
package com.itheima_06;
import java.io.*;
/**
* 需求:
* 把G:\\itcast 这个文件夹复制到模块目录下
* 思路:
* 1.创建数据源目录File对象,路径是G:\\itcast
* 2.获取数据源目录File对象名称(itcast)
* 3.创建目的地目录File对象,路径名是模块名+itcast组成(myCharStream\\itcast)
* 4.判断目的地目录对应的File目录是否存在,如果不存在,就创建
* 5.获取数据源目录下所有文件的File数组
* 6.遍历File数组,得到每一个File对象,该File对象,其实就是数据源文件
* 数据源文件:E:\\itcast\\mn.jpg
* 7.获取数据源文件File对象的名称(mn.jpg)
* 8.创建目的地文件File对象,路径名是目的地目录+mn.jpg组成(myCharStream\\itcast\\mn.jpg)
* 9.复制文件
* 由于不仅仅是文本文件,还有图片、视频等文件,所以采用字节流复制文件
*/
public class CopyFolderDemo {
public static void main(String[] args) throws IOException {
//创建数据源目录File对象,路径是G:\\itcast
File srcfoder = new File("G:\\itcast");
//获取数据源目录File对象名称(itcast)
String srcfoderName = srcfoder.getName();
//创建目的地目录File对象,路径名是模块名+itcast组成(myCharStream\\itcast)
File desFolder = new File("myCharStream", srcfoderName);
//判断目的地目录对应的File目录是否存在,如果不存在,就创建
if (!desFolder.exists()) {
desFolder.mkdir();
}
//获取数据源目录下所有文件的File数组
File[] listFiles = srcfoder.listFiles();
//遍历File数组,得到每一个File对象,该File对象,其实就是数据源文件
for (File srcFile : listFiles) {
//数据源文件:E:\\itcast\\mn.jpg
//获取数据源文件File对象的名称(mn.jpg)
String srcFileName = srcFile.getName();
//创建目的地文件File对象,路径名是目的地目录+mn.jpg组成(myCharStream\\itcast\\mn.jpg)
File desFile = new File(desFolder, srcFileName);
//复制文件
copyFile(srcFile, desFile);
}
}
private static void copyFile(File srcFile, File desFile) throws IOException {
//创建字节输入流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
//创建字节输出流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(desFile));
//使用一次复制一个字节数组的方法进行复制
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read()) != -1){
bos.write(bytes,0,len);
}
//释放资源
bos.close();
bis.close();
}
}
例题2:复制多级文件夹
package com.itheima_06;
/**
* 需求:把G:\\itcast复制到F盘目录下
* 思路
* 1.创建数据源File对象,路径是G:\\itcast
* 2.创建目的地File对象,路径是F:\\
* 3.写方法实现文件夹的复制,参数为数据源File对象和目的地File对象
* 4.判断数据源File是否是目录
* 是:
* A:在目的地下创建和数据源File名称一样的目录
* B:获取数据源File下所有的文件或者目录的File数组
* C:遍历该File数组,得到每一个File对象
* D:把该File作为数据源File对象,递归调用复制文件夹的方法
* 不是:
* 说明是文件,直接复制
*/
import java.io.*;
/*public class CopyFolderDemo2 {
public static void main(String[] args) {
//创建数据源File对象,路径是G:\\itcast
File srcFolder = new File("G:\\itcast");
//创建目的地File对象,路径是F:\\
File desFolder = new File("F:\\");
//写方法实现文件夹的复制,参数为数据源File对象和目的地File对象
copyFolder(srcFolder,desFolder);
}
private static void copyFolder(File srcFolder, File desFolder) {
//获取数据源目录File对象名称(itcast)
String srcFolderName = srcFolder.getName();
//创建目的地目录File对象,路径名是模F+itcast组成
File desFolder2 = new File(desFolder,srcFolderName);
//判断目的地目录对应的File目录是否存在,如果不存在,就创建
if (!desFolder2.exists()){
desFolder2.mkdir();
}
//获取数据源目录下所有文件的File数组
File[] listFiles = srcFolder.listFiles();
//判断数据源File是否是目录
for (File srcFile : listFiles){
if (srcFile.isDirectory()){
//获取数据源File名称
String srcFileName = srcFile.getName();
//在目的地下创建和数据源File名称一样的目录
File desFile = new File(desFolder2,srcFileName);
}
}
}
}*/ //想不清楚接下来应该怎样去写,不知道怎样去写递归调用
public class CopyFolderDemo2 {
public static void main(String[] args) throws IOException {
//创建数据源File对象,路径是G:\\itcast
File srcFile = new File("G:\\itcast");
//创建目的地File对象,路径是F:\\
File desFile = new File("F:\\");
//写方法实现文件夹的复制,参数为数据源File对象和目的地File对象
copyFolder(srcFile, desFile);
}
//复制文件夹的方法
private static void copyFolder(File srcFile, File desFile) throws IOException {
//判断数据源File是否是目录
if (srcFile.isDirectory()) {
//在目的地下创建和数据源File名称一样的目录
String srcFileName = srcFile.getName();
File newFolder = new File(srcFile, srcFileName);//这一步创建 F:\\itcast
if (!newFolder.exists()){
newFolder.mkdir();
}
//获取数据源File下所有的文件或者目录的File数组
File[] filesArray = srcFile.listFiles();
//把该File作为数据源File对象,递归调用复制文件夹的方法
for (File file : filesArray) {
copyFolder(file, newFolder);
}
} else {
//说明是文件,直接复制
File newFile = new File(srcFile, srcFile.getName());
copyFile(srcFile, newFile);
}
}
//复制文件
private static void copyFile(File srcFile, File desFile) throws IOException {
//创建字节输入流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
//创建字节输出流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(desFile));
//使用一次复制一个字节数组的方法进行复制
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read()) != -1) {
bos.write(bytes, 0, len);
}
//释放资源
bos.close();
bis.close();
}
}