学前知道
Java的IO使用“流”的概念来表示。IO流涉及到数据源和目的地。流,是从源“流向”目的的数据流。
Java将各种数据源和目标之间数据的传输统一抽象为流,通过对流对象的操作来完成I/O功能。
输入输出实际都是对内存而言的。
数据源可以是键盘、文件、应用程序、鼠标、网络连接。数据目的地可以是屏幕、文件、应用程序、网络连接。
无论数据从哪种数据源到哪种数据目的地,也无论数据是哪种类型,IO操作的基本方法是一样的。
输入:创建一个输入流类对象,读数据,关闭流。
输出:创建一个输出流类对象,写数据,关闭流。
可以将流理解为连接数据源和目的的管道。
按照数据流的方向分为输入流和输出流。
按照流处理数据类型的不同分为字节流和字符流。
缓冲输入流BufferedInputStream和BufferedReader类添加了缓存功能,创建对象时即创建了一个内部缓冲区支持 mark 和 reset功能。
通过设置BufferedOutputStream和BufferedWriter输出流,应用程序可以将多个字节批量写入基本输出流中,而不必每个字节都调用底层的系统IO。(通俗点,就是说,先放内存中,等达到一个设定值长度时输出)
缓冲流通常封装其它的基本流类,实现一次读写批量数据,从而提高了效率。(这整段看到缓冲流时再看) !缓冲流为功能流,必须要传入非功能流对象
Java的对象流ObjectInputStream和ObjectOutputStream类能实现读写Java类对象。
ObjectInputStream能够从输入流中读取对象而不是原始字节。但是对象必须是序列化的对象,也就是必须实现Serializable接口。
ObjectOutputStream能够恢复之前被序列化的对象。
Java IO的API使用Java.IO包其中超过50个类(可以自己查看Java API文档,标记为常用):

下面为object的四个直接子类(四个抽象类) :

注:
文本文件的输入输出推荐使用字符流。(防止乱码-->字符与子节类型占用长度的区别)
其它的,比如,视频,音频,word文档(特别的)推荐使用字节流。(这类型的文件不支持字节流处理)
小点与练习
inputstream抽象类:

InputStream类中的常用方法:
int **available()**返回输入流中下一次调用能够不受阻塞的读取或跳过的字节数。
void **close()**关闭输入流并释放相关所有系统资源。
void mark(int readlimit)标记输入流的当前位置。
abstract int read()从输入流中读取一个字节。该方法的属性为abstract,必须由子类实现。
int read(byte[] b)从输入流中读取一定数量的字节存入字节数组b,并返回读取的字节数。
int read(byte[] b, int off, int len) 从输入流中读取最多len个字节存入字节数组b,读取的第一个字节存入b[off]中,依次类推。
void reset()将流重新置位为上次mark的位置。
long skip(long n)跳过输入流中的指定数量n个字节。
boolean **marksupported()**判断输入流是否支持mark和reset。
FileInputStream构造函数:
FileInputStream(File file);创建一个连接到文件file的FileInputStream流对象(文件有相对路径与绝对路径)
FileInputStream(String name);创建一个连接到文件名为name的FileInputStream流对象
缓冲流:
BufferedInputStream (InputStream in): 创建一个封装基本流类in的BufferedInputStream流对象。
对象流特别的方法:
从对象输入流中读取一个对象。 Object readObject()
outputstream抽象类:

OutputStream类中的常用方法:
abstract void write(int b)将整形b的低字节写到输出流。该方法的属性为abstract,必须为子类所实现。
void **write(byte b[])**把字节数组b中的b.length个字节写输出流。
void **write(byte b[], int off, int len)**把字节数组b中从off开始的len个字节写到输出流。
void **flush()**有时写到输出流的字节并没有被真正发送出去,而是被缓存,达到一定的积累才被真正写出。这是流的内部实现为了提高效率而设计如此的。flush( )方法强制缓存的数据立即执行写操作。
void **close()**关闭输出流并释放与之相关关的所有系统资源。
FileOutputStream构造函数:
FileOutputStream(File file);创建一个连接到文件file的FileInputStream流对象(文件有相对路径与绝对路径)
FileOutputStream(File file,boolean append);如果append为true,字节内容将会添加到文件末尾
FileOutputStream(String name);创建一个连接到文件名为name的FileInputStream流对象
FileOutputStream(String name,boolean append);如果append为true,字节内容将会添加到文件末尾
缓冲流:
BufferedOutputStream (OutputStream out): 创建一个封装基本流类out的BufferedOutputStream 流对象
对象流特别的方法:
将对象obj写入对象输出流。 void writeObject(object obj)
第一个案例(文件流):

1 1 public class FileRW { 2 2 3 3 /*1.完成一个完整的文件读写案例(用java的字节流写一个文件复制器软件),例如:把c:/1.txt完整复制到d:\1.txt 4 4 扩展部分:考虑单个字节读写和提高效率读写方式*/ 5 5 public void fileCopy() throws IOException{ 6 6 FileInputStream fis = new FileInputStream("c:/1.txt"); 7 7 FileOutputStream fos = new FileOutputStream("d:/1.txt"); 8 8 9 9 int len; 1010 byte[] b = new byte[1024]; 1111 while((len = fis.read(b)) != -1){ 1212 fos.write(b, 0, len); 1313 } 1414 fis.close(); 1515 fos.close(); 1616 }
View Code

1 1 public class Text { 2 2 3 3 public static void main(String[] args) throws IOException { 4 4 // TODO Auto-generated method stub 5 5 FileRW fileRW = new FileRW(); 6 6 7 7 fileRW.fileCopy(); 8 8 9 9 } 1010 1111 }
View Code
第二个案例(文件流):

1 1 // 2.做一个文本文件过滤器组件,要求,用代码实现读取一个文本文件,进行处理,把文件里面的‘TMD’替换成'***' 2 2 //第一种 3 3 /*public void filter() throws IOException{ 4 4 FileReader fr = new FileReader("d:/1.txt"); 5 5 char[] c = new char[1]; //先一个字符读取 6 6 while( fr.read(c) != -1){ 7 7 if (c[0] == 'T') { 8 8 char[] ch = new char[2]; //等查找到T使用两个字符读取 9 9 fr.read(ch); 1010 if (ch[0] == 'M' && ch[1] == 'D') { 1111 String string = new String("TMD"); 1212 System.out.print(string.replace("TMD", "***")); 1313 continue; 1414 } 1515 else { 1616 System.out.print(c); 1717 System.out.print(ch); 1818 continue; 1919 } 2020 } 2121 System.out.print(c); 2222 } 2323 fr.close(); 2424 }*/ 2525 //第二种比上一个快 2626 public void filter() throws IOException{ 2727 FileReader fr = new FileReader("d:/1.txt"); 2828 char[] c = new char[1024]; 2929 while( fr.read(c) != -1){ 3030 String s = new String(c); 3131 s = s.replace("TMD", "***"); 3232 System.out.println(s); 3333 } 3434 fr.close(); 3535 }
View Code

1 1 public class Text { 2 2 3 3 public static void main(String[] args) throws IOException { 4 4 // TODO Auto-generated method stub 5 5 FileRW fileRW = new FileRW(); 6 6 7 7 fileRW.filter(); 8 8 9 9 } 1010 1111 }
View Code

11 public void filter() throws IOException{ 22 BufferedReader bfr = new BufferedReader(new FileReader("d:/1.txt")); 33 String str; 44 while ((str = bfr.readLine()) != null) { 55 String s = new String(str); 66 System.out.println(s.replace("TMD", "***")); 77 } 88 }
View Code
reader抽象类:

Reader类中常用的方法:
int read() 读取单个字符。
int read(char[] cbuf) 从输入流中读取一定数量的字符到字符数组cbuf。
int read(char[] cbuf,int off,int len) 将输入流中最多len个字符读入字符数组cbuf的off位置开始的部分。
long skip(long n) 跳过次输入流中的指定数量的字符。
void mark(int readAheadLimit) 标记输入流的当前位置。
void reset() 重置输入流到上次mark方法标记的位置。
void **close()**关闭输入流并释放与流相关的所有系统资源。
boolean ready() 判断输入流是否可读。
boolean **marksupported()**判断输入流是否支持mark和reset。
构造函数与 FileInputStream类似,不赘述
缓冲流:
BufferedReader (Reader out): 创建一个封装基本流类out的BufferedOutputStream流对象
BufferedReader类特别的方法:
String readLine()): 一次读取一行以'\n' 、'\r'或'\n' '\r'为结束符的文本。
writer抽象类:

Writer类中的常用方法:
void write(int c) 将指定的字符写入输出流。
void write(char[] cbuf) 将指定的字符数组cbuf的内容写入输出流。
void write(char[] cbuf,int off, int len) 把字节数组b中从索引off开始的len个字符写入输出流。
write(String str) 将指定字符串str的各个字符写入输出流。
write(String str,int off,int len) 将指定字符串str从off位置开始的len个字符写入输出流。
void flush() 刷新输出流并强制写出缓冲区中的输出字符。
void close() 关闭此输出流并释放与之相关的系统资源。
Writer append(char c)把字符c追加到输出流。
Writer append( CharSequence csq) 把字符序列csq追加到输出流。
构造函数与 FileOutputStream类似,不赘述
缓冲流:
BufferedWriter (Writer out): 创建一个封装基本流类out的BufferedWriter流对象。
BufferedWriter类特别的方法:
void write(String s,int off, int len) 提供了一个直接写字符串的方法写入部分字符串s,从off位置开始的len个字符。
第三个案例(文件流):

1 1 // 3.读取一个图像或者音频文件,读取过程中,每读取100个自己,跳过1个字节,然后保存成一个新文件,看看会得到什么效果的文件? 2 2 // 文件已损坏,不能播放 3 3 public void fileSkip() throws IOException{ 4 4 FileInputStream fis = new FileInputStream("music/李慧珍 - 在等待.mp3"); 5 5 FileOutputStream fos = new FileOutputStream("d:/李慧珍 - 在等待.mp3"); 6 6 7 7 int len; 8 8 byte[] b = new byte[100]; 9 9 while((len = fis.read(b)) != -1){ 1010 fos.write(b, 0, len); 1111 fis.skip(1); 1212 } 1313 fis.close(); 1414 fos.close(); 1515 }
View Code

1 1 public class Text { 2 2 3 3 public static void main(String[] args) throws IOException { 4 4 // TODO Auto-generated method stub 5 5 FileRW fileRW = new FileRW(); 6 6 7 7 fileRW.catalog(); 8 8 } 9 9 1010 }
View Code
第四个案例(对象流):

1 1 //Javabean 2 2 public class User implements Serializable{ 3 3 4 4 private String username; 5 5 private String password; 6 6 private String regTime; 7 7 8 8 public String getUsername() { 9 9 return username; 1010 } 1111 1212 public void setUsername(String username) { 1313 this.username = username; 1414 } 1515 1616 public String getPassword() { 1717 return password; 1818 } 1919 2020 public void setPassword(String password) { 2121 this.password = password; 2222 } 2323 2424 public String getRegTime() { 2525 return regTime; 2626 } 2727 2828 public void setRegTime(String regTime) { 2929 this.regTime = regTime; 3030 } 3131 3232 @Override 3333 public String toString() { 3434 return "User [username=" + username + ", password=" + password + ", regTime=" + regTime + "]"; 3535 } 3636 3737 }
View Code

1 1 //模拟迅雷下载 2 2 public class Test { 3 3 /* 5.使用序列化流(ObjectOutputStream)流将一个User类的对象序列化(存储)到磁盘上,然后继而用反序列化将之前存储的对象从磁盘上读取出来并将对象的属性输出到控制台。 4 4 User 类设计如下: 5 5 Class User{ 6 6 String username;//用户名 7 7 String password;//密码 8 8 String regTime;//注册时间 9 9 }*/ 1010 public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { 1111 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:/123.txt")); 1212 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:/123.txt")); 1313 1414 User u = new User(); 1515 u.setUsername("张三"); 1616 u.setPassword("123456"); 1717 u.setRegTime(new Date().toLocaleString()); 1818 oos.writeObject(u); 1919 2020 User o = (User)ois.readObject(); 2121 2222 System.out.println(o.toString()); 2323 oos.close(); 2424 ois.close(); 2525 } 2626 2727 }
View Code
第五个案例(缓冲流):

1 1 public class Test { 2 2 /*6.设计一个简单的聊天记录保存功能,将控制台输入的内容保存到一个文本文件中(能够续存,而不是覆盖)。*/ 3 3 public static void main(String[] args) throws IOException { 4 4 BufferedWriter bfw = new BufferedWriter(new FileWriter("E:/456.txt")); 5 5 String n = null; 6 6 do{ 7 7 Scanner s = new Scanner(System.in); 8 8 n = s.nextLine(); 9 9 bfw.write(n); 1010 bfw.newLine(); 1111 bfw.flush(); 1212 }while(n != "1"); 1313 1414 bfw.close(); 1515 } 1616 1717 }
View Code
需要多思考,不断实践去尝试摸索
https://www.cnblogs.com/biehongli/p/6074713.html 这个看了一下,推荐一下