声明
首先在学习io流的时候一定要看明白字节流和字符流的的父类。关系如下 :
一,字节流
注意事项,
1,用完流一定要手动关闭,
2,用到read读取方法的时候,是按照一个字节一个字节来读取。
3,如果按照常规的read方法读取的结果如果存在汉字,会出现乱码
4,流的读取是依次向下的,如果你已经读取一个流的部分内容,但是未读取完毕,那么接下来的再次出现读取该流的内容的时候,会接着往下面继续读,无法返回已经读取过的位置
5,在使用书写的时候,要注意字节流书写的参数是int类型,如果范围在-128---127内,会出现正常的值(可能是字母,数字,符号),如果超出这个范围。就会乱码
6,在没有设置文件流是添加的情况下,书写会覆盖掉原本的值
文档准备:注意每个文档的内容和名称
代码演示如下:
字节输入流
// IO流文件的读取
public static void main(String[] args) throws Exception {
// 首先创建一个文件流对象,获取到到文件 路径可以用相对路径也可以用绝对路径
// todo 绝对路径
// InputStream is=new FileInputStream("D:\\Cllection\\day17\\src\\com\\haogu\\write.txt");
// todo 相对路径
InputStream is=new FileInputStream("src/com/haogu/write.txt");
InputStream is2=new FileInputStream("src/com/haogu/write2.txt");
InputStream is3=new FileInputStream("src/com/haogu/write3.txt");
// 读取文件的内容
System.out.println("注意输出三次会发现他是依次向下输入内容,而不是重复输出第一个内容");
// io是一个流的形式 读取是向下流动读取
System.out.println(is2.read());
System.out.println(is2.read());
// TODO:内容读取完毕之后继续读取会输出-1
// 并且发现他们读取出来的数据是unicode编码值想要文件的具体内容需要格式转化
// 在接下来的循环里面展示
System.out.println(is2.read());
int num;
System.out.println("如果有文字的情况下会出现乱码:因为常用文字在utf-8占三个字符,不常用文字占4个字符");
System.out.println("字符流输出只能一个一个字节去输出");
while((num=is.read())!=-1){
System.out.print((char)num);
}
// 为了避免乱码调整的策略
// 处理乱码方式
//先定义一个字节数组(晚点用来保存读出来数据),数组的长度就是你这个数组能存放的最大的字节数
System.out.println();
System.out.println("=============解决乱码方案======================");
byte[] bytes=new byte[20];
// todo 难点!!!
// 在下方循环中,需要着重理解read(bytes) 本来我们read()是一个字节一个字节读取
// 在这里我传入数组,意味着不是一个一个读取,已经是一次性读取1024个字节而不是一次,一次的读取
// 而这里的num则是你每次读取的内容,
// 注意我这里没有用write.txt而是用他的副本write3.txt的原因是,
// 上方展示乱码的时候,write的流已经读取完了,再读直接就是读到-1,和我最初演示的io是一个流的形式同理
while((num=is3.read(bytes))!=-1){
System.out.println(num);
System.out.println(Arrays.toString(bytes));
System.out.println(new String(bytes,0,num));
}
// 第三种读取方式根据文件的自己大小来读取,好处不会创建过大的数租节省空间,缺点,long转int会造成精度丢失
InputStream is4=new FileInputStream("src/com/haogu/write4.txt");
File file=new File("src/com/haogu/write4.txt");
// 转换会造成精度的丢失
byte[] bytes2=new byte[(int) file.length()];
while((num=is4.read(bytes2))!=-1){
// 可以看到数组的内部没有多余的0
System.out.println(Arrays.toString(bytes2));
}
//
// 最后关闭流
is.close();
is2.close();
is3.close();
}
![](https://i-blog.csdnimg.cn/direct/0737fea0a80e4d9a93135bf8bad6af21.png)
字节输出流
注意文档被覆盖的情况我不在演示自己操作。
public static void main(String[] args) throws Exception {
OutputStream os=new FileOutputStream("src/com/haogu/Java02/write2.txt");
// 在文件中书写操作,这里用的文件和读取文件用的文件一样
// 注意 字节的范围是-128--127 所以传入的范围在这个范围内,大于这个返回会乱码
// todo 发现覆盖了原本的文档内容此时 同时字节流输入的参数要求是int 字符流是str
// 如果想要不覆盖可以再创建文件流对象的时候在后面的参数书写为true
OutputStream os2=new FileOutputStream("src/com/haogu/Java02/write2.txt",true);
os.write(123);
os2.write(64);
os2.write(62);
os2.write(63);
os2.write(127);
os2.write(128);
os2.write(-128);
os2.write(-129);
// 发现{os(输入就会覆盖原本文档的对象流)输入的{没有被覆盖,
// 而os2(不会覆盖原本文档的对象流)输入的内容内有覆盖原本的文档
//超过范围的部分乱码了
// 如果想要传入中文汉字,那么需要获取到汉字的字节格式例子如下
String str="测试传入中文汉字";
byte[] bytes= str.getBytes();
os2.write(bytes);
}
字符流
注意事项
1,在字符流读取的时候,他是按照字符来读取,即使你的文件里面有字节内容,依旧是可以读取的,会默认进行隐形转换,把字节转化为字符。
2,字符流使用read()读出来的编码依旧是unicode编码。(在我的案例里面,存放如char数组的过程中 会把unicode编码转化为字符,然后存入到你的字符数组内)
3,流的读取是依次向下的,如果你已经读取一个流的部分内容,但是未读取完毕,那么接下来的再次出现读取该流的内容的时候,会接着往下面继续读,无法返回已经读取过的位置
4,在没有设置文件流是添加的情况下,书写会覆盖掉原本的值
5,他的wirte()方法传入的是字符串,并且他写入的结果不是直接写入,而是先存入到磁盘缓冲区,在你关闭流之后,他才会存入到文件里面
代码如下
字符输入流
文档准备:
代码如下
// 说完了字节接下来来说字符 他们的区别在于 字节的父类是 Output和Input而 字符是Read 和Write
public static void main(String[] args) throws IOException {
Reader re=new FileReader("src/com/haogu/Java03/wirte1.txt");
Reader re2=new FileReader("src/com/haogu/Java03/wirte2.txt");
// 普通读取
//可以看到读出来的依旧是unicode编码
System.out.println( re.read());
System.out.println( re.read());
System.out.println( re.read());
System.out.println( re.read());
System.out.println( re.read());
System.out.println( re.read());
System.out.println( re.read());
System.out.println("=====================依靠循环来读取===================");
//这里不用wi的原因是因为wi已经读取了部分数据了,接下来只会从未读取的部分开始读取
// 此时代表以一个字符数组为单位进行读取
char[] chars=new char[20];
int num;
while((num=re2.read(chars))!=-1){
// num是每次读取到的字符的长度 因为是字符流单位是字符 一个字符三个字节,不常用四个字节 在utf-8编码格式下
// 中长度设置的是20,但是一共只有15个字符,所以num打印为15
System.out.println(num);
System.out.println(chars);
// 把读取到的集合转化为一个字符串
System.out.println(new String(chars,0,num));
}
字符输出流
随意准备一个又内容的文档:
代码如下:
public static void main(String[] args) throws IOException {
Writer wi=new FileWriter("src/com/haogu/Java04/wirte1.txt");
wi.write("第二次输入的数据,完成覆盖初始数据");
// todo 重点我们会发现,如果我们不去关闭这个流,那么数据不会被写入文件,会一直保存在缓冲区内部
// 所以在操作字符流的时候,最后书写完毕之后一定记得关闭流
wi.close();
// 在文件本来原有的内容上添加而不是去覆盖
Writer wi2=new FileWriter("src/com/haogu/Java04/wirte1.txt",true);
wi2.write("{中括号内是添加的内容}");
wi2.close();
}
运行后的结果变为