1.认识IO
IO,即in和out,也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为 输入input和 输出 output ,即流向内存是输入流,流出内存的输出流。
lava中I/O操作主要是指使用 iava.io 包下的内容,进行输入、输出操作,输入也叫做读取数据,输出也叫做作写出数据。
输入:内容进入到系统内存中;
输出:内容从内存中到别的地方;
流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。
1.按照流的方向进行分类:以内存作为参照物,往内存中去,叫做输入。或者叫做读(Read)。从内存中出来,叫做输出。或者叫做写(Write)。
2.按照读取数据方式不同进行分类:有的流是按照字节的方式读取数据,一次读取1个字节byte等同于一次读取8个二进制位。这种流是万能的,什么类型的文件都可以读取。包括文本文件、图片、声音文件、视频文件等等…;有的流是按照字符的方式读取数据,一次读取一个字符,这种流是为了方便读取普通文本文件存在的。这种流不能读取:图片、声音、视频等文件,只能读取纯文本文件,连word文件都无法读取。
字节流 | 字符流 | |
输入流 | java.io.InputStream 字节输入流 | java.io.Reader 字符输入流 |
输出流 | java.io.OutputStream 字节输出流 | java.io.Writer 字符输出流 |
一、字节流
FileOutputStream类
构造方法摘要 | |
---|---|
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 | |
FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 | |
FileOutputStream(FileDescriptor fdObj) 创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。 | |
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。 | |
FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。 |
方法摘要 | |
---|---|
void | write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。 |
void | write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 |
void | write(int b) 将指定字节写入此文件输出流。 |
OutputStream输出流
OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。
方法摘要 | |
---|---|
void | close() 关闭此输出流并释放与此流有关的所有系统资源。 |
void | flush() 刷新此输出流并强制写出所有缓冲的输出字节。 |
void | write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。 |
void | write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 |
abstract void | write(int b) 将指定的字节写入此输出流。 |
public class OutPutTest01 {
public static void main(String[] args) throws IOException {
File f1 = new File("d:/aa");
File f2 = new File(f1,"a.txt");
f1.mkdirs();
f2.createNewFile();
//使用OutPutStream输出流完成对文件的写入操作 内存输出到文件
OutputStream out = new FileOutputStream(f2);//定义一个输出流,输出到f2文件中
//out.write(97);//按照AscII解析数字写入文件中 写入的是97对应的a
byte[] bytes = {97,98,99,100,101,102,103};
//out.write(bytes);//按照AscII解析数组写入文件 写入的:abcdefg
out.write(bytes,2,3);//从数组指定索引位置2写入3个元素
}
}
public class OutPutTest02 {
public static void main(String[] args) throws IOException {
File f1 = new File("d:/来自一个爱你的表白.txt");//
f1.createNewFile();
OutputStream out = new FileOutputStream(f1);
Scanner sc = new Scanner(System.in);
System.out.println("请输入:");
String msg = sc.next();
//定义一个String,把字符串的内容写入到电脑的磁盘中
//String msg ="爱你在每一个不知道的瞬间!";
byte[] bytes = msg.getBytes();//获取字符串对应解析后的byte数组
out.write(bytes);//把byte数组写入文件,相当于把字符串写入文件中
}
}
InputStream输入流
inputstream类和outputstream类都为抽象类,不能创建对象,可以通过子类来实例化。
InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.
Inputstream类中的常用方法:
FileInputStream类
构造方法摘要 | |
---|---|
FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream ,该文件通过文件系统中的 File 对象 file 指定。 | |
FileInputStream(FileDescriptor fdObj) 通过使用文件描述符 fdObj 创建一个 FileInputStream ,该文件描述符表示到文件系统中某个实际文件的现有连接。 | |
FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream ,该文件通过文件系统中的路径名 name 指定。 |
常用方法
方法摘要 | |
---|---|
int | available() 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。 |
void | close() 关闭此输入流并释放与该流关联的所有系统资源。 |
void | mark(int readlimit) 在此输入流中标记当前的位置。 |
boolean | markSupported() 测试此输入流是否支持 mark 和 reset 方法。 |
abstract int | read() 从输入流中读取数据的下一个字节。 |
int | read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 |
int | read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。 |
void | reset() 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。 |
long | skip(long n) 跳过和丢弃此输入流中数据的 n 个字节。 |
文件的读取和写入操作
public class InPutTest03 {
public static void main(String[] args) throws IOException {
//输出流:内存的内容输出到文件(写操作) 输入流:文件内容输入到内存中(读操作)
File f1 = new File("d:/a.txt");
//创建一个输入流,读取f1这个文件
InputStream input = new FileInputStream(f1);
//read()读取文件的一个字符,然后把字符转换为对应的数字返回;若读取到文件的末尾,返回-1
// int n;
// while((n=input.read())!=-1){
// System.out.println((char)n);
// }
//int read(byte[] b)使用缓冲区读取:一次读取数组长度个元素,读取到的字符转换成数字存入数组中,返回的是实际读取的字节数
byte[] b = new byte[10];//定义byte数组,指定长度,作为每次读取的缓冲区
int n = n=input.read(b);//按照数组长度去读取,读取的内容存在数组中,返回的是实际读取的字节数
//System.out.println(n);
String s = new String(b,0,n);//对数组从0索引开始 截取实际读取的长度产生字符串
System.out.println(s);
byte[] b1 = new byte[10];
int n1 = n=input.read(b1);//要求读10个,实际只有5个 b数组中有5个是读取到的数据
//System.out.println(n1);
String s1 = new String(b1,0,n1);
System.out.println(s1);
}
}
public class InPutTest04 {
public static void main(String[] args) throws IOException {
File f1 = new File("D:/a.txt");
//创建一个输入流,读取f1这个文件
InputStream input = new FileInputStream(f1);
//使用read()循环读取文件内容
// int n;
// while((n=in.read())!=-1){
// out.write(n);
// }
//使用read(byte[] b)缓冲区循环读取内容
int n;
byte[] b = new byte[10];
while((n=input.read(b))!=-1){
//把读取到的byte数组转换成字符串
String s = new String(b,0,n);//从0开始,截取有效读取的字节数你,生成字符串
System.out.print(s);
}
}
}
综合案例:文件的复制
public class CopyFileTest05 {
public static void main(String[] args) throws IOException {
//文件复制
//1.定义源文件和目的文件的文件对象
File f1 = new File("D:/a.txt");
File newFile = new File("D:/aa/copy.txt");
//2.创建目的文件
newFile.createNewFile();
//3.定义输入流:使用输入流读取内容 使用输出流写入内容
InputStream in = new FileInputStream(f1);
OutputStream out = new FileOutputStream(newFile);
//4.循环读取文件内容,同时写入指定的文件中
// int n;
// while((n=in.read())!=-1){
// out.write(n);
// }
//实际工作中推荐写法
// byte[] buffer = new byte[10];
// int n;
// while((n=in.read(buffer))!=-1){
// //把buffer数组从0开始,截取读取到有效字节数n,写入到目的文件中
// out.write(buffer,0,n);
// }
//练习时容易理解的方式
byte[] buffer = new byte[10];
int n=0;
while(true){
//读取文件,内容放入buffer数组中,返回的是实际读取的字节数
n =in.read(buffer);
if(n!=-1){
//把buffer数组从0开始,截取读取到有效字节数n,写入到目的文件中
out.write(buffer,0,n);
}else{
break;
}
}
//资源关闭
out.close();
in.close();
}
}