------- android培训、java培训、期待与您交流! ----------
前言
IO流,应该算是JAVA程序,与外部沟通的桥梁吧。
这边整理一下自己在IO流学习中,经常容易忘掉的知识点。
说明:
1)本文中的代码,为了体现主干流程思想,暂时上抛所有异常。
2)JDK1.7版本以后,可以参考新try-catch的处理方法,处理IO流的关闭。
1、在文件后添加内容
实现方法:在新建文件流的时候,第二个参数置为true。eg:
private static void appendFile() throws IOException { //打开文件流 FileWriter fw1 = new FileWriter("D:\\1.txt"); //写入文件 fw1.write("HelloWorld1"); //关闭文件流 fw1.close(); //再次打开文件流 FileWriter fw2 = new FileWriter("D:\\1.txt",true); //写入文件 fw2.write("HelloWorld2"); //关闭文件流 fw2.close(); }
2、LineNumberReader类
通过LineNumberReader类读取行数、指定读取的起始行数,eg:
private static void lineNumber() throws FileNotFoundException, IOException { LineNumberReader lnr = new LineNumberReader(new FileReader("D:\\ClassLoaderTest.java")); //指定读取的起始行数 lnr.setLineNumber(2); String line = null; while(null!=(line=lnr.readLine())) //获取行数,并打印行内容 System.out.println(lnr.getLineNumber() + ":" + line); lnr.close(); }
该流提供了打印方法,可以将各中数据类型的数据都原样打印。eg:
private static void PrintWriterTest() { //新建打印流 PrintWriter pr = new PrintWriter(System.out); //打印数据 pr.println("hello"); //打印基本数据 pr.println(1.111); List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); //打印对象 pr.println(list); //关闭打印流 pr.close(); }
4、合并流
用于合并读取多个输入流,eg:
private static void sequenceInputStreamTest() throws FileNotFoundException, IOException { //用一个Vector存储多个输入流 Vector<FileInputStream> vector = new Vector<FileInputStream>(); vector.add(new FileInputStream("D:\\1.txt")); vector.add(new FileInputStream("D:\\2.txt")); vector.add(new FileInputStream("D:\\3.txt")); //定义一个序列流 SequenceInputStream sis = new SequenceInputStream(vector.elements()); //定义一个输出流 FileOutputStream fos = new FileOutputStream("D:\\4.txt"); //依此读取 三个输入流 到 一个输出流 中 int len=0; byte[] buf = new byte[1024]; while((len=sis.read(buf))>0) { fos.write(buf, 0, len); } //关闭输出流 fos.close(); //关闭输入流 sis.close(); }
5、对象序列化ObjectInputStream和ObjectOutputStream
被操作的对象,需要实现Serializable接口(标记接口),eg:
1)可序列化的类:
import java.io.Serializable; public class Person implements Serializable{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }2)序列化对象:
private static void objectOutputStreamTest() throws IOException, FileNotFoundException { //定义对象输出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\object.txt")); //定义待序列化的对象 Person person = new Person(); person.setName("cby"); //序列化对象到文件中 oos.writeObject(person); //关闭输出流 oos.close(); }3)反序列化对象
private static void objectInputStreamTest() throws IOException, FileNotFoundException, ClassNotFoundException { //定义对象输入流 ObjectInputStream oos = new ObjectInputStream(new FileInputStream("D:\\object.txt")); //从文件中反序列化对象 Person person = (Person)oos.readObject(); //获取对象中的属性值 System.out.println(person.getName()); //关闭输入流 oos.close(); }
4)序列化的文件
1)、静态属性是不能被序列化的
2)、如果有非静态成员不详序列化,应该用transient修饰。
6、管道流PipedInputStream和PipedOutputStream
输入输出可以直接进行连接。
应该用于多线程,单线程易导致死锁。
在写之前,读是阻塞式方法。
开发的时候,参考API文档就可以了。
7、RandomAccessFile
随机访问文件(灰常强大),有些书上说,这个类可以用作断点续传。
主要是因为,这个类读取文件时,是可以指定开始读取位置的。
开发的时候,参考API文档就可以了。
8、数据流:DataOutputStream和DataInputStream
专门用于操作数据的流。
开发的时候,参考API文档就可以了。
9、数组操作对象:ByteArrayInputStream和ByteArrayOutputStream
没有访问资源,不需要关闭。
即使关闭以后,对象依然可以正常访问。
开发的时候,参考API文档就可以了。
10、转换流操作编码表
//定义文本转换输出流(向文件输出UTF-8编码的中文字符)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\utf.txt"),"UTF-8");
//写入信息
osw.write("你好");
//关闭流
osw.close();
当你同时访问多个文件资源时,多个IO流的释放往往是一件让人头疼的事。
我们可以看一下以下的代码:
我们可以看一下以下的代码:
public static void main(String[] args) { FileReader fr = null; FileWriter fw = null; try { fr = new FileReader("D:\\ClassLoaderTest.java"); fw = new FileWriter("D:\\ClassLoaderTest1.java"); char[] cbuf = new char[1024]; int len = 0; while((len=fr.read(cbuf)) > 0) fw.write(cbuf, 0, len); } catch (IOException e) { e.printStackTrace(); } finally { try { if(null!=fr) { fr.close(); } } catch (IOException e) { e.printStackTrace(); } finally { try { if(null!=fw) { fw.close(); } } catch (IOException e) { e.printStackTrace(); } } } }代码的功能很简单,其实就是将一个文本文件拷贝到另外一个文本文件中。
但为了较为安全的释放IO流访问的资源。
我们花费了将近一半的篇幅,来写释放资源的代码。
看括号的层次,就挺让人觉得烦躁的。
所以,在JDK1.7中,我们可以用如下方法来实现:
public static void main(String[] args) { try ( FileReader fr = new FileReader("D:\\ClassLoaderTest.java"); FileWriter fw = new FileWriter("D:\\ClassLoaderTest1.java"); ) { char[] cbuf = new char[1024]; int len = 0; while((len=fr.read(cbuf)) > 0) fw.write(cbuf, 0, len); } catch (IOException e) { e.printStackTrace(); } }显然,以上这段代码,相对于第一段代码而言,清晰很多。
两段代码的区别在于:
1、将资源的创建放到了try后面的小括号中。
2、省去了资源释放的代码。
在try中的代码运行结束后,不需要手动的close()资源。
JAVA会自动去释放这些资源。
这应该算是JDK1.7之后一个较好的改进吧。
2、省去了资源释放的代码。
在try中的代码运行结束后,不需要手动的close()资源。
JAVA会自动去释放这些资源。
这应该算是JDK1.7之后一个较好的改进吧。