InputStream
把数据从硬盘读到内存中,输入输出的方向,是以CPU/内存为中心,所以读数据是input,写数据是output
int | read() | 从输入流读取数据的下一个字节。 值被返回作为int 范围0 至255 。 如果没有字节可用,因为已经到达流的末尾,则返回值-1 。 该方法阻塞直到输入数据可用,检测到流的结尾,或抛出异常 |
int | read(byte[] b) | 从输入流读取一些字节数,并将它们存储到缓冲区b 。 实际读取的字节数作为整数返回。 该方法阻塞直到输入数据可用,检测到文件结束或抛出异常。 如果 |
int | read(byte[] b, | 从输入流读取len 字节的数据到一个字节数组。 尝试读取多达len 个字节,但可以读取较小的数字。 实际读取的字节数作为整数返回。 该方法阻塞直到输入数据可用,检测到文件结束或抛出异常。 如果 第一个字节读取存储在元素 |
void | close() | 关闭字节流 |
注意:InputStream是一个抽象类,需要子类去重写这些方法,而我们这关心从文件读取,所以适用FileInputStream
FileInputStream
FileInputStream(File file) | 利用File构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
public static void main(String[] args) throws IOException {
InputStream inputStream = new FileInputStream("./dir/aaa/bbb/test.txt");//该文件中已经填充有hello world
while(true){
int ret = inputStream.read();
if(ret == -1){
break;
}
System.out.println(ret);
}
inputStream.close();//更推荐适用try(),以免自己忘记关闭
}
inputstream是字节流,我们也可以通过给Scanner传入inputstream,包装出一个字符流
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("./dir/aaa/bbb/test.txt")){//相当于inputStream.close()
Scanner scanner = new Scanner(inputStream);
while(scanner.hasNext()){
System.out.println(scanner.next());
}
}
}
此时输出的就是hello world
通过字符流Reader读取文件
public static void main(String[] args) throws IOException {
try(Reader reader = new FileReader("./dir/aaa/bbb/test.txt")){
while(true){
int ret = reader.read();
if(ret == -1){
break;
}
char ch = (char) ret;
System.out.println(ch);
}
}
OutputStream
void | write(int b) | 将指定字节写入输出流 |
void | write(byte[] b) | 将b.length字节从指定的字节数组写入此输出流 |
void | write(byte [] b, int off, int len) | 将指定的字节数组写入len个字节,从偏移off开始输出到输出流 |
void | close() | 关闭输出流并释放与此流相关的任何系统资源 |
void | flush() | 我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中 |
OutputStream也是抽象类,需要子类重写父类的方法,在文件操作中使用FileOutputStream.
public static void main(String[] args) throws IOException {
try(OutputStream outputStream = new FileOutputStream("./dir/aaa/bbb/test.txt")){//原文件的内容会被删除,重新写入
outputStream.write(97);
outputStream.write(98);
outputStream.write(99);
outputStream.flush();
}
}
利用PrintWriter简化开发
public static void main(String[] args) throws IOException {
try(OutputStream outputStream = new FileOutputStream("./dir/aaa/bbb/test.txt")){
try(PrintWriter writer = new PrintWriter(outputStream)){
writer.print("hello world");
}
}
使用字符流写文件 Writer
public static void main(String[] args) throws IOException {
try(Writer writer = new FileWriter("./dir/aaa/bbb/test.txt")){
writer.write("welcome to China");
}
}
纸上得来终觉浅,觉知此事要躬行。
题目:扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件
public static void main(String[] args) throws IOException {
//1.让用户输入信息
System.out.println("请输入你要扫描的路径");
Scanner scanner = new Scanner(System.in);
File dir = new File(scanner.next());
if(!dir.isDirectory()){
System.out.println("你输入的目录不存在");
return;
}
System.out.println("请输入关键字");
String toDelete = scanner.next();
//遍历目录
scanDir(dir, toDelete);
}
private static void scanDir(File dir, String toDelete) throws IOException {
System.out.println("当前访问:"+dir.getCanonicalPath());
File[] files = dir.listFiles();//返回目录下的所有文件
if(files == null){
System.out.println("目录为空");
return;
}
for (File f : files) {
if(f.isDirectory()){
scanDir(f, toDelete);//直到找到文件
}else{
checkDelete(f, toDelete);
}
}
}
private static void checkDelete(File f, String toDelete) throws IOException {
if(f.getName().contains(toDelete)){
System.out.println("该单词"+toDelete+"被"+f.getCanonicalPath()+"包含");
System.out.println("是否要删除(Y/N)");
Scanner scanner = new Scanner(System.in);
String choice = scanner.next();
if(choice.equals("Y") || choice.equals("y")){
f.delete();
System.out.println("删除成功");
}
}
}
注意:这里的路径是俺已经存在的,你在输入的时候要使用你自己的路径