流按流向分为两种:输入流,输出流。
文件 输入流 输出流 文件
内存 -------------> Java程序 ------------------> 内存
键盘 控制台
| |
数据源 数据目的地
流按操作最小数据单元类型分为两种:
字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
字符流 : 字符流只能操作纯字符数据,比较方便
IO流常用父类
字节流的抽象父类:
InputStream
OutputStream
字符流的抽象父类:
Reader
Writer
字节流:
InputStream以字节为单位的输入流,最主要做read()读操作
OutputStream以字节为单位的输出流,最主要做write()写操作
1、对文件进行操作
FileInputStream和FileOutputStream
read()一次读取一个字节,返回值是int,不是byte,只用低8位
write(int)一次 写出一个字节,虽然写的是int,但到文件中的是byte,会自动去除前24位
把一个源文件拷到另一个文件,FileOutputStream如果文件不存在,新建空文件;如果文件已经存在,清空其内容;
如果想向文件追加内容,将构造器第二个参数传true
字节流一次读写一个字节代码如下:
import java.io.*;
public class Copy1 {
public static void test1(String in,String out) {
FileInputStream fis = null;
FileOutputStream fos = null;
int data;
try {
//1.创建输入/输出流对象
fis = new FileInputStream(in);
fos = new FileOutputStream(out);
//改为追加
//fos = new FileOutputStream(out,true);
//2.读/写操作
while((data = fis.read()) != -1) {//一次读一个字节,-1是末尾
fos.write(data);
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}catch(IOException e2) {
e2.printStackTrace();
}finally {//3.关闭资源
try {
fis.close();
fos.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//if(args.length !=2 ) {
// System.err.println("Please input two file path!");
// System.exit(1);
//}
//args[0]:源文件,args[1]:目标文件
test1("a.txt","b.txt");
}
}
字节流一次读写一个数组代码如下:
import java.io.*;
public class Copy1 {
public static void test2(String in,String out) {
FileInputStream fis = null;
FileOutputStream fos = null;
byte[] array;
int len;
try {
//1.创建输入/输出流对象
fis = new FileInputStream(in);
fos = new FileOutputStream(out);
//2.读/写操作
len = fis.available();//返回可读字节数
array = new byte[len];
fis.read(array);
fos.write(array);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}catch(IOException e2) {
e2.printStackTrace();
}finally {//3.关闭资源
try {
fis.close();
fos.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
test2("a.txt","b.txt");
}
}
如果源文件很大,防止溢出,一次读取指定字节
import java.io.*;
public class Copy1 {
public static void test3(String in,String out) {
FileInputStream fis = null;
FileOutputStream fos = null;
//每次最多读1024字节
byte[] array = new byte[1024];
int len;
try {
//1.创建输入/输出流对象
fis = new FileInputStream(in);
fos = new FileOutputStream(out);
//2.读/写操作
while((fis.read(array)) != -1){//可能读不够1024字节,返回实际读到的字节数
fos.write(array,0,array.length);
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}catch(IOException e2) {
e2.printStackTrace();
}finally {//3.关闭资源
try {
fis.close();
fos.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
test3("a.txt","b.txt");
}
}
FilterInputStream和FilterOutStream
Filter相关的流,是辅助流,需要依赖其它流,起到功能增强的作用,依赖的流以参数形式传进去
BufferedInputStream和BufferedOutputStream
BufferedInputStream调用read()操作并不是一次读一个字节,一般是1024*8个字节,放到缓冲区,下次再读的时候,不用从文件中去读,而是从缓冲区中读,减少操作文件的次数,提高了效率,write()也不是直接写到文件中,而是把一个字节先写到缓冲区中。
缓冲区的东西什么时候到文件中去呢?1、调用flush()刷新;2、缓冲区满了;3、调用close()关闭输出流
import java.io.*;
public class Copy2 {
public static void test1(String in,String out) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
byte[] array = new byte[1024];
int len;
try {
bis = new BufferedInputStream(new FileInputStream(in));
bos = new BufferedOutputStream(new FileOutputStream(out,true));
while((len = bis.read(array)) != -1) {
//写到Buffer的缓冲区中了
bos.write(array,0,len);
bos.write("\n".getBytes());//换行
}
//bos.flush();
}catch(IOException e) {
e.printStackTrace();
}finally {
try {
if(bis != null)
bis.close();
if(bos != null)
bos.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
test1("a.txt","b.txt");
}
}
DataInputStream和DataOutputStream
可以直接对java中的基本数据类型进行读、写操作
import java.io.*;
public class DataStreamTest {
/*
* 将整形数写到文件
*/
public static void test1(String path) {
int num = 100;
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream(path));
dos.writeInt(num);
}catch(IOException e) {
e.printStackTrace();
}finally {
try {
if(dos != null)
dos.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
/*
* 从文件读出整形数
*/
public static void test2(String path) {
DataInputStream dis = null;
try {
dis = new DataInputStream(new FileInputStream(path));
System.out.println("num: "+dis.readInt());
}catch(IOException e) {
e.printStackTrace();
}finally {
try {
if(dis != null)
dis.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
test1(args[0]);
test2(args[0]);
}
}
PipedInputStream和PipedOutputStream
PipedOutputStream和PipedInputStream分别是管道输出流和管道输入流。
它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedOutputStream和PipedInputStream配套使用。
使用管道通信时,大致的流程是:我们在线程A中向PipedOutputStream中写入数据,这些数据会自动的发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲中;此时,线程B通过读取PipedInputStream中的数据。就可以实现,线程A和线程B的通信。
import java.io.*;
class Sender extends Thread{
private PipedOutputStream pos;
public Sender(PipedOutputStream pos) {
this.pos = pos;
}
public void run() {
int num = 100;
DataOutputStream dos = null;
try {
dos = new DataOutputStream(pos);
dos.writeInt(num);
}catch(IOException e) {
e.printStackTrace();
}
}
}
class Fetcher extends Thread{
private PipedInputStream pis;
public Fetcher(PipedInputStream pis) {
this.pis = pis;
}
public void run() {
DataInputStream dis =null;
try {
dis = new DataInputStream(pis);
System.out.println("num: "+dis.readInt());
}catch(IOException e) {
e.printStackTrace();
}
}
}
public class PipedStreamTest {
public static void main(String[] args) {
PipedOutputStream pos = null;
PipedInputStream pis = null;
Thread t1,t2;
try {
pos = new PipedOutputStream();
pis = new PipedInputStream(pos);
t1 = new Sender(pos);
t2 = new Fetcher(pis);
t1.start();
t2.start();
t1.join();
t2.join();
}catch(IOException e1) {
e1.printStackTrace();
}catch(InterruptedException e2) {
e2.printStackTrace();
}finally {
try {
if(pis != null) {
pis.close();
}
if(pos != null) {
pos.close();
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
ObjectInputStream和ObjectOutputStream:可以读取、写出对象
https://blog.csdn.net/fzq13994952987/article/details/102511338
字符流:
字符流以字符为单位进行数据的读取和写入,底层依然使用的是字节流,要先把字节流转换为字符流
需要使用InputStreamReader和OutputStreamWriter:按照指定的字符编码进行读写操作
字节流、字符流转换的桥梁
import java.io.*;
public class ReaderWriterTest {
public static void main(String[] args) {
InputStreamReader isr = null;
OutputStreamWriter osw = null;
int data;
try {
//字节流转换为字符流
isr = new InputStreamReader(new FileInputStream(args[0]),"GBK");
osw = new OutputStreamWriter(new FileOutputStream(args[1]),"UTF8");
while((data = isr.read()) != -1) {
osw.write(data);
}
}catch(IOException e) {
e.printStackTrace();
}finally {
try {
if(isr != null)
isr.close();
if(osw != null)
osw.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
BufferedReader和BufferedWriter:在字符流的基础上添加了缓冲区,提高了读写的效率
BufferedReader里有一个很重要的方法readLine(),一次可以读一行
import java.io.*;
public class BufferedReaderWriterTest {
/*
* 将字符串写入文件,让程序员可以直接读懂
*/
public static void test1(String path) {
BufferedWriter bw = null;
String info = "Hello Briup";
try {
bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(path),"UTF8"));
bw.write(info,0,info.length());
}catch(IOException e) {
e.printStackTrace();
}finally {
try {
if(bw != null)
bw.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void test2(String path) {
BufferedReader br = null;
String line;
try {
br = new BufferedReader(new InputStreamReader(
new FileInputStream(path),"UTF8"));
//读一行数据
line = br.readLine();//特有方法
System.out.println("line: "+line);
}catch(IOException e) {
e.printStackTrace();
}finally {
try {
if(br != null)
br.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//test1(args[0]);
test2(args[0]);
}
}
FileReader和FileWriter:可以简化以字符为单位进行文件的读和写操作
import java.io.*;
public class FileReaderWriterTest {
/*
* 将字符串写入文件,让程序员可以直接读懂
*/
public static void test1(String path) {
FileWriter fw = null;
String info = "Hello Briup";
try {
fw = new FileWriter(path);
fw.write(info,0,info.length());
}catch(IOException e) {
e.printStackTrace();
}finally {
try {
if(fw != null)
fw.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void test2(String path) {
FileReader fr = null;
char[] array = new char[256];
try {
fr = new FileReader(path);
fr.read(array, 0, 256);
System.out.println("string: " + new String(array));
}catch(IOException e) {
e.printStackTrace();
}finally {
try {
if(fr != null)
fr.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//test1(args[0]);
test2(args[0]);
}
}