java io流小结

来源:互联网 发布:联合贷网络贷款 编辑:程序博客网 时间:2024/04/29 03:05

java IO流类结构图:

 

流:

    流是一组有序的,有起点和终点的字节集合,是对数据传输的总称或抽象,即数据在两设备间的传输称为流。

IO流的分类:

    根据处理数据类型的不同分为:字节流和字符流。

    根据数据流向不同分为:输入流和输出流。

字节流和字符流:

    字符流的由来:因为字符编码的不同,而有了对字符进行高效操作的流对象,本质就是基于字节流读取时,去查了指定的码表。

    二者的区别:

        读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读取多个字节。

        处理对象不同:字节流能处理所有类型的数据(如图片、视频等),而字符流只能处理字符类型的数据。

输入流和输出流:(输入与输出是站在程序的角度而言的)

    对输入流只能进行读操作, 对输出流只能进行写操作。

 

在java中,有很多流类,但我们常用的只有那么几个。

字节流:


1. FileInputStream与FileOutputStream:对文件系统中某个文件的读写操作。

一个文件拷贝的列子:

读取文件:

<span style="font-family:Microsoft YaHei;">public class FileCopyInputStream {/** * 读源文件,并将读取的结果保存到ArrayList中 *  * @param file *            源文件 * @param isCut *            是否剪切,true==剪切,false==复制 * @return 源文件内容,即ArrayList */public ArrayList<DataBuffer> read(File file, boolean isCut) {// 文件输入流FileInputStream fis = null;// ArrayList,用来保存读取的数据ArrayList<DataBuffer> aList = new ArrayList<>();try {// 初始化文件输入流fis = new FileInputStream(file);// 文件容量大于0,就读if (fis.available() > 0) {// 读取的内容,为-1时表示文件读取结束// 临时数组,用来保存read方法读到的数据byte[] bytes = new byte[1024];// read方法读到的数据的长度int readLength = 0;// 一直读到文件结尾while ((readLength = fis.read(bytes)) != -1) {// 创建一个DataBuffer对象,用来装载每一次read方法读出的数据DataBuffer db = new DataBuffer();// 读取的内容db.setBytes(bytes);// 读取的长度db.setLength(readLength);// 将DataBuffer对象添加到ArrayList中aList.add(db);}}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {// 文件输入流不为空时,关闭输入流if (fis != null) {try {// 关闭文件流fis.close();} catch (IOException e) {e.printStackTrace();}}}// 剪切,删除源文件if (isCut) {file.delete();}// 返回读取的内容return aList;}}</span>
将读取的数据写入到文件:

<span style="font-family:Microsoft YaHei;">public class FileCopyOutputStream {/** * 将数据写入到一个新的文件中 *  * @param file *            目标文件 * @param aList *            数据源 */public void write(File file, ArrayList<DataBuffer> aList) {// 文件输出流FileOutputStream fos = null;try {// 初始化文件输出流fos = new FileOutputStream(file);// 迭代器,遍历ArrayList中的数据Iterator<DataBuffer> iter = aList.iterator();// 遍历while (iter.hasNext()) {// 取出数据DataBuffer db = iter.next();// 将数据写入到输出流fos.write(db.getBytes(), 0, db.getLength());}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {// 文件输出流不为空时,关闭输出流if (fos != null) {try {// 清空文件输出流fos.flush();// 关闭文件输出流fos.close();} catch (IOException e) {e.printStackTrace();}}}}}</span>
DataBuffer辅助类:

<span style="font-family:Microsoft YaHei;">public class DataBuffer {// byte数组,用来保存读出的数据private byte[] bytes;// 保存每次读出的数据长度private int length;/** * 获取byte数组 *  * @return byte数组 */public byte[] getBytes() {return bytes;}/** * 设置byte数组的值 *  * @param bytes *            byte数组 */public void setBytes(byte[] bytes) {this.bytes = bytes;}/** * 获取数据长度 *  * @return 数据长度 */public int getLength() {return length;}/** * 设置数据长度 *  * @param length *            数据长度 */public void setLength(int length) {this.length = length;}}</span>
测试类:

<span style="font-family:Microsoft YaHei;">public class FileCopyTest {public static void main(String[] args) {// 源文件File src = new File("C:\\Users\\Administrator\\Desktop\\aa.txt");// 目标文件目录File desc = new File("src/com/wzd/filecopy/");// 执行拷贝操作copy(src, desc, false);}/** * 拷贝 *  * @param src *            源文件 * @param desc *            目标目录 * @param isCut *            true,剪切 false,复制 */public static void copy(File src, File desc, boolean isCut) {// 判断源文件是目录还是文件if (src.isFile()) {// 是文件copyFile(src, desc, false);} else {// 是目录coprDirectory(src, desc, false);}}/** * 拷贝目录 *  * @param src *            源文件 * @param desc *            目标目录 * @param isCut *            true,剪切 false,复制 */private static void coprDirectory(File src, File desc, boolean isCut) {// 在目标目录下创建一个新文件对象File newDirectory = new File(desc, src.getName());// 创建目录newDirectory.mkdirs();// 拷贝该目录内的子文件File[] files = src.listFiles();// 遍历flies数组for(File file : files) {// 继续拷贝copy(file, newDirectory, false);}// 剪切文件,则删除if(isCut) {src.delete();}}/** * 拷贝文件 *  * @param src *            源文件 * @param desc *            目标目录 * @param isCut *            true,剪切 false,复制 */private static void copyFile(File src, File desc, boolean isCut) {// 在目标目录下创建一个新文件对象File newFile = new File(desc, src.getName());// 如果目标文件不存在,则创建一个目标文件if (!newFile.exists()) {try {// 创建一个新文件newFile.createNewFile();} catch (IOException e) {e.printStackTrace();}}// 文件复制输入流FileCopyInputStream input = new FileCopyInputStream();// 读文件ArrayList<DataBuffer> aList = input.read(src, false);// 文件复制输出流FileCopyOutputStream output = new FileCopyOutputStream();// 写文件output.write(newFile, aList);}}</span>

2. ObjectInputStream与ObjectOutputStream:对对象进行的读写操作,一般是将对象保存在文件中。

一个模拟数据库的列子:

此时需要注意:ObjectOutputStream的构造器会向输出流中写入头信息,因此在向文件中追加数据时,每一次都会写入头信息。

一种处理方式是自定义一个类,继承自ObjectOutputStream,重写writeStreamHeader()方法,该方法什么都不做,就不会再写入头信息。

自定义类,继承自ObjectOutputStream:

<span style="font-family:Microsoft YaHei;">public class DBObjectOutputStream extends ObjectOutputStream {public DBObjectOutputStream() throws IOException, SecurityException {}public DBObjectOutputStream(OutputStream out) throws IOException {super(out);}/** * 写流的头信息 */@Overrideprotected void writeStreamHeader() throws IOException {// 不实现该方法,则不会写入文件头信息return;}}</span>
向文件中写入数据:
<span style="font-family:Microsoft YaHei;">public class DBOutputStream<T> {/** * 向指定文件写入数据 *  * @param t *            泛型对象 * @param file *            目标文件 */public void write(T t, File file) {// 创建一个FileOutputStream对象FileOutputStream fos = null;// 创建一个ObjectOutputStream对象ObjectOutputStream oos = null;try {// 初始化FileOutputStream对象,append参数为truefos = new FileOutputStream(file, true);// 检测文件是否存在,若不存在,则创建文件if (!file.exists()) {// 创建新文件file.createNewFile();}// 检测文件大小,确定是否是第一次操作文件if (file.length() < 1) {// 第一次操作文件。由于ObjectOutputStream每次都会向文件中写入文件头信息,// 因此只在第一次操作文件时使用oos = new ObjectOutputStream(fos);} else {// 不是第一次操作文件,则使用自己定义的DBObjectOutputStreamoos = new DBObjectOutputStream(fos);}// 向文件中写入对象oos.writeObject(t);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 若oos不为空,则关闭该输出流if (oos != null) {// 刷新流缓冲oos.flush();// 关闭流oos.close();}} catch (IOException e) {e.printStackTrace();}}}}</span>
从文件中读取数据:

<span style="font-family:Microsoft YaHei;">public class DBInputStream {/** * 从指定文件中读取数据 *  * @param file *            指定文件 * @return ArrayList<Object> 读取的结果 */public ArrayList<Object> read(File file) {// 创建一个FileInputStream对象FileInputStream fis = null;// 创建一个ObjectInputStream对象ObjectInputStream ois = null;// 创建一个ArrayList<Object>ArrayList<Object> aList = new ArrayList<>();// 创建一个Object对象Object object = null;try {// 判断文件是否存在if (!file.exists()) {return null;}// 初始化FileInputStream对象fis = new FileInputStream(file);// 初始化ObjectInputStream对象ois = new ObjectInputStream(fis);// 死循环读取文件内容,当抛出EOFException异常时,表示已经读至文件结尾while (true) {// 从文件里读对象object = ois.readObject();// 将对象放入ArrayList<Object>中aList.add(object);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (EOFException e) {// TODO: handle exception} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {try {// 若ois不为空,关闭输入流if (ois != null) {// 关闭流ois.close();}} catch (IOException e) {e.printStackTrace();}}// 返回ObjectInputStream读出的结果return aList;}}</span>

dao类:

<span style="font-family:Microsoft YaHei;">public class StudnetInfoDAO {// 接受控制台的输入信息Scanner scanner = new Scanner(System.in);// 保存学生对象的文件File studentFile = new File("src/com/wzd/dbimitate/resource/student.obj");// 保存课程对象的文件File courseFile = new File("src/com/wzd/dbimitate/resource/course.obj");// 保存成绩对象的文件File gradeFile = new File("src/com/wzd/dbimitate/resource/grade.obj");// ArrayList<Object>,保存DBInputStream读出的数据ArrayList<Object> objects = new ArrayList<>();// DBInputStream,从指定文件中读取数据DBInputStream dbis = new DBInputStream();/** * 添加学生信息 */public void insertIntoStudent() {// 提示输入格式System.out.println("请输入学生信息(学生姓名,学生学号,学生电话):");// 接收输入的信息String str = scanner.next().trim();// 分解字符串String[] strs = str.split(",");// 创建一个Student对象,并赋值Student student = new Student();student.setName(strs[0]);student.setNumber(strs[1]);student.setPhone(strs[2]);// DBOutputStream<Student>输出流DBOutputStream<Student> dbos = new DBOutputStream<>();// 向学生文件中写数据dbos.write(student, studentFile);}/** * 添加课程信息 */public void insertIntoCourse() {// 提示输入格式System.out.println("请输入课程信息(课程名,课程号):");// 接收输入的信息String str = scanner.next().trim();// 分解字符串String[] strs = str.split(",");// 创建一个Course对象,并赋值Course course = new Course();course.setName(strs[0]);course.setNumber(strs[1]);// DBOutputStream<Course>输出流DBOutputStream<Course> dbos = new DBOutputStream<>();// 向课程文件中写数据dbos.write(course, courseFile);}/** * 添加成绩信息 */public void insertIntoGrade() {// 提示输入格式System.out.println("请输入成绩信息(学生学号,课程号,成绩):");// 接收输入的信息String str = scanner.next().trim();// 分解字符串String[] strs = str.split(",");// 创建一个Grade对象,并赋值Grade grade = new Grade();grade.setStudentNumber(strs[0]);grade.setCourseNumber(strs[1]);grade.setGrade(Double.parseDouble(strs[2]));// DBOutputStream<Grade>输出流DBOutputStream<Grade> dbos = new DBOutputStream<>();// 向成绩文件中写数据dbos.write(grade, gradeFile);}/** * 通过学生姓名查询到所有的成绩信息 */public void selectGrade() {// 提示输入信息System.out.println("请输入学生姓名:");// 接收输入的信息String studentName = scanner.next().trim();// 查询学生信息Student student = selectStudentInfo(studentName);// 查询成绩信息ArrayList<Grade> grades = selectGradeInfo(student.getNumber());// 创建一个课程对象数组Course[] course = new Course[grades.size()];// 遍历ArrayList<Grade>for (int i = 0; i < grades.size(); i++) {// 查询课程信息course[i] = selectCourseInfo(grades.get(i).getCourseNumber());}// 打印头信息System.out.println("学生姓名\t\t课程名\t\t分数");// 遍历for (int i = 0; i < grades.size(); i++) {// 打印最终结果System.out.println(student.getName() + "\t\t" + course[i].getName()+ "\t\t" + grades.get(i).getGrade());}}/** * 通过学生姓名查询到所有的考试科目 */public void selectCourse() {// 提示输入信息System.out.println("请输入学生姓名:");// 接收输入的信息String studentName = scanner.next().trim();// 查询学生信息Student student = selectStudentInfo(studentName);// 查询成绩信息ArrayList<Grade> grades = selectGradeInfo(student.getNumber());// 创建一个课程对象数组Course[] course = new Course[grades.size()];// 遍历ArrayList<Grade>for (int i = 0; i < grades.size(); i++) {// 查询课程信息course[i] = selectCourseInfo(grades.get(i).getCourseNumber());}// 打印头信息System.out.println("学生姓名\t\t考试科目");// 遍历for (int i = 0; i < course.length; i++) {// 打印最终结果System.out.println(student.getName() + "\t\t" + course[i].getName());}}/** * 通过学生姓名获取学生信息 */public void selectStudent() {// 提示输入信息System.out.println("请输入学生姓名:");// 接收输入的信息String studentName = scanner.next().trim();// 查询学生信息Student student = selectStudentInfo(studentName);// 打印头信息System.out.println("学生姓名\t\t学号\t\t电话号码");// 打印最终结果System.out.println(student.getName() + "\t\t" + student.getNumber()+ "\t\t" + student.getPhone());}/** * 通过课程号查询课程信息 *  * @param courseNumber *            课程号 * @return 课程对象 */private Course selectCourseInfo(String courseNumber) {// 创建一个Course对象Course course = null;// 从课程文件中读取数据objects = dbis.read(courseFile);// 遍历读取结果for (Object object : objects) {// 转换为Course对象course = (Course) object;// 若匹配if (courseNumber.equals(course.getNumber())) {// 返回课程对象return course;}}// 返回空return null;}/** * 通过学号查询成绩信息 *  * @param studentNumber *            学号 * @return ArrayList<Grade> 成绩信息 */private ArrayList<Grade> selectGradeInfo(String studentNumber) {// 创建一个Grade对象Grade grade = null;// 创建一个ArrayList<Grade>ArrayList<Grade> grades = new ArrayList<>();// 从成绩文件中读取数据objects = dbis.read(gradeFile);// 遍历读取结果for (Object object : objects) {// 转换为Grade对象grade = (Grade) object;// 若匹配if (studentNumber.equals(grade.getStudentNumber())) {// 将Grade对象添加到ArrayList<Grade>中grades.add(grade);}}// 返回结果return grades;}/** * 通过学生姓名查询学生信息 *  * @param studentName *            学生姓名 * @return 学生对象 */private Student selectStudentInfo(String studentName) {// 创建一个Student对象Student student = new Student();// 从学生文件中读取数据objects = dbis.read(studentFile);// 遍历读取结果for (Object object : objects) {// 转换为Student对象student = (Student) object;// 若匹配if (studentName.equals(student.getName())) {// 返回Student对象return student;}}// 返回空return null;}}</span>
测试类:

<span style="font-family:Microsoft YaHei;">public class DBImitateTest {public static void main(String[] args) {// 创建一个StudnetInfoDAO对象StudnetInfoDAO dao = new StudnetInfoDAO();// 1.可以使用命令 存入学生成绩: 学生学号,学生姓名,学生成绩,科目,学生电话// 添加学生信息for (int i = 0; i < 5; i++) {dao.insertIntoStudent();}// 添加课程信息for (int i = 0; i < 4; i++) {dao.insertIntoCourse();}// 添加成绩信息for (int i = 0; i < 9; i++) {dao.insertIntoGrade();}// 2.可以通过学生姓名查询到所有的成绩信息dao.selectGrade();// 3.可以通过学生姓名查询到所有的考试科目dao.selectCourse();// 4.可以通过学生姓名获取学生信息dao.selectStudent();}}</span>

3. BufferedInputStream与BufferedOutputStream:缓冲流,里面包装其他的输入输出流,以提高读写的效率,其中BufferedInputStream支持mark和reset的使用。

示列如下:

<span style="font-family:Microsoft YaHei;">public class BufferedInputStreamTest {public static void main(String[] args) {//try {BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/com/wzd/test/dec22/ReaderTest.java"));// 判断该流是否可读if(bis.available() > 0) {// 判断该流是否可以被markif(bis.markSupported()) {// mark一下,做一个标记,参数在此时没有使用,只要填写一个int值就行// mark在一个流中只有一个有效,后面下的mark会覆盖掉前面的System.out.print((char)bis.read());System.out.println((char)bis.read());bis.mark(0);System.out.print((char)bis.read());System.out.println((char)bis.read());// 回到mark标记处bis.reset();System.out.print((char)bis.read());System.out.println((char)bis.read());}}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}</span>


4. DataInputStream与DataOutputStream:对java基本数据类型进行读写操作。


字符流:(字符流的操作与字节流基本类似)

1. FileReader与FileWriter:以字符的形式对文件进行读写操作。


2. BufferedReader与BufferedWriter:缓冲字符流。


3. InputStreamReader与OutputStreamWriter:

InputStreamReader是字节流通向字符流的桥梁:它使用charset读取字节并将其解码为字符。

OutputStreamWriter是字符流通向字节流的桥梁:可以使用指定的charset将要写入流中的字符编码成字节。

0 0