input output 像水流一样读取数据
存储和读取数据的解决方案
内存中数据不能永久化存储 程序停止运行 数据消失
File只能对文件本身进行操作 不能读写文件里存储的数据
读写数据必须要有IO流
可以把程序中的数据保存到文件当中
还可以把本地文件中的数据读取到数据当中
分类
流的方向
输入流 读取
输出流 写出
操作文件类型
字节流 操作所有类型的文件
字符流 只能操作纯文本文件
纯文本文件时用微软自带的记事本打开能读的懂的文件
基本用法
写一段文字到本地文件当中
需要把文件放到包下 先创建文件
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {//抛出异常
//本地文件
FileOutputStream fos=new FileOutputStream("untitled1\\a.txt");
fos.write(97);//父类异常
fos.close();//释放资源
}
}
创建对象时 会根据路径让程序和文件产生通道
之后我们即可以进行数据的传输
当使用了close方法后 相当于切断了通道
写出数据的细节
创建字节输出流对象
1.参数是字符串表示的路径或者是File对象都是可以的
2.如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
3.如果文件已经存在,则会清空文件
写数据
1.write 方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
97 -> a
100 -> d
释放资源
是IO流中每一种流都要使用
每一次使用完流后,都要释放IO流
如果不释放流
会显示,操作无法完成,文件已经在Java Platform SE binary中打开
释放资源就是解决了资源的占用
总结
字节输出流FileOutputStream
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
FileOutputStream f=new FileOutputStream("untitled1\\a.txt");
byte arr[]=new byte[]{97,98,99};
f.write(arr,1,2);
f.close();
//文件中是bc
}
}
写出数据的几个问题
1.把字符串写入文件
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
FileOutputStream f=new FileOutputStream("untitled1\\a.txt");
String str="Dduo";
String s=new String("Dduo");
byte[] bytes = str.getBytes();
//把字符串获取成字节数组
f.write(bytes);
f.close();
}
}
window系统
\r 表示回车
\n 表示换行
Linux系统
\n换行
Mac系统
\r换行
在window操作系统中,java对换行进行了优化,虽然完整的是\r\n,但是我们写其中一个\r或者\n
java也可以实现换行,因为java在底层会进行补全
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
FileOutputStream f=new FileOutputStream("untitled1\\a.txt");
String s1=new String("Dduo");
byte[] bytes1 = s1.getBytes();
f.write(bytes1);
String s2=new String("\r\n");
byte[] bytes2 = s2.getBytes();
f.write(bytes2);
String s3=new String("666");
byte[] bytes3 = s3.getBytes();
f.write(bytes3);
f.close();
}
}
创建对象时第二个参数就是续写开关
默认数值是false 表示关闭续写 此时创建对象会清空文件
手动传递true表示打开续写,此时创建对象的时候不会清空文件
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
while(true){
FileOutputStream f=new FileOutputStream("untitled1\\a.txt",true);
String s1=new String("Dduo666");
byte[] bytes1 = s1.getBytes();
f.write(bytes1);
String s2=new String("\r\n");
byte[] bytes2 = s2.getBytes();
f.write(bytes2);
f.close();
}
}
}
这样会输出44万行 直到文本文档的大小达到2.56MB
小结
字节输入流FileInputStream
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
//创建对象
FileInputStream fis=new FileInputStream("untitled1\\a.txt");
//读取数据
int b1 = fis.read();
System.out.println((char) b1);
fis.close();
}
}
read方法负责读取文件当中的数据
如果读不到了 返回-1
写入数据的细节
如果文件不存在就会直接报错
Java为什么会这么设计呢
输出流:不存在,创建
输入流:不存在,报错 因为创建出来的数据是没有数据的没有任何意义 这种逻辑没有意义
读取数据
一次读一个字节
读出来的数据是在ASCII上对应的数字
读到文件末尾了,read方法返回的是-1
如果是空格 则读取空格所对应的ASCII码30
如果是负数 则会先读取符号 不会当做一个整体
释放资源
每一次使用完流必须要释放资源
字节输入流循环读取
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
//创建对象
FileInputStream fis=new FileInputStream("untitled1\\a.txt");
int b;
while((b=fis.read())!=-1) System.out.print((char) b);
}
}
定义一个变量b
read方法表示读取数据。并且读取一次就移动一次指针
和迭代器相似
所以要用第三方变量接收
文件拷贝 (挨个字节拷贝)
拷贝文件夹到指定的文件当中
先开的流最后关闭
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
long start=System.currentTimeMillis();
//写入
FileOutputStream fos=new FileOutputStream("untitled1\\a.txt");
//读取
FileInputStream fis=new FileInputStream("untitled1\\b.txt");
int b;
while((b=fis.read())!=-1) fos.write(b);
long end=System.currentTimeMillis();//获取当前系统的时间
System.out.println("运行时间为:"+(end-start));
//先开的流最后关
fis.close();
fos.close();
}
}
FileInputStream读取的问题
拷贝一次只能读写一个字节
速度太慢了
可以用字节数组
一次读一个字节数组的数据,我们要尽可能将字节数组填满
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
long start=System.currentTimeMillis();
//读取
FileInputStream fis=new FileInputStream("untitled1\\b.txt");
//创建字节数组
byte []bytes=new byte[7];
System.out.println(fis.read(bytes));
System.out.println(new String(bytes));
long end=System.currentTimeMillis();
System.out.println("运行时间为:"+(end-start)+"毫秒");
//先开的流最后关
fis.close();
}
}
输出结果是7个字节
其中换行回车一共是2个字节 一个英文字母是一个字节
如果越界了 读取不到东西 数组元素就不会改变
read方法如果读取不到数据就会返回-1
文件拷贝代码改写
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
long start=System.currentTimeMillis();
//写入
FileOutputStream fos=new FileOutputStream("untitled1\\a.txt");
//读取
FileInputStream fis=new FileInputStream("untitled1\\b.txt");
int b;
byte []bytes=new byte[1024*1024*5];
while((b=fis.read(bytes))!=-1) fos.write(bytes,0, b);
long end=System.currentTimeMillis();//获取当前系统的时间
System.out.println("拷贝成功");
System.out.println("运行时间为:"+(end-start));
//先开的流最后关
fis.close();
fos.close();
}
}
后两个参数是防止读取不到东西导致把上一次存入字节数组的数据又写入文件
try...catch异常处理
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
long start=System.currentTimeMillis();//获取当前系统的时间
FileOutputStream fos=null;
FileInputStream fis=null;
try {
//写入
fos=new FileOutputStream("untitled1\\a.txt");
//读取
fis=new FileInputStream("untitled1\\b.txt");
int b;
byte []bytes=new byte[1024*1024*5];
while((b=fis.read(bytes))!=-1) fos.write(bytes,0, b);
long end=System.currentTimeMillis();//获取当前系统的时间
System.out.println("拷贝成功");
System.out.println("运行时间为:"+(end-start)+"毫秒");
}
catch (IOException e) {
throw new RuntimeException(e);
}
finally {
if(fos!=null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fis!=null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//先开的流最后关
}
}
代码复杂
我们需要学习一下设计思想
释放资源过于复杂
AutoCloseable接口
以后所有的异常我们都是抛出处理
个人号推广
博客主页
朱道阳-CSDN博客
Web后端开发
https://blog.csdn.net/qq_30500575/category_12624592.html?spm=1001.2014.3001.5482
Web前端开发
https://blog.csdn.net/qq_30500575/category_12642989.html?spm=1001.2014.3001.5482
数据库开发
https://blog.csdn.net/qq_30500575/category_12651993.html?spm=1001.2014.3001.5482
项目实战
https://blog.csdn.net/qq_30500575/category_12699801.html?spm=1001.2014.3001.5482
算法与数据结构
https://blog.csdn.net/qq_30500575/category_12630954.html?spm=1001.2014.3001.5482
计算机基础
https://blog.csdn.net/qq_30500575/category_12701605.html?spm=1001.2014.3001.5482
回忆录
https://blog.csdn.net/qq_30500575/category_12620276.html?spm=1001.2014.3001.5482