IO流
一、概述
在电脑程序中,对于数据的传输,可以看成数据的流动。根据流动的方向分为输入(input)和输出(output)流。
比如:通过键盘把数据写入(input)到文件中,又通过显示器将数据输出(output)显示出来。
Java中的IO就是对数据进行输入、输出操作。数据的I/O操作依靠流来实现,根据数据单位不同又将流分为字节流和字符流。
注:一切文件的数据(文本、图片、视频)在存储时,都是以二进制的的形式进行和保存,都是以字节为单位。因此通过字节流可以操作任意的数据。
Java中对于流的操作类:
输出流 | 输入流 | |
---|---|---|
字符流 | Writer | Reader |
字节流 | OutputStream | InputStream |
二、字节流
一、输出流-OutputStream
是所有字节输出流的超类(顶级父类)。
注:是一个抽象类,不能创建对象。
1、该类中声明的方法:
**1.public void close();**关闭输出流并释放资源。
**2.public void flush();**刷新输出流并强制任何正在缓冲的字节被写出。
**3.public void write(byte[] b);**将制定的字节数组的内容写入到输出流。
**4.public void write(byte[],int off,int len);**将指定字节数组从off位置开始偏移len长度的内容写入到输出流。
2、子类
子类 | 描述 |
---|---|
FileOutputStream | 文件字节输出流 |
PipedOutputStream | 管道字节输出流 |
ObjectOutputStream | 对象字节输出流 |
FilterOutputStrem | 过滤器字节输出流 |
ByteArrayOutputStream | 字节数组输出流 |
3、子类–FileOutPutStream
用于将数据写到文件中。
构造方法
**1.FileOutputStream(String name);**通过指定文件的路径名来创建文件输出流对象。
**2.FileOutputStream(File file);**通过一个File对象来创建文件输出流。
写入数据的的流程:
java程序—>JVM---->OS(操作系统)—>OS调用写数据的方法---->写入文件中
使用步骤:
1.创建OutputStream对象,传递文件路径。
2.调用write方法,把数据写入到文件中。
3.调用close方法释放资源。
代码示例:
public static void test1() throws IOException{
//1.根据指定文件路径创建文件输出流对象
FileOutputStream out = new FileOutputStream("E://test.txt");
//2.向文件中输出数据
out.write(97);
//3.关闭资源
out.close();
}
转换流程:
写入多个数据:
比如,在文件中写入一个数据
代码示例:
public static void test2() throws IOException{
//1.根据指定文件路径创建文件输出流对象
FileOutputStream out = new FileOutputStream("E://test.txt");
//声明一个byte类型数组
byte[] b={50,50,48,53,48,49};
//2.调用write重载的方法write(byte[] b);
out.write(b);
//或者调用write重载方法write(byte[] b,int off,int len )
//out.write(b,0,6);
//3.关闭资源
out.close();
}
将一个字符串写入文件中
代码示例:
public static void test3() throws IOException{
FileOutputStream out = new FileOutputStream("E://test.txt");
String str="你好";
//使用getBytes()方法将字符串转换成字节数组
byte[] bytes = str.getBytes();
//调用write(byte[] b)方法将数据写入
out.write(bytes);
//关闭资源
out.close();
}
注:一般来说,一个中文字符占两个字节。但在UTF-8编码中,一个中文字符占三个字节。
续写和换行
每创建一次FileOutputStrem对象对文件进行数据写入时 ,会将文件中的内容覆盖掉。
解决:
使用以下两个构造方法创建对象:
1.FileOutputStrem(String name,boolean append);
2.FileOutputStrem(File file,boolean append);
注:append参数为true:每次创建输出流对象时,不会覆盖掉指定路径的文件。则在文件内容后追加写入数据,反之就会被覆盖。
代码示例:
public static void test4() throws IOException{
FileOutputStream out = new FileOutputStream("E://hqyj//teach//test.txt",true);
for(int i=1;i<=10;i++){
out.write("你好".getBytes());
//每写入一次数据,换行
out.write("\n".getBytes());
}
}
二、输入流-InputStream
是所有字节输入流的超类(顶级父类)。
注:是一个抽象类,不能创建对象。
1、声明的方法
**1.int read();**读取输入流中字节数据,转换成整数。每读一次,自动获取下一个数据。数据读完后返回-1;
**2.int read(byte[] b);**将读取的数据存储在一个字节数组中。
**3.void close();**关闭数据流。
2、子类
子类 | 描述 |
---|---|
FileInputStream | 文件输入流 |
PipedInputStream | 管道输入流 |
ObjectInputStream | 对象输入流 |
FilterInputStream | 过滤器输入流 |
SequenceInputStream | 顺序输入流 |
ByteArrayInputStream | 字节数组输入流 |
StringBufferInputStream | 缓冲字符串输入流 |
3、子类–FileInputStream
将磁盘中文件的数据读取到程序中使用
构造方法
**1.public FileInputStream(String name);**通过指定路径创建文件输入流对象。
**2.public FileInputStream(File file);**通过指定File对象来创建输入流对象。
读取数据流程
java程序—>JVM—>OS—>OS调用读取数据的方法—>读取文件
使用步骤
1.创建FileInputStream对象,传递指定文件的路径参数。
2.调用FileInputSream中的read方法读取文件
3.释放资源
代码示例:
public static void test() throws IOException {
//1.创建FileInputStream对象
FileInputStream input=new FileInputStream("E://test.txt");
//2.调用read();方法 读取数据,每调用一次,自动指向下一个数据。数据读完后,返回-1;
int data=0;
data=input.read();//a
System.out.println(data);//97
data=input.read();//b
System.out.println(data);//98
data=input.read();//c
System.out.println(data);//99
data=input.read();//d
System.out.println(data);//100
data=input.read();//数据读完了
System.out.println(data);//-1
//3.关闭资源
input.close();
}
代码优化:
public static void test() throws IOException {
//1.创建FileInputStream对象
FileInputStream input=new FileInputStream("E://test.txt");
//2.调用read();方法 读取数据,每调用一次,自动指向下一个数据。数据读完后,返回-1;
//声明一个变量,存储每一次读取到的数据
int data;
//判断data是否为-1,不为-1,继续读取,直到返回的是-1 终止循环。
while((data=input.read())!=-1){
System.out.println(data);
}
//3.关闭资源
input.close();
}
一次性读取多个数据
使用public int read(byte[] b);方法
参数:用来存储每次读到的数据
返回值:表示读取到了几个数据,返回-1说明数据读取完毕。
代码示例:
public static void test2() throws IOException{
FileInputStream input=new FileInputStream("E://test.txt");
//声明一个字节数组来存储获取到的数据,长度为2 表示每次读取两个数据存储在数组中
byte[] b=new byte[2];
//声明一个变量表示每次获取的数据个数
int len;
//循环读取数据,存储在数组里面
while((len=input.read(b))!=-1){
//将字节数组转换为字符串显示 使用String str=new String(byte[] b)构造方法初始化字符串
String str=new String(b);
System.out.println(str);
}
//关闭资源
input.close();
}
//该代码执行后,出现了获取错误的数据的情况
注: 一次性把数组长度给够,一般初始化为1024的整数倍,避免出现读取到不正确的数据。
代码优化:
public static void test2() throws IOException{
FileInputStream input=new FileInputStream("E://test.txt");
//声明一个字节数组来存储获取到的数据,长度为2 表示每次读取两个数据存储在数组中
byte[] b=new byte[1024];
//声明一个变量表示每次获取的数据个数
int len;
String str="";
//循环读取数据,存储在数组里面
while((len=input.read(b))!=-1){
//使用String str=new String(byte[] b,int offset,int length)。
//offset:从指定下标开始,length:偏移量
//每次只转len有效长度的数据为字符串,然后进行拼接,这样就避免把数组空数据也转换成字符串
str+=new String(b,0,len);
}
System.out.println(str);
//关闭资源
input.close();
}
练习:将文件从一个磁盘文件夹复制到另一个磁盘文件夹中
思路:先从一个地方输入到程序,再从程序输出到另一个地方
1.通过文件路径创建文件的文件输入流对象。
2.创建文件的文件输出流对象,并且指定文件写出的路径
3.通过输入流read方法在程序中获取到文件字节数据。
4.通过输出流write方法输出字节数据。
代码示例:
public static void test3() throws IOException{
//1.通过文件路径创建文件的文件输入流对象。
FileInputStream input=new FileInputStream("E:\\test\\原图.png");
//2.创建文件的文件输出流对象,并且指定文件写出的路径
FileOutputStream out=new FileOutputStream("E:\\复制的图片.png");
//用于存储文件字节数据的数组
byte[] b=new byte[1024];
//表示每次获取到文件的有效数据个数
int len;
//3.通过输入流read方法在程序中获取到文件字节数据。
while((len=input.read(b))!=-1){
// 4.通过输出流write方法输出字节数据
out.write(b,0,len);
}
//关闭资源
input.close();
out.close();
}
三、字符流
主要用于处理文本文件。由于中文字符可能会占用多个字节存储,因此使用字节流获取数据时,可能会导致字符显示错误。
GBK编码:中文占2个字节
UTF-8编码中:中文占3个字节
一、输入流-Reader
是所有字符输入流的超类,用于读取字符信息。
注:是一个抽象类,无法创建对象。
1、声明的方法:
**1.public void close();**关闭流,释放资源
**2.public int read();**读取一个字符
**3.public int read(char[] cbuf);**读取一些字符,存储在字符数组中
2、子类–FileReader类
文件字符输入流,用于读取字符文件的类,创建对象时使用的是系统默认的字符编码(GBK)
构造方法:
**1.public FileReader(String fileName);**通过指定文件路径创建对象。
**2.public FileReader(File file);**通过file对象来创建对象
使用步骤:
1.创建FileReader对象,并指定文件的路径。
2.使用read方法,读取单个字符并返回。
3.释放资源
代码示例:
public static void test() throws IOException {
//1.创建指定路径文件的字符文件输入流对象
FileReader reader = new FileReader("E://test.txt");
//声明data变量表示每次获取到的字符数据
int data;
//2.使用read()方法循环获取单个数据,如果返回值为-1,表示获取结束
while((data=reader.read())!=-1)
System.out.println((char)data);
//3.关闭流
reader.close();
}
public static void test2()throws IOException{
//1.创建指定路径文件的字符文件输入流对象
FileReader reader = new FileReader("E://test.txt");
//声明一个字符数组来存储获取到的多个字符
char[] c=new char[1024];
//声明一个变量来表示每次获取的有效数据个数
int len;
String str="";
//2.使用read(char[] cbuf)方法来循环获取多个字符
while((len=reader.read(c))!=-1){
//将每次获取到有效数据字符数组,转换成字符串。使用new String(char[] c,int offset,int length)方法初始化字符串
str+=new String(c,0,len);
}
System.out.println(str);
//3.关闭流
reader.close();
}
二、输出流-Writer
是所有字符输出流的超类(顶级父类),输出指定的字符到指定地方。
注意:是一个抽象类,无法创建对象。
一、声明的方法
**1.void write(int c);**写入单个字符。
**2.void write(char[] cubf);**写入字符数组。
**3.void write(char[] cubf,int off,int len);**写入字符数组的一部分,从指定下标off开始,偏移len长度个字符。
**4.void write(String str);**写入指定字符串。
**4.void write(String str,int off,int length);**写入指定部分字符串。
**5.void flush();**刷新缓存
**6.void close();**关闭流
二、子类-FileWriter类
继承关系:FileWriter extends OutputStreamWriter extend Writer
用于向指定路径的文件中写入字符
构造方法
**1.public FileWriter(File file);**使用指定的file对象创建字符输出流对象。
**2.public FileWriter(String filenName);**使用指定文件路径创建字符输出流对象。
使用步骤
1.创建FileWriter对象,指定字符要写入的目的地。
2.使用write();方法,将字符写入到内存缓冲区中。
3.使用flush();方法,将内存缓冲区中的字符,刷新到文件中。(字符转换为字节的过程)
4.使用close();方法,释放资源。同时也在执行刷新缓存的操作。
代码示例:
写入一个字符
public static void test() throws IOException {
//1.创建FileWriter对象,指定字符要写入的目的地。
FileWriter writer = new FileWriter("E:\\test2.txt");
//2.使用write();方法,将字符写入到内存缓冲区中。
writer.write(65);
//3.使用flush();方法,将内存缓冲区中的字符,刷新到文件中。
writer.flush();
//4.关闭流,同时刷新缓存
writer.close();
}
注:执行flush方法过后,流还可以继续使用。执行了close方法过后,流不能再使用。
写入多个字符
代码示例:
public static void test2()throws IOException{
//创建FileWriter对象,指定字符要写入的目的地。
FileWriter writer = new FileWriter("E:\\test2.txt");
//指定要写入的字符数组
char[] c={'你','好','世','界'};
//调用write(char[] cubf)方法
writer.write(c);
//调用 write(char[] cubf,int off,int len)方法
writer.write(c,2,2);
//调用write(String str)方法
writer.write("萨瓦迪卡");
//调用write(String str,int off,int length)方法;
writer.write("嘿嘿嘿",0,2);
//刷新
writer.flush();
//关闭
writer.close();
}
续写和换行
使用下列构造器:指定oppend的值为true即可
1.FileWriter(String fileName,boolean oppend);
2.FileWriter(File file,boolean oppend);
注意:字符流,只能操作文本文件,不能操作图片,视频等非文本文件。 当我们单纯读或者写文本文件 时 使用字符流 其他情况使用字节流。
续写和换行
使用下列构造器:指定oppend的值为true即可
1.FileWriter(String fileName,boolean oppend);
2.FileWriter(File file,boolean oppend);
注意:字符流,只能操作文本文件,不能操作图片,视频等非文本文件。 当我们单纯读或者写文本文件 时 使用字符流 其他情况使用字节流。