在Java中,把这些不同类型的输入、输出抽象为流(Stream),而其中输入或输出的数据称为数据流(Data Stream),用统一的接口来表示,从而使程序设计简单明了。
首先我要声明下:所谓的输入输出都是相对内存而言的
还要讲几个基本概念:字节流和字符流,字节流8位,主要由InputStream和OutputStream来处理。字符流16位,主要由Reader和Writer来处理。
节点流和处理流,磁盘或网络等读写的数据的流为节点流,对节点流进行封装和处理的流叫处理流。
InputStream和Reader都是抽象类,我用他们对File的实现类做例子,eg(FileInputStream)
- public class FileInputStreamTest
- {
- public static void main(String[] args) throws IOException
- {
- //创建字节输入流
- FileInputStream fis = new FileInputStream("FileInputStreamTest.java");
- //创建一个长度为1024的“竹筒”
- byte[] bbuf = new byte[1024];
- //用于保存实际读取的字节数
- int hasRead = 0;
- //使用循环来重复“取水”过程
- while ((hasRead = fis.read(bbuf)) > 0 )
- {
- //取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!
- System.out.print(new String(bbuf , 0 , hasRead ));
- }
- fis.close();
- }
- }
eg(FileReader)
- public class FileWriterTest
- {
- public static void main(String[] args) throws IOException
- {
- FileWriter fw = null;
- try
- {
- //创建字符输出流
- fw = new FileWriter("poem.txt");
- fw.write("锦瑟 - 李商隐/r/n");
- fw.write("锦瑟无端五十弦,一弦一柱思华年。/r/n");
- fw.write("庄生晓梦迷蝴蝶,望帝春心托杜鹃。/r/n");
- fw.write("沧海月明珠有泪,蓝田日暖玉生烟。/r/n");
- fw.write("此情可待成追忆,只是当时已惘然。/r/n");
- }
- catch (IOException ioe)
- {
- ioe.printStackTrace();
- }
- finally
- {
- //使用finally块来关闭文件输出流
- if (fw != null)
- {
- fw.close();
- }
- }
- }
- }
以上是输入,下面讲下输出
OutputStream和Writer也是抽象类,我用他们对File的实现类做例子,eg(OutputStream)
- public class FileOutputStreamTest
- {
- public static void main(String[] args) throws IOException
- {
- FileInputStream fis = null;
- FileOutputStream fos = null;
- try
- {
- //创建字节输入流
- fis = new FileInputStream("FileOutputStreamTest.java");
- //创建字节输入流
- fos = new FileOutputStream("newFile.txt");
- byte[] bbuf = new byte[32];
- int hasRead = 0;
- //循环从输入流中取出数据
- while ((hasRead = fis.read(bbuf)) > 0 )
- {
- //每读取一次,即写入文件输出流,读了多少,就写多少。
- fos.write(bbuf , 0 , hasRead);
- }
- }
- catch (IOException ioe)
- {
- ioe.printStackTrace();
- }
- finally
- {
- //使用finally块来关闭文件输入流
- if (fis != null)
- {
- fis.close();
- }
- //使用finally块来关闭文件输出流
- if (fos != null)
- {
- fos.close();
- }
- }
- }
- }
eg(Writer)
- public class FileWriterTest
- {
- public static void main(String[] args) throws IOException
- {
- FileWriter fw = null;
- try
- {
- //创建字符输出流
- fw = new FileWriter("poem.txt");
- fw.write("锦瑟 - 李商隐/r/n");
- fw.write("锦瑟无端五十弦,一弦一柱思华年。/r/n");
- fw.write("庄生晓梦迷蝴蝶,望帝春心托杜鹃。/r/n");
- fw.write("沧海月明珠有泪,蓝田日暖玉生烟。/r/n");
- fw.write("此情可待成追忆,只是当时已惘然。/r/n");
- }
- catch (IOException ioe)
- {
- ioe.printStackTrace();
- }
- finally
- {
- //使用finally块来关闭文件输出流
- if (fw != null)
- {
- fw.close();
- }
- }
- }
- }
以上都是节点流的处理,但用起来比较麻烦,下面使用处理流来简化i/o操作
- public class PrintStreamTest
- {
- public static void main(String[] args)throws IOException
- {
- PrintStream ps = null;
- try
- {
- //创建一个节点输出流:FileOutputStream
- FileOutputStream fos = new FileOutputStream("test.txt");
- //以PrintStream来包装FileOutputStream输出流
- ps = new PrintStream(fos);
- //使用PrintStream执行输出
- ps.println("普通字符串");
- ps.println(new PrintStreamTest());
- }
- catch (IOException ioe)
- {
- ioe.printStackTrace(ps);
- }
- finally
- {
- ps.close();
- }
- }
- }
转换流,主要用于从字节流到字符流,方便流的操作,然后利用BufferedReader来方便字符流的操作,eg
- public class KeyinTest
- {
- public static void main(String[] args)
- {
- BufferedReader br = null;
- try
- {
- //将Sytem.in对象转换成Reader对象
- InputStreamReader reader = new InputStreamReader(System.in);
- //将普通Reader包装成BufferedReader
- br = new BufferedReader(reader);
- String buffer = null;
- //采用循环方式来一行一行的读取
- while ((buffer = br.readLine()) != null)
- {
- //如果读取的字符串为"exit",程序退出
- if (buffer.equals("exit"))
- {
- System.exit(1);
- }
- //打印读取的内容
- System.out.println("输入内容为:" + buffer);
- }
- }
- catch (IOException ioe)
- {
- ioe.printStackTrace();
- }
- //关闭输入流
- finally
- {
- try
- {
- br.close();
- }
- catch (IOException ioe)
- {
- ioe.printStackTrace();
- }
- }
- }
- }
最后讲下File类的使用,eg
- public class FilenameFilterTest
- {
- public static void main(String[] args)
- {
- File file = new File(".");
- String[] nameList = file.list(new MyFilenameFilter());
- for (String name : nameList)
- {
- System.out.println(name);
- }
- }
- }
- //实现自己的FilenameFilter实现类
- class MyFilenameFilter implements FilenameFilter
- {
- public boolean accept(File dir, String name)
- {
- //如果文件名以.java结尾,或者文件对应一个路径,返回true
- return name.endsWith(".java")
- || new File(name).isDirectory();
- }
- }
注意我加了后缀的过滤,讲了File不得不补充RandomAccessFile,任意文件访问类,拥有reader和writer的功能,但要注意
他对文件的插入只是一种覆盖,eg
- public class InsertContent
- {
- public static void insert(String fileName , long pos ,
- String insertContent)throws IOException
- {
- RandomAccessFile raf = null;
- //创建一个临时文件来保存插入点后的数据
- File tmp = File.createTempFile("tmp" , null);
- FileOutputStream tmpOut = null;
- FileInputStream tmpIn = null;
- tmp.deleteOnExit();
- try
- {
- raf = new RandomAccessFile(fileName , "rw");
- tmpOut = new FileOutputStream(tmp);
- tmpIn = new FileInputStream(tmp);
- raf.seek(pos);
- //--------下面代码将插入点后的内容读入临时文件中保存---------
- byte[] bbuf = new byte[64];
- //用于保存实际读取的字节数
- int hasRead = 0;
- //使用循环方式读取插入点后的数据
- while ((hasRead = raf.read(bbuf)) > 0 )
- {
- //将读取的数据写入临时文件
- tmpOut.write(bbuf , 0 , hasRead);
- }
- //----------下面代码插入内容----------
- //把文件记录指针重新定位到pos位置
- raf.seek(pos);
- //追加需要插入的内容
- raf.write(insertContent.getBytes());
- //追加临时文件中的内容
- while ((hasRead = tmpIn.read(bbuf)) > 0 )
- {
- raf.write(bbuf , 0 , hasRead);
- }
- }
- finally
- {
- raf.close();
- }
- }
- public static void main(String[] args) throws IOException
- {
- insert("InsertContent.java" , 45 , "插入的内容/r/n");
- }
- }