- java io可以上我们用边追的读写操作来完成对不同设备的读写数据工作。
- java将IO按照方向划分为输入流和输出流,参照点是我们写的程序。
- 输入:用来读取数据的,是从外界到程序的方向,用于获取数据。
- 输出:用来写出数据的,是从程序到外界的方向,用于发送数据。
java将IO比喻为流。就像生活中的电流、水流一样,它是以同一个方向顺序移动的过程。只不过这里的流动是字节(2进制数据)。所以再IO中有输入流和输出流之分。我们理解他们是连接程序与另一端的“管道”,用于获取或发送数据到另一端。
java定义了两个超类
- Java.io.InputStream.所有字节输入流的超类,其中第赢了读取数据的方法。依次将看来不管读取的是什么设备(连接该设备的流)都有这些读取方法,因此我们可以使用相同的方法读取不同设备中的数据
- Java.io.OutputStream.所有字节输出流的超类,其中定义了写出数据的方法。
java江流分为两类:节点流和处理流
- 节点流:也称之为低级流,节点流的一端是明确的,是实际读写数据的流,读写一定是建立在节点流的基础上进行的
- 处理流:也称之为高级流。处理流不能独立存在,必须连接在其他流上,目的是当数据流经当前处理流时对数据进行加工处理来简化我们对数据的操作。
实际应用中,我们可以通过串联一组高级流到某个低级流上以流水线式的加工处理对某设备的数据进行读写,这个过程也称之为流的连接,这也是IO的精髓所在。
文件流
文件流是一对低级流,是节点流。用于读写文件数据的流。用于连接程序与文件(硬盘)的管道。负责读写文件数据
文件输出流 java.io.FileOutputStream
package day01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FOSDemo {
public static void main(String[] args) throws IOException {
//需求:向当前目录中的文件fos.dat中写入数据
FileOutputStream fos=new FileOutputStream("./fos.dat");
/* void write(int b)
写出1个字节,将给定参数int值对应的2进制的“低八位”写出
文件输出流继承了outputstream后,重写了该方法,作用是将该字节写入到文件中
*/
fos.write(1);
fos.write(2);
System.out.println("写出完毕");
fos.close();
}
}
fos.dat中的数据由于是二进制格式,我们通常打开文件是以文本格式打开的,所以打开后是乱码
文件输入流 java.io.FileInputStream
package day01;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FISDemo {
public static void main(String[] args) throws IOException {
//将文件fos.dat中的数据读取出来
FileInputStream fis=new FileInputStream("fos.dat");
/*
java.io.inputstream(所有字节输入流的超类)定义这读取字节的相关方法
int read()
读取1个字节并以int型整数返回读取到的字节内容,返回的int值中对应的2进制的“低八位”就是读取到的数据。
如果返回的int值为整数-1(这是一个特殊值,32为2进制全部是1)表达的是读取到末尾
int read(byte[] date) 块写
*/
int d=fis.read();
System.out.println(d);
d= fis.read();
System.out.println(d);
fis.close();
}
}
结果为
1
2
文件复制
当学习了文件输入流和文件输出流后,我们通过这一对文件流实现文件的复制。读一个写一个。
package day01;
import java.io.*;
public class CopyDemo {
public static void main(String[] args) throws IOException {
//复制image.jpg文件
FileInputStream fis=new FileInputStream("image.jpg");
FileOutputStream fos=new FileOutputStream("image_cp.jpg");
File file=new File("image.jpg");
int b;
long start=System.currentTimeMillis();
while ((b=fis.read())!=-1){
fos.write(b);
}
long end=System.currentTimeMillis();
System.out.println("复制完毕,耗时"+(end-start)+"ms");
}
}
结果为
复制完毕,耗时4976ms
但实际上image.jpg文件并不大,只有1.51MB.使用 int read()方法进行文件复制过于缓慢,需要使用块读写文件操作
块读写的文件复制操作
快读操作 int read(byte[ ] date) 一次性从文件中读写给定的字节数组总长度的字节量,并存入到该数组中。返回值为实际读取到的字节两。若返回值为-1则表示读取到了文件末尾。
块写操作 void write(byte[ ] date) 以此向将给定的字节数组所有字节写入到文件中
void write(byte[ ] date,int offset,int len) 一次性将给定字节数组从下表offset处开始的连续len个字节写入到文件中。
package day01;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo2 {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("image.jpg");
FileOutputStream fos=new FileOutputStream("image_cp.jpg",true);
byte[]date=new byte[1024*10];
int len;
long start=System.currentTimeMillis();
while ((len=fis.read(date))!=-1){
fos.write(date,0,len);
}
long end=System.currentTimeMillis();
System.out.println("复制完毕,耗时"+(end-start)+"ms");
}
}
运行结果为
复制完毕,耗时0ms
块读写(一次性读写一组字节数组)相比较原来(一次性一个字节)的读写要快上很多。
写文本数据
String提供方法byte[ ] getBytes(String charsetName)将当前字符串转换为一组字节
参数为字符集的名字,常用的是UTF-8.其中中文文字3个字节表示个,英文1字节表示1个
package day01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class WriteStringDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos=new FileOutputStream("fos.txt",true);
String line="这一次世界杯,我赌伊朗出线";
byte[] data=line.getBytes(StandardCharsets.UTF_8);
fos.write(data);
line="3000万,我买伊朗出线";
data=line.getBytes(StandardCharsets.UTF_8);
fos.write(data);
line="有种天台见";
data=line.getBytes(StandardCharsets.UTF_8);
fos.write(data);
fos.close();
}
}
fos.txt中数据为
这一次世界杯,我赌伊朗出线3000万,我买伊朗出线有种天台见
文件输出流---追加模式
重载的构造方法可以将文件输出流创建为追加模式
-
FileOutputStream(String path,boolean append)
-
FileOutputStream(File file,boolean append)
当第二个参数传入true时,文件为追加模式,即:指定文件若存在,则原有数据保留,新写入数据会被顺序追加到文件中
文件流有两种创建方式:
覆盖模式:所谓覆盖模式,文件流在创建时若发现该文件已存在,则会将文件原内容全部删除,然后再陆续将该流写出的内容保存在文件中
构造方法
- FileOutputStream(String path)
- FileOutputStream(File file)
追加模式:文件流在创建时若发现该文件已存在,则原内容保留。通过当前六陆续写的内容都会被追加到文件末尾
读取文本数据
package day01;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class ReadStringDeMO {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("fos.txt");
byte[] date=new byte[1024];
int len;
len=fis.read(date);
System.out.println("实际读取的字节长度"+len);
String line= new String(date,0,len, StandardCharsets.UTF_8);
System.out.println(line);
fis.close();
}
}
运行结果为
实际读取的字节长度164
这一次世界杯,我赌伊朗出线3000万,我买伊朗出线有种天台见这一次世界杯,我赌伊朗出线3000万,我买伊朗出线有种天台见
UTF-8字符集中文字3字节表示1个,英文、符号、数字1字节表示1个