IO流的概述
IO:输入/输出(Input/Outout)
l流:是一种抽象感念,是对数据传输的总称。数据在设备间的传输称为流,流的本质是数据的传输。
IO流就是用来处理设备间的数据传输问题的。常见的应用有:文本复制,文件上传,文件下载…
分类:
按照数据的流向:
输入流:读取数据
输出流:写入数据
按照数据类型:(默认)
字节流(万能流)
输入字节流
输出字节流
字符流(在使用系统自带的文本文档能读懂的内容就可以使用)
输入字符流
输出字符流
字节流写数据:
InputStream:字节输入流的所有类的超类
OutputStream:字节输出流的所有类的超类
子类名的特点: 子类名都是以其父类名作为子类名的后缀。
/*
FileOutputStream:文件输出流,用于将指定的数据写入File
FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。
*/
import java.io.*;
public class TestDemo_01 {
public static void main(String[] args) throws IOException {
FileOutputStream fo = new FileOutputStream("D:\\JavaProject\\JavaSE\\javase.txt");
/* 这里做了三件事情
1.调用系统功能创建了文件。 javase.txt
2.创建了字节输出流对象。 fo
3.让字节输出流指向了创建好的文件。 fo → javase.txt
*/
fo.write(97);//小写a,这里写入的都是字符。
fo.close();//所有和IO有关的操作都要释放资源。
/*
close() 关闭此文件输出流并释放与此流相关的任何系统资源。
*/
}
步骤:
1.创建字节输出流对象{
①.调用系统功能创建了文件(javase.txt )
②创建了字节输出流对象。(fo)
③让字节输出流指向了创建好的文件。 ( fo → javase.txt)
}
2.调用字节流输出对象的写数据方法
3.释放资源(关闭此文件输出流并释放与此流相关的任何系统资源。)
字节流写数据的三种方法:
package IODemo;
/*
void write(byte[] b) 将 b.length字节从指定的字节数组写入此文件输出流。
void write(byte[] b, int off, int len) 将 len字节从指定的字节数组开始,从偏移量 off开始写入此文件输出流。
void write(int b) 将指定的字节写入此文件输出流。
*/
import java.io.*;
public class TestDemo_01 {
public static void main(String[] args) throws IOException {
FileOutputStream fo1 = new FileOutputStream("D:\\JavaProject\\JavaSE\\javase.txt");
//一次 写一个字节
fo1.write(89);
//一次写一个数组的字节
byte[] b = {97,98,99,100,101};
fo1.write(b);
//一次写一个数组指定的字节
fo1.write(b,1,4);
fo1.close();
//FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。
// append 添加 创建文件输出流以指定的名称写入文件。 如果第二个参数为true ,
// 则字节将写入文件的末尾而不是开头。 将创建一个新的FileDescriptor对象来表示此文件连接。
FileOutputStream fo2 = new FileOutputStream("D:\\JavaProject\\JavaSE\\javase.txt",true);
//byte[] getBytes() 使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中。
for (int a = 0 ; a < 6 ;a++){
fo2.write("efghi\r\n".getBytes());
}
/*
字节流的换行
windows: \r\n
linux: \n
mac: \r
*/
fo2.close();
}
}
字节流读数据:
/*
D:\JavaProject\text\复制.txt 文件中存有下列内容
Hello
Wolrd
两行字
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class InputStreamDemo {
public static void main(String[] args) throws IOException {
FileInputStream fi = new FileInputStream("D:\\JavaProject\\text\\复制.txt");
//一次读取一个数组的字节
byte[] by = new byte[1024];
int len=fi.read(by);
while (len!=-1){
System.out.println(new String(by,0,len));
}
// //第二次读取
// System.out.println(len); //len 是读取到的字节数,这里是5
// System.out.println(new String(by));// ello 因为已经在上边读取了一个字节,所以这里是从第二个开始的
// //4个字母是因为 o 后边有换行符 /r
// //第三次读取
// len = fi.read(by);
// System.out.println(len); //len 是读取到的字节数,这里是5
// System.out.println(new String(by));
// /*
// 5
//
// Wolr 5,这里空了一行,然后输出Wolr 因为windows中换行是/r/n上边读取了一个
// /r,还有一个/n这次的读取是从/n开始的,一共五个
//
//
// */
// //第四次读取
// len = fi.read(by);
// System.out.println(len); //len 是读取到的字节数,这里是3
// System.out.println(new String(by));
// /*
// d
// lr
// 这里读取的是从d开始然后是/r/n这里只有三个字节,所以读取数字是3,我们要读取五个,还空下两个,这两个是由上一次读
// 到的数组中的后两个组成的。
// */
//
// /*
// 这里应该这么写 System.out.println(new String(by,0,len));
// String(byte[] bytes, int offset, int length) 通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。
// byte数组中 从多少个元素开始 读取多少个
// */
//释放资源
fi.close();
}
}
复制文件
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo {
public static void main(String[] args) throws IOException {
FileInputStream fi = new FileInputStream("F:\\GM\\GM命令\\基础命令.txt");
FileOutputStream fo = new FileOutputStream("D:\\JavaProject\\text\\复制.txt");
int by;
while ((by=fi.read())!=-1){ // 只要读取的字节数量不是 -1,就一直读取。
fo.write(by); // 每读取by数量的字节,就写入by数量的字节
}
fo.close();
fi.close();
}
}
对比,下边的为什么会输出乱码
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo {
public static void main(String[] args) throws IOException {
FileInputStream fi = new FileInputStream("F:\\GM\\GM命令\\基础命令.txt");
FileOutputStream fo = new FileOutputStream("D:\\JavaProject\\text\\复制.txt");
while (fi.read()!=-1){ // 只要读取的字节数量不是 -1,就一直读取。
fo.write(fi.read()); // 每读取by数量的字节,就写入by数量的字节
}
fo.close();
fi.close();
}
}
一次读取一个数组的复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo {
public static void main(String[] args) throws IOException {
FileInputStream fi = new FileInputStream("F:\\GM\\GM命令\\基础命令.txt");
FileOutputStream fo = new FileOutputStream("D:\\JavaProject\\text\\复制.txt");
byte[] by = new byte[1024];
int len;
while ((len=fi.read(by))!=-1){ // 只要读取的字节数量不是 -1,就一直读取。
fo.write(by,0,len); // 每读取by数量的字节,就写入by数量的字节
}
fo.close();
fi.close();
}
}
字节缓冲流(提高读写效率)
BufferedOutputStream:
该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。
BufferedInputStream:
创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节。
构造方法:
BufferedInputStream(InputStream in)
创建一个 BufferedInputStream并保存其参数,输入流 in供以后使用。
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
字节缓冲流仅仅提供缓冲区域,而真正的读写数据还得靠基本的字节流对象进行操作。所以,这里的参数是对象,不是具体的文件或者字符串路径。
//BufferedInputStream源码解析
private static int DEFAULT_BUFFER_SIZE = 8192;
public BufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
//上边的构造方法调用了 下边的构造方法
public BufferedInputStream(InputStream in, int size) {
//将DEFAULT_BUFFER_SIZE 的值传给了size
}
super(in);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
//创建了一个自带的数组,大小是8192
}
读写代码:
import java.io.*;
public class BuffereDemo {
public static void main(String[] args) throws IOException {
// FileInputStream fi = new FileInputStream("F:\\GM\\GM命令\\基础命令.txt");
// FileOutputStream fo = new FileOutputStream("D:\\JavaProject\\text\\复制.txt");
// BufferedOutputStream bo = new BufferedOutputStream(fo);
// BufferedInputStream bi = new BufferedInputStream(fi);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\JavaProject\\text\\复制.txt"));
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\JavaProject\\text\\复制.txt"));
//写数据
//void write(byte[] b, int off, int len) 从偏移量 off开始的指定字节数组写入 len字节到缓冲输出流。
//void write(int b) 将指定的字节写入缓冲的输出流。
//byte[] getBytes() 使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中。
//这里没有write(byte[] byte)的方法...但是它的父类中有,所以可以用。
bos.write("Hello\r\n".getBytes());
bos.write("World\r\n".getBytes());
bos.close();//先释放才能在下边读取代码。否则是没有写入么?
//读数据 和 FileOutputStream 一样
int by;
while ((by = bis.read())!=-1){ //将读取字节的 值 给by
System.out.print((char)by);//将by转换为char值并输出
}
System.out.println("***********");//因为bis.read()=-1了,所以下边的代码不会执行了
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys))!=-1){
System.out.println(new String(bys,0,len));
}
bis.close();
// byte[] by = new byte[1024];
// int len;
// while ((len = bi.read(by))!= -1){
// bo.write(by,0,len);
// }
}
}