Java基础-IO流
来源:互联网 发布:网络传真怎么发 编辑:程序博客网 时间:2024/05/16 04:33
终于学习到了本人认为Java中体系最复杂的IO流这一章了。如果在学习之前没有好好的捋一捋IO流的体系,各种流之间的关系,学习起来真的会非常吃力。
IO概述:
IO流(Input&Output):是为了解决不同设备之间数据传输的问题。IO流一般配合着网络,才能发挥其强大的功能。
IO的体系图
分析: 在学习IO体系的时候,我们一般是按照字符流和字节流来展开的。每一个体系中,都有对应的普通的流和高效的流。
首先,学习字符流
字符流包括:
A:字符输入流 Reader —— 是一个抽象类,要想实现数据的输入,需要new其子类对象
B:字符输出流 Writer —— 是一个抽象类,new其子类对象
在学习过程中,通常会遇到这样的问题:一个流到底是输入流还是输出流,会有不同的争论。其实这个是相对的,一般情况下,我们都是站在Java程序的角度上去看待这个问题。在Java的角度,流进Java程序的,就是输入流,流出Java程序的就是输出流。需求:我们一般都会使用程序对文本文件来处理数据。要想对文件进行读取和写入数据,那么需要用到与File有关的输入输出流**FileReader & FileWriter** 下面我们来学习一下这两个类
代码: FileWriter
import java.io.FileWriter;import java.io.IOException;public class FileWriterDemo { public static void main(String[] args) { // 创建FileWriter对象 FileWriter fw = null; try { /* * 创建字符输出流对象做了几件事? A:调用系统功能创建了指定的文件; B:创建了字符输出流对象; C:把字符输出流对象指向创建的文件 */ fw = new FileWriter("a.txt"); //调用写数据的功能 fw.write("你好,傻逼IO"); /* * 为什么要flush() 在Java中,1个字符=2个字节 * 在系统文件数据的底层单位是字节,而我们现在使用的是字符输出流,所以不能直接把数据写入文件, * 在这里,是把要输出的数据存放在缓冲区里,只有我们刷新缓冲区,数据才会被写入到文件中. */ fw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { /* * 为什么一定要close() 1.让流对象变成垃圾 2.通知系统去释放与文件相关的资源. */ fw.close(); } catch (IOException e) { e.printStackTrace(); } } }}
结果:
分析:
A:创建字符流对象,做了几件事? 1、调用了系统功能创建了指定文件;2、创建了字符输出流对象;3、把字符输出流对象
指向了创建的文件。
B:为什么要flush() 在Java中,1个字符=2个字节
在系统文件数据的底层单位是字节,而我们现在使用的是字符输出流,所以不能直接把数据写入文件,
在这里,是把要输出的数据存放在缓冲区里,只有我们刷新缓冲区,数据才会被写入到文件中.
C:为什么一定要close()
1、让流变成垃圾,释放资源
2、通知系统去释放与文件管理相关的资源。
FileWriter的几个小问题
字符输出流操作步骤: * A:创建字符输出流对象 * B:调用字符输出流对象的写入数据方法,并刷新缓冲区 * C:释放资源
*
* 三个小问题:
*
* 问题1:为什么FileWriter没有无参构造方法?
* 因为在写数据的时候,必须要明确些到哪里去.
*
* 问题2:flush()和close()的区别?
* flush(): 只刷新缓冲区,流对象还可以使用
* close(): 先刷新缓冲区,再关闭流对象,流对象不可以继续被使用.
*
* 问题3:难道每次调用完流对象的写入数据方法时,都需要刷新缓冲区吗?是否可以不刷新,直接等到close()来解决?
* 这两种方法都不可取.
代码:FileWriter 加入了捕捉异常标准代码
package cn.itcast.filewriter;/* * FileWriter加入异常处理的标准代码 * */import java.io.FileWriter;import java.io.IOException;public class FileWriterDem3 { public static void main(String[] args) { // 创建字符输出流对象 FileWriter fw = null; try { fw = new FileWriter("c.txt"); fw.write("干了这杯热翔"); fw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (fw != null) { try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } }}
FileReader
FileReader 字符输入流
* 构造方法:
* FileReader(File file)
* FileReader(String fileName) 选用
*
* 读取方法:
* int read(): 每次读取一个字符,没读取完一个字符,自动移动到下一个数据位置等待读取
* 当没有数据可读时,会返回-1
int read(char[] cbuf):
代码:
public class FileReaderDemo { public static void main(String[] args) { // 创建字符输入流对象 FileReader fr = null; try { fr = new FileReader("FileReaderDemo.java");// int ch = fr.read();// while(ch != -1){// System.out.print((char)ch);// ch = fr.read();// } //开发是的写法 int ch = 0; while((ch=fr.read())!=-1){ System.out.print((char)ch); } } catch (IOException e) { e.printStackTrace(); } finally { if (fr != null) { try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } } }}
结果:
分析:
读取一个文件,在控制台上输出
FileReader读取数据方式二:
* int read(char[] cbuf): 每次读取数据,把数据存储到字符数组中,读取长度自定义,一般为1024的整数倍
* 返回值是实际读取的长度.
代码2:
import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class FileReaderDemo3 { public static void main(String[] args) throws IOException { //创建字符输入流对象 FileReader fr = new FileReader("FileReaderDemo.java"); //读取 开发中的代码 char[] chs = new char[1024]; int len = 0; while((len = fr.read(chs))!=-1){ System.out.print(new String(chs,0,len)); } }}
结果:
分析:
这个是开始中的标准代码,每次读取1024个字符,大大的提高了效率。在开发中,一般这个字符数组的大小,都是设置为1024的整数倍。
那么在学习完FileReader和FileWriter两个对文件操作的类后,就可以用这些学习过的方法,来进行文件的复制了。
需求:将本项目目录下的FileReaderDemo.java文件,复制到D:\copy.java
* 思路:
* 数据源:
* FileReaderDemo.java – Reader –FileReader
*
* 目的地:
* D:\copy.java – Writer – FileWriter
代码;
import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyFileDemo { public static void main(String[] args) throws IOException { // 创建字符输入流对象 FileReader fr = new FileReader("FileReaderDemo.java"); // 创建字符输出流对象 FileWriter fw = new FileWriter("D:\\copy.java"); // 读入数据 int ch = 0; while ((ch = fr.read()) != -1) { fw.write(ch); } fw.flush(); // 释放资源 fw.close(); fr.close(); }}
结果:
相对高效的复制操作,其实也就是用了字符数组的原理:
代码:
import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyFileDemo2 { public static void main(String[] args) throws IOException { //创建字符输入流对象 FileReader fr = new FileReader("FileReaderDemo.java"); //创建字符输出流对象 FileWriter fw = new FileWriter("d:\\copy1.java"); //创建一个大小为1024的字符数组,存储输入流读取到的数据 char[] chs = new char[1024]; int ch = 0; //读取 while((ch = fr.read(chs))!= -1){ //将存储在字符数组中的数据写进指定的文件 fw.write(chs); } //刷新输出流 fw.flush(); //关闭资源 fw.close(); fr.close(); }}
学习完简单的文件字符流类,下面来学习一下简单的文件字节流类
FileInputStream 和 FileOutputStream
在IO体系里,基本上方法和格式都是固定的,出了部分类有自己特有的方法外,其他基本上都是通用。那么,我们直接使用在FileReader 和 FileWriter类中的方法,进行操作
通过字节流往文件中写数据。
*
* 字节输出流操作步骤:
* A:创建字节输出流对象
* B:调用写数据的方法
* C:释放资源
FileOutputStream
代码:
public class FileOutputStreamDemo { public static void main(String[] args) throws IOException { // 创建字节输出流对象 // FileOutputStream fos = new FileOutputStream("a.txt",true); FileOutputStream fos = new FileOutputStream("a.txt"); // 调用写数据的方法 // 写入一个字节 // fos.write(97); // fos.write(98); // fos.write(99); // fos.flush(); // 写一个字节数组 // byte[] bys = { 97, 98, 99, 100, 101 }; byte[] bys = "abcde".getBytes(); // fos.write(bys); // 写一个字节数组的一部分 fos.write(bys, 0, 2); // 释放资源 fos.close(); }}
FileInputStream
代码:
public class FileInputStreamDemo { public static void main(String[] args) throws IOException { // 创建字节输入流对象 FileInputStream fis = new FileInputStream("b.txt"); // 调用读取数据的方式,并显示 // 方式1 // int by = 0; // while ((by = fis.read()) != -1) { // System.out.println(by); // } // 方式2 byte[] bys = new byte[1024]; int len = 0; while ((len = fis.read(bys)) != -1) { System.out.print(new String(bys, 0, len)); } // 释放资源 fis.close(); }}
——————————————————————————————————————————-到这里,已经把简单的字符流和字节流学习了。不过这些方法都属于比较低效的。
下面,我们学习一下高效的字符缓冲流和字节缓冲流
A:字符缓冲流
|–BufferedWriter
|–BufferedReader
B:字节缓冲流
|–BufferedInputStream
|–BufferedOutputStream
字符缓冲流
* 我们开始自己定义数组,给出缓冲区大小,是为了提高效率。
* 那么,java在设计类的时候,它也考虑到了这一点,所以,就提供了一种高效的流。带缓冲区的流。
* BufferedWriter:写入数据
* BufferedReader:读取数据
*
* BufferedWriter:
* 构造方法:BufferedWriter(Writer out)
* 为什么传递的是Writer呢?
* 因为BufferedWriter这种流,被称为缓冲流,它只提供数据的缓冲功能。
* 真正的读写还得靠别人。所以,我们这里将使用FileWriter作为参数传递。
*
* 缓冲区只提供缓冲功能,没有真正的读写。
*
* 基本流:能直接进行读写的流对象。
* 高级流:站在基本流的基础上,提供一些特殊的功能。(处理流。)
代码:BufferedWriter
public class BufferedWriterDemo { public static void main(String[] args) throws IOException { // 创建缓冲流对象 // Writer fw = new FileWriter("c.txt"); // FileWriter fw = new FileWriter("c.txt"); // BufferedWriter bw = new BufferedWriter(fw); BufferedWriter bw = new BufferedWriter(new FileWriter("c.txt")); // 写入数据 bw.write("hello"); bw.flush(); // 释放资源 // fw.close();// 这个不用关闭 bw.close(); }}
代码:FileReader:
import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;/* * 字符缓冲流读取数据 */public class BufferedReaderDemo { public static void main(String[] args) throws IOException { // 创建字符缓冲流对象 BufferedReader br = new BufferedReader(new FileReader("c.txt")); // 读取数据 // int ch = 0; // while ((ch = br.read()) != -1) { // System.out.print((char) ch); // } char[] chs = new char[1024]; int len = 0; while ((len = br.read(chs)) != -1) { System.out.print(new String(chs, 0, len)); } // 释放资源 br.close(); }}
在学习简单IO流的时候,有一个复制文件的操作,如果要复制的文件比较大,可以使用字符缓冲流来提高效率
代码:
package cn.itcast_03;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;/* * 用字符高效流复制文本文件。 * * 数据源: * FileOutputStreamDemo.java * 目的地: * Copy.java */public class CopyFile { public static void main(String[] args) throws IOException { // 封装数据源和目的地 BufferedReader br = new BufferedReader(new FileReader( "FileOutputStreamDemo.java")); BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")); // 一次一个字符 // int ch = 0; // while ((ch = br.read()) != -1) { // bw.write(ch); // // bw.flush(); // } // 一次一个字符数组 char[] chs = new char[1024]; int len = 0; while ((len = br.read(chs)) != -1) { bw.write(chs, 0, len); } // 释放资源 bw.close(); br.close(); }}
结果:
由于操作速度非常快,都是用毫秒值来计算的,那么我们要怎样才能知道,到底字符缓冲流,是不是真的比较高效呢?
我们在学习System类的时候,有一个currentTimeMillis()的方法,可以用来计算一段代码之间的时间
不多说,马上改造:代码
package cn.itcast_04;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/** * 需求:把d:\\哥有老婆.mp4复制到项目路径下x.mp3(x=1,2,3,4) * * @author Administrator * * 基本字节流一次读写一个字节: 共耗时:66922毫秒 * 基本字节流一次读写一个字节数组: 共耗时:94毫秒 * 高效字节流一次读写一个字节:共耗时:1235毫秒 * 高效字节流一次读写一个字节数组:共耗时:47毫秒 */public class CopyMP3 { public static void main(String[] args) throws IOException { long start = System.currentTimeMillis(); // method1(); // method2();// method3(); method4(); long end = System.currentTimeMillis(); System.out.println("共耗时:" + (end - start) + "毫秒"); } //高效字节流一次读写一个字节数组 private static void method4() throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream( "d:\\哥有老婆.mp4")); BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("4.mp4")); byte[] bys = new byte[1024]; int len = 0; while((len=bis.read(bys))!=-1){ bos.write(bys,0,len); } bos.close(); bis.close(); } //基本字节流一次读写一个字节数组 private static void method3() throws IOException { FileInputStream fis = new FileInputStream("d:\\哥有老婆.mp4"); FileOutputStream fos = new FileOutputStream("3.mp4"); byte[] bys = new byte[1024]; int len = 0; while((len=fis.read(bys))!=-1){ fos.write(bys,0,len); } fos.close(); fis.close(); } // 高效字节流一次读写一个字节 private static void method2() throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream( "d:\\哥有老婆.mp4")); BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("2.mp4")); int by = 0; while ((by = bis.read()) != -1) { bos.write(by); } bos.close(); bis.close(); } // 基本字节流一次读写一个字节 private static void method1() throws IOException { FileInputStream fis = new FileInputStream("d:\\哥有老婆.mp4"); FileOutputStream fos = new FileOutputStream("1.mp4"); int by = 0; while ((by = fis.read()) != -1) { fos.write(by); } fos.close(); fis.close(); }}
结果:
* 基本字节流一次读写一个字节: 共耗时:66922毫秒
* 基本字节流一次读写一个字节数组: 共耗时:94毫秒
* 高效字节流一次读写一个字节:共耗时:1235毫秒
* 高效字节流一次读写一个字节数组:共耗时:47毫秒
分析:
高效流确实会更有效率,一般在开发中,我们都是选择高效流来使用。
BufferedWriter 和 BufferedReader 的特有方法
* BufferedWriter: * public void newLine():根据系统平台写入行分隔符 * * BufferedReader: * public String readLine():一次读取一行的数据。但是不包含换行符。代码如下:
public class BufferedStreamDemo { public static void main(String[] args) throws IOException { //创建流对象 BufferedReader br = new BufferedReader(new FileReader("bw.txt")); // 读取数据 String line = null; while((line=br.readLine())!=null){ System.out.println(line); } br.close(); }}
- JAVA 基础IO流
- java基础:IO流
- Java基础-->IO流
- Java IO流基础
- java基础---IO流
- Java基础:IO流
- Java基础---IO流
- JAVA基础----IO流
- Java基础---IO流
- Java基础-IO流
- Java基础--------IO流
- 【java基础】]IO流
- java基础 IO流
- Java基础--IO流
- JAVA IO流 基础
- Java IO流基础
- Java IO流基础
- java基础/IO流/
- 安卓操作系统的组成部分
- Ext.form.ComboBox最常用的一些属性和方法
- 欢迎使用CSDN-markdown编辑器
- LNMP服务器安全指南
- 关于文件上传遇到的问 no multipart boundary was found
- Java基础-IO流
- GDB调试利器
- 使用epublib解析epub文件(章节内容、书籍菜单)
- git断点续传
- nagios插件之登陆SBC监控电话数
- 求最大公约数(欧几里得算法尾递归版)+N皇后算法(位运算版)
- Android数据库 之 SQLite数据库
- 近期将会暂停服务的网站一览 - 做好数据迁移的准备哦^_^
- Struts2表单回显原理,struts2表单回显