InputStream 只是一个抽象类,在实例化时,需要使用具体的实现类,而InputStream 的实现类有很多,可以认为不同的输入设备都对应着一个InputStream 类,而针对于文件读写时,主要使用 FileInputStream
构造方法 | 说明 |
---|---|
FileInputStream(File file) | 使用 File 对象构造输入流 |
FileInputStream(String name) | 使用文件路径构造输入流 |
返回值 | 方法 | 说明 |
---|---|---|
int | read() | 读取一个字节的数据,返回-1代表已经读完 |
int | read(byte[] b) | 最多读取b.length长度字节的数据到b中,返回实际读到的数量,-1表示读完 |
int | read(byte[] b, int off, int len) | 最多读取off-len长度字节的数据到数组中,从off位置开始放数据 |
void | close() | 关闭字节流 |
代码演示:
第一种读取方式:
public static void main(String[] args) {
try(InputStream is = new FileInputStream("d:/新建文件夹/text.txt")) {
while(true) {
byte[] b = new byte[1024];
int n = is.read(b);//返回读到的字节个数
System.out.println(n);
if(n == -1) {
//表示数据已经读完了
break;
}
for(int i = 0; i < n; i++) {
System.out.printf("%x\n",b[i]);//用十六进制显示
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
第二种读取方式:使用Scanner进行读取
Scanner(InputStream is, String charset) | 使用charset字符集对流对象进行读取 |
---|
public static void main(String[] args) {
try(InputStream is = new FileInputStream("d:/新建文件夹/text.txt");
Scanner scanner = new Scanner(is, "UTF-8")) {
//使用Scanner包装一下流对象,将读的内容转换为字符
while(scanner.hasNext()) {
String s = scanner.next();
System.out.println(s);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
与InputStream一样,OutputStream也是一个抽象类,需要具体类进行实现,例如:FileOutputStream ,构造方法的参数与InpuStream也是一样的;
返回值 | 方法 | 说明 |
---|---|---|
void | write() | 写入一个字节的数据 |
void | write(byte[] b) | 将b这个数组中的数据全都写入文件中 |
void | write(byte[] b, int off, int len) | 将b这个字节数组中,从off这个位置开始的数据写入文件中,一直写len个长度 |
void | close() | 关闭字节流 |
void | flush() | 下面讲解 |
flush作用:
举一个例子,平时嗑瓜子时,难道我们嗑一个瓜子就跑出去扔一个瓜子皮吗?并不是的,而是嗑了许多瓜子之后,瓜子皮一块扔,这样就很省力气,OutputStream 也就是这样的,因为写向硬盘中写入数据时是很慢的,所以,会将写入的数据先存放在缓冲中,等缓冲区满了,再写入到硬盘中,但是这样就会有一个缺陷就是,如果还没来得及写入硬盘中时,进程就结束了,那么数据就遗留到了缓冲区中,所以为了防止这种情况,就可以在合适的位置使用 flush() 来刷新缓冲区,这样才真正的将数据写入到了硬盘中
示例一:
import java.io.*;
public static void main(String[] args) {
//参数中指定一个true表示,写入数据时,不会将文件中原有的数据覆盖掉
try(OutputStream os = new FileOutputStream("d:/新建文件夹/text.txt", true)) {
os.write('a');
os.write('b');
os.write('c');
os.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
示例二:
import java.io.*;
public static void main(String[] args) {
//参数中指定一个true表示,写入数据时,不会将文件中原有的数据覆盖掉
try(OutputStream os = new FileOutputStream("d:/新建文件夹/text.txt", true)) {
byte[] b = new byte[]{(byte)'Q',(byte)'E',(byte)'R',(byte)'T'};
os.write(b);//将数组中的数据全都写入到文件中
os.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
示例三:
import java.io.*;
public static void main(String[] args) {
//参数中指定一个true表示,写入数据时,不会将文件中原有的数据覆盖掉
try(OutputStream os = new FileOutputStream("d:/新建文件夹/text.txt", true)) {
byte[] b = new byte[]{(byte)'Q',(byte)'E',(byte)'R',(byte)'T'};
os.write(b, 0, 3);//将数组中的数据从0位置开始写入到文件中,写入3个字节的数据
os.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
示例四:
import java.io.*;
public static void main(String[] args) {
//参数中指定一个true表示,写入数据时,不会将文件中原有的数据覆盖掉
try(OutputStream os = new FileOutputStream("d:/新建文件夹/text.txt", true)) {
String s = "你好中国";
byte[] b = s.getBytes();
//s.getBytes("UTF-8");指定一个字符集
os.write(b);
os.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
在上述的流对象中,写入数据时,都必须先转化成字节然后再写入,这对于这一点,可以使用PrintWriter 这个类对输出流进行包装,这样就不用我们自己手动的转化了;
PrintWriter 类中,也提供 Print()、printf()、println() 这样的方法进行写入
演示:
public static void main(String[] args) {
try(OutputStream os = new FileOutputStream("d:/新建文件夹/text.txt")) {
try(OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
//也可以省略上一行直接写PrintWriter pw = new PrintWriter(os),只不过这里没有指定字符集
PrintWriter pw = new PrintWriter(osw)) {//告诉它我们使用的字符集时UTF-8
pw.println("我是第一行");//println写入时,会自动写入一个字符串
pw.print("我是第二行\n");
pw.printf("%s\n", "我是第三行");
pw.flush();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
示例1:
扫描指定路径,并找到名称中包含指定字符的所有普通文件,并且后续询问用户是否要删除该文件
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//1.输入文件路径
Scanner in = new Scanner(System.in);
while(true) {
System.out.println("请输入要扫描的路径");
String path = in.nextLine();
//2.判断路径是否正确
File path_file = new File(path);
while(true) {
if(!path_file.exists()) {
System.out.println("您输入的路径不存在,请重新输入");
}else if(!path_file.isDirectory()) {
System.out.println("您输入的路径不是一个目录,请重新输入");
}else{
break;
}
path = in.nextLine();
path_file = new File(path);
}
//3.递归扫描目录,将目标文件加入到集合中
System.out.println("请输入指定字符");
String aim_char = in.nextLine();
List<File> result = new ArrayList<>();
search_comment(path_file, aim_char, result);
//4.遍历这个集合,判断是否要删除该文件
for(File f : result) {
//打印该文件名称
System.out.println("是否要删除该文件"+f.getName()+"(Yes/No):");
while(true) {
String input = in.nextLine().toLowerCase();
if(input.equals("yes")) {
//5.删除操作
f.delete();
System.out.println("删除成功");
break;
}else if(input.equals("no")){
System.out.println("取消删除");
break;
}else {
System.out.println("输入有误,请重新输入");
}
}
}
}
}
private static void search_comment(File path, String aim, List<File> result) {
//将path这个目录中的所有文件全部拿出来进行遍历
File[] all_file = path.listFiles();
if(all_file == null || all_file.length == 0) {
return;
}
for(File f : all_file) {
if(f.isDirectory()) {
//如果f是一个目录,那么就继续递归这个目录
search_comment(f, aim, result);
}else {
//判断该文件是否是目标文件
if(f.getName().contains(aim)) {
//该文件是目标文件,加入到result中
result.add(f);
}
}
}
}
}
示例2:
进行 普通文件的复制
import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//1.输入源文件路径
Scanner scan = new Scanner(System.in);
while (true) {
System.out.println("请输入文件路径:>");
String srcPath = scan.nextLine();
//2.构建file对象
File srcFile = new File(srcPath);
//3.检查指定的源文件
while(true) {
if(!srcFile.exists()) {
//判断指定的文件是否存在
System.out.println("你输入的路径不存在,请重新输入!!!");
}else if(!srcFile.isFile()) {
//如果是目录,则重新输入
System.out.println("您输入的路径不是一个普通文件,请重新输入!!!");
}else {
break;
}
srcPath = scan.nextLine();
srcFile = new File(srcPath);
}
//4.输入目标路径
System.out.println("请输入目标文件路径:>");
String destPath = scan.nextLine();
File destFile = new File(destPath);
//判断要复制的文件在该路径下是否已经存在
while(true) {
if(!destFile.exists()) {
//如果文件不存在,则创建一个文件
try {
destFile.createNewFile();
break;
} catch (IOException e) {
throw new RuntimeException(e);
}
}else if(destFile.isDirectory()) {
System.out.println("您输入的路径是一个目录,请重新输入");
}else if(destFile.isFile()){
//表示目标文件已经存在,是否进行覆盖
System.out.println("目标文件已经存在,是否进行覆盖(Yes/No)");
String input = scan.nextLine().toLowerCase();
if(!input.equals("no")) {
break;
}else {
System.out.println("停止复制");
return;
}
}else {
break;
}
destPath = scan.nextLine();
destFile = new File(destPath);
}
//复制文件
try(InputStream is = new FileInputStream(srcFile);
OutputStream os = new FileOutputStream(destFile)) {
//定义一个数组,用来存储读出的内容
byte[] arr = new byte[1024];
//定义一个标记,用来记录是否读到最后的位置
int len;
while(true) {
//定义循环是为了防止内容不能一次读完
len = is.read(arr);
if(len == -1) {
break;
}
os.write(arr, 0, len);
}
os.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("复制完毕!!!");
}
}
}