JAVA之旅(三十)——打印流PrintWriter,合并流,切割文件并且合并,对象的序列化Serializable,管道流,RandomAccessFile,IO其他类,字符编码


三十篇了,又是一个阳光明媚的周末,一个又一个的周末,周而复始,不断学习,前方的路你可曾看见?随我一起走进技术的世界,流连忘返吧!

一.打印流PrintWriter

打印流有PrintWriter和PrintStream,他的特点可以直接操作输入流还有文件

  • 该流提供了打印方法,可以将各种数据类型原样打印

    • file对象 File
    • 字符串路径 String
    • 字节打印流
    • 字符打印流

我们演示一遍大家就对此有所了解了

  1. package com.lgl.hellojava;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.io.PrintWriter;
  6. public class HelloJJAVA {
  7. public static void main(String[] args) {
  8. try {
  9. BufferedReader bufr = new BufferedReader(new InputStreamReader(
  10. System.in));
  11. PrintWriter oWriter = new PrintWriter(System.out, true);
  12. String line = null;
  13. while ((line = bufr.readLine()) != null) {
  14. if (line.equals("over")) {
  15. break;
  16. }
  17. oWriter.write(line);
  18. }
  19. oWriter.close();
  20. bufr.close();
  21. } catch (IOException e) {
  22. // TODO Auto-generated catch block
  23. e.printStackTrace();
  24. }
  25. }
  26. }

要想存到文件里,也是可以直接把文件给放进去的

二.合并流

我们来看看什么是合并流,在API文档上说,他可以串联流

  1. package com.lgl.hellojava;
  2. import java.io.FileInputStream;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.SequenceInputStream;
  7. import java.util.Enumeration;
  8. import java.util.Vector;
  9. public class HelloJJAVA {
  10. public static void main(String[] args) {
  11. try {
  12. Vector<FileInputStream> v = new Vector<FileInputStream>();
  13. v.add(new FileInputStream("1.txt"));
  14. v.add(new FileInputStream("2.txt"));
  15. Enumeration<FileInputStream> elements = v.elements();
  16. SequenceInputStream sis = new SequenceInputStream(elements);
  17. FileOutputStream fos = new FileOutputStream("3.txt");
  18. byte[] buf = new byte[1024];
  19. int len = 0;
  20. while ((len = sis.read(buf)) != -1) {
  21. fos.write(buf, 0, len);
  22. }
  23. fos.close();
  24. sis.close();
  25. } catch (FileNotFoundException e) {
  26. // TODO Auto-generated catch block
  27. e.printStackTrace();
  28. } catch (IOException e) {
  29. // TODO Auto-generated catch block
  30. e.printStackTrace();
  31. }
  32. }
  33. }

把1.txt和2.txt乃至add更多的内容合并到3.txt文件中,这就是流的合并

三.切割文件

合并文件可以,那肯定可以切割了,我们来看下具体是怎么去制作的

  1. // 切割文件
  2. public static void splitFile() {
  3. try {
  4. FileInputStream fis = new FileInputStream("1.jpg");
  5. FileOutputStream fos = null;
  6. byte[] buf = new byte[1024 * 1024];
  7. int len = 0;
  8. int count = 1;
  9. while ((len = fis.read(buf)) != -1) {
  10. fos = new FileOutputStream((count++) + ".patch");
  11. fos.write(buf, 0, len);
  12. fos.close();
  13. }
  14. fis.close();
  15. } catch (FileNotFoundException e) {
  16. // TODO Auto-generated catch block
  17. e.printStackTrace();
  18. } catch (IOException e) {
  19. // TODO Auto-generated catch block
  20. e.printStackTrace();
  21. }
  22. }

当运行结束之后,我们可以看到

已经成功切割了

切割完我们可以合并了

  1. // 合并文件
  2. public static void merge() {
  3. ArrayList<FileInputStream> al = new ArrayList<>();
  4. for (int i = 1; i <= 2; i++) {
  5. try {
  6. al.add(new FileInputStream(i + ".patch"));
  7. } catch (FileNotFoundException e) {
  8. // TODO Auto-generated catch block
  9. e.printStackTrace();
  10. }
  11. }
  12. Iterator<FileInputStream> iterator = al.iterator();
  13. Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {
  14. @Override
  15. public boolean hasMoreElements() {
  16. // TODO Auto-generated method stub
  17. return iterator.hasNext();
  18. }
  19. @Override
  20. public FileInputStream nextElement() {
  21. // TODO Auto-generated method stub
  22. return iterator.next();
  23. }
  24. };
  25. try {
  26. SequenceInputStream seq = new SequenceInputStream(en);
  27. FileOutputStream fos = new FileOutputStream("2.jpg");
  28. byte[] buf = new byte[1024];
  29. int len = 0;
  30. while ((len = seq.read(buf)) != -1) {
  31. fos.write(buf, 0, len);
  32. }
  33. fos.close();
  34. seq.close();
  35. } catch (FileNotFoundException e) {
  36. // TODO Auto-generated catch block
  37. e.printStackTrace();
  38. } catch (IOException e) {
  39. // TODO Auto-generated catch block
  40. e.printStackTrace();
  41. }
  42. }

这样我们就把图片拷贝出来了,可以看到

这段代码是非常帮的,我们一定会用到的,希望能用的上

四.对象的序列化Serializable

其实就是可以直接操作对象的流,他会实现一个Serializable()接口,我们用代码来看下他是怎么用的,我们直接写读取对象的类了

  1. package com.lgl.hellojava;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectInputStream;
  6. import java.io.ObjectOutputStream;
  7. import java.io.Serializable;
  8. public class HelloJJAVA {
  9. public static void main(String[] args) {
  10. // writeObj();
  11. readObj();
  12. }
  13. private static void readObj() {
  14. try {
  15. ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
  16. "obj.txt"));
  17. Person p = (Person) ois.readObject();
  18. System.out.println(p);
  19. ois.close();
  20. } catch (IOException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. } catch (ClassNotFoundException e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. }
  27. }
  28. private static void writeObj() {
  29. try {
  30. ObjectOutputStream oos = new ObjectOutputStream(
  31. new FileOutputStream("obj.txt"));
  32. oos.writeObject(new Person("zhangsan", 20));
  33. oos.close();
  34. } catch (IOException e) {
  35. // TODO Auto-generated catch block
  36. e.printStackTrace();
  37. }
  38. }
  39. }
  40. class Person implements Serializable {
  41. String name;
  42. int age;
  43. public Person(String name, int age) {
  44. this.name = name;
  45. this.age = age;
  46. }
  47. }

OK,自己去验证一下

五.管道流

输入输出可以直接进行连接,通常结合线程使用

  1. package com.lgl.hellojava;
  2. import java.io.IOException;
  3. import java.io.PipedInputStream;
  4. import java.io.PipedOutputStream;
  5. public class HelloJJAVA {
  6. public static void main(String[] args) {
  7. PipedInputStream pi = new PipedInputStream();
  8. PipedOutputStream po = new PipedOutputStream();
  9. try {
  10. pi.connect(po);
  11. } catch (IOException e) {
  12. // TODO Auto-generated catch block
  13. e.printStackTrace();
  14. }
  15. Read read = new Read(pi);
  16. Write write = new Write(po);
  17. new Thread(read).start();
  18. new Thread(write).start();
  19. }
  20. }
  21. class Read implements Runnable {
  22. private PipedInputStream in;
  23. public Read(PipedInputStream in) {
  24. this.in = in;
  25. }
  26. @Override
  27. public void run() {
  28. try {
  29. byte[] buf = new byte[1024];
  30. int len = in.read(buf);
  31. String s = new String(buf, 0, len);
  32. System.out.println(s);
  33. in.close();
  34. } catch (IOException e) {
  35. // TODO Auto-generated catch block
  36. e.printStackTrace();
  37. }
  38. }
  39. }
  40. class Write implements Runnable {
  41. private PipedOutputStream out;
  42. public Write(PipedOutputStream out) {
  43. this.out = out;
  44. }
  45. @Override
  46. public void run() {
  47. try {
  48. out.write("yes".getBytes());
  49. out.close();
  50. } catch (IOException e) {
  51. // TODO Auto-generated catch block
  52. e.printStackTrace();
  53. }
  54. }
  55. }

现在就可以联通了

六.RandomAccessFile

这是一个很特别的家伙,他继承的是Object

  • 该类不是IO体系中的子类
  • 但是他是IO包中的成员,他同时具备读写功能
  • 内部封装了一个数组,而且通过指针对数组中的元素进行操作
  • 可以通过getFilePointer或者指针位置同时可以通过seek改变指针的位置

其实完成读写的原理就是内部封装了字节输入,输出流,通过构造函数可以看出该类具备操作文件的能力,而且操作文件还有模式

  1. package com.lgl.hellojava;
  2. import java.io.FileNotFoundException;
  3. import java.io.IOException;
  4. import java.io.RandomAccessFile;
  5. public class HelloJJAVA {
  6. public static void main(String[] args) {
  7. writeFile();
  8. }
  9. public static void writeFile() {
  10. try {
  11. RandomAccessFile raf = new RandomAccessFile("1.txt", "rw");
  12. raf.write("zhangssan".getBytes());
  13. raf.writeInt(99);
  14. raf.close();
  15. } catch (FileNotFoundException e) {
  16. // TODO Auto-generated catch block
  17. e.printStackTrace();
  18. } catch (IOException e) {
  19. // TODO Auto-generated catch block
  20. e.printStackTrace();
  21. }
  22. }
  23. }

这只是一个写的过程,我们的特性还没有体现出来,我们来看下他是怎么读的

  1. private static void ReadFile() {
  2. try {
  3. RandomAccessFile raf = new RandomAccessFile("1.txt", "r");
  4. // 调整对象指针
  5. raf.seek(8 * 0);
  6. byte[] buf = new byte[1024];
  7. raf.read(buf);
  8. String s = new String(buf);
  9. System.out.println(s);
  10. raf.close();
  11. } catch (FileNotFoundException e) {
  12. // TODO Auto-generated catch block
  13. e.printStackTrace();
  14. } catch (IOException e) {
  15. // TODO Auto-generated catch block
  16. e.printStackTrace();
  17. }
  18. }

如果操作的文件不存在,就会自动创建,如果存在,直接覆盖

七.IO其他类

IO其他包里,还有一些其他的使用

  • 操作基本数据类型
  • 字节数组
  • 字符数组

1.基本数据类型

我们先来看下基本数据类型的,我直接读写都写出来

  1. public static void readData() {
  2. try {
  3. DataInputStream dis = new DataInputStream(new FileInputStream(
  4. "data.txt"));
  5. int num = dis.readInt();
  6. boolean d = dis.readBoolean();
  7. System.out.println(num + "" + d + "");
  8. dis.close();
  9. } catch (FileNotFoundException e) {
  10. // TODO Auto-generated catch block
  11. e.printStackTrace();
  12. } catch (IOException e) {
  13. // TODO Auto-generated catch block
  14. e.printStackTrace();
  15. }
  16. }
  17. // 基本数据类型
  18. public static void writeDatea() {
  19. try {
  20. DataOutputStream dos = new DataOutputStream(new FileOutputStream(
  21. "data.txt"));
  22. dos.writeInt(55);
  23. dos.writeBoolean(true);
  24. dos.close();
  25. } catch (FileNotFoundException e) {
  26. // TODO Auto-generated catch block
  27. e.printStackTrace();
  28. } catch (IOException e) {
  29. // TODO Auto-generated catch block
  30. e.printStackTrace();
  31. }
  32. }

读取基本数据类型

二.字节数组

这个偶尔用下,但是我们还是要去学习一下的

  • ByteArrayInputStream: 在构造的时候,需要接收数据源,而且数据源是一个字节数组

  • ByteArrayOutputStream:在构造的时候,不用定义数据的目的,因为该对象中已经内部封装了可变程度的字节数组

因为这两个流的对象都操作的数组,并且没有使用系统资源,所以,不用进行close关闭!

  1. package com.lgl.hellojava;
  2. import java.io.ByteArrayInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. public class HelloJJAVA {
  5. public static void main(String[] args) {
  6. // 数据源
  7. ByteArrayInputStream bis = new ByteArrayInputStream("123".getBytes());
  8. // 数据目的
  9. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  10. int ch = 0;
  11. while ((ch = bis.read()) != -1) {
  12. bos.write(ch);
  13. }
  14. System.out.println(bos.size());
  15. System.out.println(bos.toString());
  16. }
  17. }

是不是比较简单,字符流我就不说了,和字节流是类似的,但是他会衍生出一个新的内容就是字符编码

八.字符编码

这些乱七八糟的编码说真的,东西还是挺多的,但是我并不想讲那么多,因为本身我也不是很清楚,其次这玩意大致的知道一点就可以了(个人觉得),什么ASCLL,GBK,UTF-8之类的

  1. String s = "hello java";
  2. byte [] b1 = s.getBytes();
  3. System.out.println(Arrays.toString(b1));

他得到的是什么?

现在我换一个编码

  1. byte [] b1 = s.getBytes("GBK");

我设置成GBK,他的值是一样的,说明默认的是GBK

九.练习

写完这个练习,我们的I/O流就GG了,感慨颇多,写I/O写了很多篇,但是仍然晕乎乎的,应该继续加深印象的,我们来看下需求

  • 有五个学生,每个学生有三门课程,从键盘输入以下数据(包括姓名,三门课成绩),输入的格式,如zhangsan,30,60,96计算出总成绩,并把学生的信息和计算出的总分数高低顺序存入文件student.txt中去;

好了,开始撸代码了

  1. package com.lgl.hellojava;
  2. import java.io.BufferedReader;
  3. import java.io.BufferedWriter;
  4. import java.io.FileWriter;
  5. import java.io.IOException;
  6. import java.io.InputStreamReader;
  7. import java.util.Set;
  8. import java.util.TreeSet;
  9. public class HelloJJAVA {
  10. public static void main(String[] args) {
  11. /**
  12. * 逻辑:
  13. * 1.通过获取键盘录入一行数据,然后取出数据封装成学生对象
  14. * 2.需要从高到低排列,需要排序,使用集合TreeSet就可以了
  15. * 3.写入文件
  16. */
  17. try {
  18. Set<Student> stus = StudentInfoTool.getStudents();
  19. StudentInfoTool.writeFile(stus);
  20. } catch (IOException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. // 比较数据,Comparable接口
  27. class Student implements Comparable<Student> {
  28. // 姓名
  29. private String name;
  30. // 三科分数
  31. private int n1, n2, n3;
  32. // 总分
  33. private int sum;
  34. // 构造函数
  35. public Student(String name, int n1, int n2, int n3) {
  36. this.name = name;
  37. this.n1 = n1;
  38. this.n2 = n2;
  39. this.n3 = n3;
  40. sum = n1 + n2 + n3;
  41. }
  42. public String getName() {
  43. return name;
  44. }
  45. public void setName(String name) {
  46. this.name = name;
  47. }
  48. public int getSum() {
  49. return sum;
  50. }
  51. public void setSum(int sum) {
  52. this.sum = sum;
  53. }
  54. @Override
  55. public int compareTo(Student o) {
  56. int num = new Integer(this.sum).compareTo(new Integer(o.sum));
  57. if (num == 0) {
  58. return this.name.compareTo(o.name);
  59. }
  60. return num;
  61. }
  62. @Override
  63. public int hashCode() {
  64. // TODO Auto-generated method stub
  65. return name.hashCode() + sum * 78;
  66. }
  67. @Override
  68. public boolean equals(Object obj) {
  69. if (!(obj instanceof Student)) {
  70. throw new ClassCastException("Type Error");
  71. }
  72. Student s = (Student) obj;
  73. return this.name.equals(s.name) && this.sum == s.sum;
  74. }
  75. }
  76. // 工具类
  77. class StudentInfoTool {
  78. public static Set<Student> getStudents() throws IOException {
  79. BufferedReader bufr = new BufferedReader(new InputStreamReader(
  80. System.in));
  81. String line = null;
  82. // 集合
  83. Set<Student> stus = new TreeSet<>();
  84. while ((line = bufr.readLine()) != null) {
  85. if (line.equals("over")) {
  86. break;
  87. }
  88. String[] info = line.split(",");
  89. Student student = new Student(info[0], Integer.parseInt(info[1]),
  90. Integer.parseInt(info[2]), Integer.parseInt(info[3]));
  91. stus.add(student);
  92. }
  93. bufr.close();
  94. return stus;
  95. }
  96. // 写入文件
  97. public static void writeFile(Set<Student> stus) {
  98. try {
  99. BufferedWriter bufw = new BufferedWriter(new FileWriter(
  100. "student.txt"));
  101. for (Student stu : stus) {
  102. bufw.write(stu.getName());
  103. bufw.write(stu.getSum() + "");
  104. bufw.newLine();
  105. bufw.flush();
  106. }
  107. bufw.close();
  108. } catch (IOException e) {
  109. // TODO Auto-generated catch block
  110. e.printStackTrace();
  111. }
  112. }
  113. }

输出的结果,可以看到

总数,从小到大,如果你想从高到低的话,自己去实现下排序,看看你们学的怎么样了

好的,我们本篇到这里就结束了,这篇也是憋了挺久的才别出来的,终于把IO写完了

有兴趣的可以加群:555974449

JAVA之旅(三十)——打印流PrintWriter,合并流,切割文件并且合并,对象的序列化Serializable,管道流,RandomAccessFile,IO其他类,字符编码的更多相关文章

  1. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

  2. Java基础---Java---IO流-----对象的序列化、管道流、RandomAccessFile、数据类型的流对象DataStream、ByteArrayStream

    ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化. ObjectOutputStream 和 ObjectInputStream ...

  3. JAVA学习第三十二课(经常使用对象API)- 基本数据类型对象包装类

    将基本数据类型(8种:int..)封装成对象的优点就是能够在对象中封装很多其它的功能和方法来操控该数据 常见的操作就是:用于基本数据类型与字符串之间的转换 基本数据类型对象包装类一般用于基本类型和字符 ...

  4. JAVA之旅(十九)——ListIterator列表迭代器,List的三个子类对象,Vector的枚举,LinkedList,ArrayList和LinkedList的小练习

    JAVA之旅(十九)--ListIterator列表迭代器,List的三个子类对象,Vector的枚举,LinkedList,ArrayList和LinkedList的小练习 关于数据结构,所讲的知识 ...

  5. JAVA之旅(十八)——基本数据类型的对象包装类,集合框架,数据结构,Collection,ArrayList,迭代器Iterator,List的使用

    JAVA之旅(十八)--基本数据类型的对象包装类,集合框架,数据结构,Collection,ArrayList,迭代器Iterator,List的使用 JAVA把完事万物都定义为对象,而我们想使用数据 ...

  6. JAVA之旅(十)——异常的概述,Try-Catch,异常声明Throws,多异常处理,自定义异常,Throw和Throws的区别

    JAVA之旅(十)--异常的概述,Try-Catch,异常声明Throws,多异常处理,自定义异常,Throw和Throws的区别 不知不觉,JAVA之旅这个系列已经更新到第十篇了,感觉如梦如幻,时间 ...

  7. JAVA之旅(十五)——多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止

    JAVA之旅(十五)--多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止 我们接着多线程讲 一.生产者和消费者 什么是生产者和消费者?我们 ...

  8. JAVA之旅(十二)——Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口

    JAVA之旅(十二)--Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口 开始挑战一些难度了,线程和I/O方面的操作了,继续坚持 一. ...

  9. Java开发学习(三十六)----SpringBoot三种配置文件解析

    一. 配置文件格式 我们现在启动服务器默认的端口号是 8080,访问路径可以书写为 http://localhost:8080/books/1 在线上环境我们还是希望将端口号改为 80,这样在访问的时 ...

随机推荐

  1. k-d树模板(BZOJ2648)

    实现了插入一个点,查询距某个位置的最近点. #include <cstdio> #include <algorithm> using namespace std; , inf ...

  2. php中sql语句常见错误

    .php文件中sql语句的写法导致的错误如下: 1.$logSql="select * from jd_login where uname=".$u."and upwd= ...

  3. C语言程序设计第二次作业——

    1,编译过程过程中的错误缺引号和分号并且拼写错误. 正确结果: 2,编译过程 改正错误: 正确结果: 3,利用SIZEOF运算符求出的数据类型所占字节大小: 4,在头文件LIMITS.H中相关的编译 ...

  4. 移动端开发,文字增加,字体自动放大(font boosting)

    问题缘由:做文章详情页的时候,文字多了一点字体就放大了,真的是奇了怪了. 问题重现 一段文字的时候 两段文字的时候 很明显,字体放大了很多. 疑点 meta标签缩放的问题 最近正好遇到处理retain ...

  5. JS中怎样判断undefined(比较不错的方法)

    最近做项目碰到的问题.拿出来跟大家分享一下吧. 用servlet赋值给html页面文本框值后,用alert来弹出这个值.结果显示"undefined".所以我就自然的用这个值和字符 ...

  6. CSS中的ul与li样式详解 list-type

    转自新浪博客http://blog.sina.com.cn/u/2539885750 ul和li列表是使用CSS布局页面时常用的元素.在CSS中,有专门控制列表表现的属性,常用的有list-style ...

  7. VMware在宿主上没有VMnet0、VMnet8,解决方法

    一开始,坐着上机实验,一直搞不通为什么虚拟机上的客户机可以ping通自己的ip也可以ping通自己本身的ip,但是主机ping不通虚拟机的客户机,也ping不通虚拟机的网关. 尝试了各种问题,也追出了 ...

  8. 数据结构Java版之交换算法(一)

    交换的本质是拷贝,其中拷贝包括两种方式.值拷贝和指针拷贝,在java中没有指针,为此,我们可以理解为地址拷贝,在我看来,指针就是地址. 1.传值方式示例: 由上述示例可得,传值,不能起到交换的作用,原 ...

  9. RX系列三 | RxJava | create | from | interval | just | range | filter

    RX系列三 | RxJava | create | from | interval | just | range | filter 我们在第一篇里有说过一些基本的关系,现在我们需要用到一些依赖,这里记 ...

  10. ngx.ctx

    https://github.com/openresty/lua-nginx-module#ngxctx 要点 生命周期和请求一致 每个请求的ngx.ctx是相互独立的,包括ngx.location. ...