IO(Input Output)

 黑马程序员

 

 

 1.   IO流概念

   IO流用来处理设备之间的数据传输

    Java对数据的操作是通过流的方式

    Java用于操作流的对象都在IO包中

    流按流向分为两种:输入流,输出流。

    流按操作类型分为两种:字节流与字符流。  字节流可以操作任何数据,字符流只能操作纯字符数据,比较方便。

 

 

 2.   IO流常用基类

        字节流的抽象基类:

    InputStream ,OutputStream

        字符流的抽象基类:

    Reader , Writer

         由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。

    如:InputStream的子类FileInputStream。 

    如:Reader的子类FileReader。

注意: InputStreamReader 是字符流, 可以从字节流中读取字符

 


import java.io.FileWriter;
import java.io.IOException;

public class WriterDemo {

 public static void main(String[] args) throws IOException {
  FileWriter fw = new FileWriter("dest.txt", true);  // 文件不存在时创建, 存在则清空
  fw.write("向文件中添加内容\r\n");
  fw.close();
 }

}

 

import java.io.FileReader;
import java.io.IOException;

public class ReaderDemo {

 public static void main(String[] args) throws IOException {
  FileReader fr = new FileReader("test.txt");
  int c;
  while ((c = fr.read()) != -1)
   System.out.print((char) c);
  fr.close();
 }

}

 

 

 3.   IO程序书写

    使用前,导入IO包中的类

    使用时,进行IO异常处理

    使用后,释放资源

 

import java.io.*;

class  FileWriterDemo
{
 public static void main(String[] args) throws IOException
 {
  /*
  需求:通过字符写入流将数据写入到一个文件中。
    使用FileWriter对象完成。
  该对象一创建就必须明确数据要存放位置。
  */
  //创建FileWriter对象。在堆内存中定义了一个对象实例。
  //同时调用了系统资源,在执行位置创建了一个文件。用于存储数据。
  /*
  当指定目录下已有该文件,会被覆盖。

  如果构造函数中传入true,那么可完成对已有文件数据续写。
  */

  FileWriter fw = new FileWriter("a.txt",true);

  //使用Writer中的write方法,写入数据。
  //将数据写入到了流中。

  fw.write("\r\nhello");

  //close()用于关闭资源,但在关闭前,会先刷新缓冲区,将缓冲区中的数据刷到目的地。
  fw.close();
  //刷新缓冲区。flush
  /*fw.flush();

  fw.write("kkkkk");
  fw.flush();

  //关闭资源。
  fw.close();

  fw.write("haha");
  */

 

  
 }
}

 

 

 

 4.   字符流读写文件

       读取文件

    定义字符流关联指定文件

FileReader reader = new FileReader("Test.txt");

   读取一个字符,返回int,该字符的码表值

int ch = reader.read();

    关闭流,释放资源

reader.close();

 

import java.io.*;

class FileReaderDemo
{
 public static void main(String[] args) throws IOException
 {

  //创建字符读取流对象,并关联指定文件数据。
  FileReader fr = new FileReader("a.txt");
  
  

  int ch = 0;

   
  while((ch=fr.read())!=-1)
  {

   System.out.println((char)ch);
  }

  fr.close();

 

 }
}

 

 

    定义字符输出流关联指定文件

FileWriter writer = new FileWriter("Test.txt");

   写出一个字符,接收int码表值

writer.write(97);

    关闭流,释放资源

writer.close();

         注意事项

    文件路径

定义文件路径时Windows中的目录符号为“\”,但这个符号在Java中是特殊字符,需要转义。

       可以用“\\”或“/”表示。

   读取文件

读取文件时必须保证文件存在,否则将抛出FileNotFoundException。

    写出文件

写出时文件如不存在时程序会创建新文件,如文件已存在则会清空原文件内容重新写入。

如需追加内容可调用FileWriter构造函数FileWriter(String fileName, boolean append)

 

import java.io.FileWriter;
import java.io.IOException;

public class WriterDemo {

 public static void main(String[] args) throws IOException {
  FileWriter fw = new FileWriter("dest.txt", true);  // 文件不存在时创建, 存在则清空
  fw.write("向文件中添加内容\r\n");
  fw.close();
 }

}

 

 

 

 5.   字符流缓冲区读写

       自定义缓冲区读写

    为什么定义缓冲区

由于单个字符读写需要频繁操作文件,所以效率非常低。

我们可以定义缓冲区将要读取或写出的数据缓存,减少操作文件次数。

   缓冲区读取

先定义一个数组,然后调用FileReader读取一个数组的方法。

int read(char[] cbuf)

    缓冲区写出

将要写出的数据存放在数组中,调用FileWriter方法,一次写出一个数组。

void write(char[] cbuf, int off, int len)

       内置缓冲区的BufferedReader和BufferedWriter

    Java提供了带缓冲功能的Reader和Writer类:BufferedReader,BufferedWriter

    这两个类都是提供包装功能,需要提供其他流来使用,给其他流增加缓冲功能

    当我们调用BufferedReader读取数据时,程序会从文件中一次读取8192个字符用来缓冲

    当我们调用BufferedWriter写出数据时,程序会先将数据写出到缓冲数组,直到写满8192个才一次性刷出到文件

 

 

import java.io.IOException;
import java.io.Writer;

public class MyBufferedWriter extends Writer {
 private Writer writer;
 private char[] buffer = new char[8192];
 private int len;

 public MyBufferedWriter(Writer writer) {
  this.writer = writer;
 }

 /*
  * 判断缓冲区是否写满, 如果写满则将缓冲区数据写出.
  * 如果缓冲区没有写满, 就先写到缓冲区中
  */
 public void write(int c) throws IOException {
  if (len == buffer.length)
   flush();
  buffer[len++] = (char) c;
 }

 /*
  * 释放资源, 并且将缓冲区的内容刷出
  */
 public void close() throws IOException {
  flush();
  writer.close();
 }

 /*
  * 将缓冲区中的数据刷出, 写到被包装的输出流中
  */
 public void flush() throws IOException {
  writer.write(buffer, 0, len);
  len = 0;
 }

 /*
  * 写出一个字符串, 将字符串转为字符数组, 遍历数组逐个写出
  */
 public void write(String line) throws IOException {
  for (char c : line.toCharArray())
   write(c);
 }

 /*
  * 写出换行符号
  */
 public void newLine() throws IOException {
  write("\r\n");
 }

 @Override
 public void write(char[] cbuf, int off, int len) throws IOException {
  for (int i = off; i < off + len; i++)
   write(cbuf[i]);
 }

}

 

 

import java.io.IOException;
import java.io.Reader;

/*
 * 在调用read()方法时, 判断缓冲区中是否有有效数据, 有则直接返回缓冲区中的, 没有就从被包装流中读取数据到缓冲区再返回
 */
public class MyBufferedReader extends Reader {
 private Reader reader;      // 被包装的流
 private char[] buffer = new char[8192];  // 缓冲区
 private int pos;       // 读取的位置
 private int len;       // 有效数据的个数

 public MyBufferedReader(Reader reader) { // 通过构造函数包装一个流
  this.reader = reader;
 }

 public int read() throws IOException {
  if(pos == len){  // 第一次调用read()方法 或者 所有有效数据都被读取过    
   len = reader.read(buffer);
   pos = 0;
  }
  return len == -1 ? -1 : buffer[pos++];
 }
 
 public void close() throws IOException{
  reader.close();
 }

 public String readLine() throws IOException {
  StringBuilder sb = new StringBuilder();
  int ch;
  while (true) {
   ch = read();     // 读取一个字符
   if (ch == '\r' || ch == -1)  // 判断是否是行末尾或文件末尾
    break;
   if (ch == '\n')
    continue;
   sb.append((char) ch);
  }
  return ch == -1 && sb.length() == 0 ? null : sb.toString();
 }

 @Override
 public int read(char[] cbuf, int off, int len) throws IOException {
  return 0;
 }
}

 

 

 

 6.   装饰设计模式(Decorator)

       什么情况下使用装饰设计模式

当我们需要对一个类的功能进行改进、增强的时候

       装饰模式的基本格式。

含有被装饰类的引用

通过构造函数传入被装饰类对象

和被装饰类含有同样的方法,其中调用被装饰类的方法,对其进行改进、增强

和被装饰类继承同一个类或实现同一个接口,可以当做被装饰类来使用

       了解BufferedReader、BufferedWriter的原理。

BufferedReader、BufferedWriter都是装饰类,他们可以装饰一个Reader或Writer,给被装饰的Reader和Writer提供缓冲的功能。

就像我们用BufferedReader、BufferedWriter装饰FileReader和FileWriter,使用的读写功能还是FileReader和FileWriter的,但给这两个类的读写添加了缓冲功能。

        练习

 


import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;

public class MyLineNumberReader extends BufferedReader {

 private int lineNumber;

 /*
  * 创建LineNumberReader的时候, 需要接受一个Reader, 这个Reader将传入BufferedReader的构造函数中
  */
 public MyLineNumberReader(Reader reader) {
  super(reader);
 }

 public int getLineNumber() {
  return lineNumber;
 }

 /*
  * 调用该方法时, 使用BufferedReader的readLine()方法读取一行
  * 判断如果不为空就将行号加1
  */
 public String readLine() throws IOException {
  String line = super.readLine();
  if (line != null)
   lineNumber++;
  return line;
 }
}

 

 

 7.   字节流

   基本操作与字符流相同

    字节流可以操作任意类型数据

   

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;

public class ConvertStream {

 public static void main(String[] args) throws IOException {
  // read3(new FileInputStream("day15-笔记.txt"));

  write1(new FileOutputStream("dest.txt"));
 }

 /*
  * 方法中获得了一个字节输出流, 想向流中写出字符数据
  */
 private static void write1(OutputStream out) throws IOException {
  out.write("字符数据".getBytes());
  out.write("再写一次".getBytes());
  out.close();
 }
 
 /*
  * 将字节流转为字符流, 直接写出字符, 自动编码
  */
 private static void write2(OutputStream out) throws IOException {
  Writer writer = new OutputStreamWriter(out);
  writer.write("字符数据");
  writer.write("再写一次");
  writer.close();
 }

 /*
  * 该方法接收一个字节输入流(流中所有数据都是字符数据), 可以将流中的字符打印在屏幕上
  */
 public static void read1(InputStream in) throws IOException {
  int b;
  while ((b = in.read()) != -1) {
   byte b1 = (byte) b;
   if (b1 < 0) {
    byte b2 = (byte) in.read();
    System.out.print(new String(new byte[] { b1, b2 }));
   } else
    System.out.print((char) b);
  }
  in.close();
 }

 /*
  * 人工解码
  * 需要考虑最后一个是否是中文的一半
  */
 public static void read2(InputStream in) throws IOException {
  byte[] buffer = new byte[1024];
  int len;
  while ((len = in.read(buffer)) != -1)
   System.out.print(new String(buffer, 0, len));
  in.close();
 }

 /*
  * 在方法中我们获得了一个字节流, 需要从中读取字符的时候, 就可以用转换流来做
  * InputStreamReader可以从InputStream中读取字符
  * 自动解码
  */
 public static void read3(InputStream in) throws IOException {
  Reader r = new InputStreamReader(in);
  int ch;
  while ((ch = r.read()) != -1)
   System.out.print((char) ch);
  r.close();
 }

}

 

 

 

 8.   字节流缓冲区读写

         自定义缓冲区读写

    原理和字符流相同,都是为了提高效率

    定义数组缓冲数据,一次读取一个数组,一次写出一个数组,减少操作文件的次数

         BufferedInputStream、BufferedOutputStream

   和BufferedReader、BufferedWriter原理相同,都是包装类

    BufferedInputStream、BufferedOutputStream包装InputStream和OutputStream提供缓冲功能

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

public class Review {

 public static void main(String[] args) throws IOException {
  //  review1();
  //  review2();
  //  review3();
  //  review4();
 }

 private static void review4() throws FileNotFoundException, IOException {
  BufferedReader r = null;
  BufferedWriter w = null;
  try {
   r = new BufferedReader(new FileReader("IMG_0009.jpg"));
   w = new BufferedWriter(new FileWriter("dest.jpg"));
   String line;
   while ((line = r.readLine()) != null) {
    w.write(line);
    w.newLine();
   }
  } finally {
   Util.close(r, w);
  }
 }

 private static void review3() throws FileNotFoundException, IOException {
  Reader r = null;
  Writer w = null;
  try {
   r = new BufferedReader(new FileReader("day15-笔记.txt")); // 读取的时候先读到缓冲区, 减少读文件的次数
   w = new BufferedWriter(new FileWriter("dest.txt")); // 写出的时候, 先写到缓冲区, 减少操作文件的次数
   int ch;
   while ((ch = r.read()) != -1)
    w.write(ch);
  } finally {
   Util.close(r, w);
  }
 }

 private static void review2() throws FileNotFoundException, IOException {
  FileReader fr = null;
  FileWriter fw = null;
  try {
   fr = new FileReader("day15-笔记.txt");
   fw = new FileWriter("dest.txt", true);
   char[] buf = new char[1024];
   int len;
   while ((len = fr.read(buf)) != -1)
    fw.write(buf, 0, len);
  } finally {
   Util.close(fr, fw);
  }
 }

 private static void review1() throws FileNotFoundException, IOException {
  FileReader fr = null;
  FileWriter fw = null;
  try {
   fr = new FileReader("day15-笔记.txt");
   fw = new FileWriter("dest.txt");
   int ch;
   while ((ch = fr.read()) != -1)
    fw.write(ch);
  } finally {
   Util.close(fr, fw);
  }
 }

}

 

 

 9.   转换流

    字符流与字节流之间的桥梁

    方便了字符流与字节流之间的操作

    字节流中的数据都是字符时,转成字符流操作更高效

    练习

 

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;

public class ConvertStream {

 public static void main(String[] args) throws IOException {
  // read3(new FileInputStream("day15-笔记.txt"));

  write1(new FileOutputStream("dest.txt"));
 }

 /*
  * 方法中获得了一个字节输出流, 想向流中写出字符数据
  */
 private static void write1(OutputStream out) throws IOException {
  out.write("字符数据".getBytes());
  out.write("再写一次".getBytes());
  out.close();
 }
 
 /*
  * 将字节流转为字符流, 直接写出字符, 自动编码
  */
 private static void write2(OutputStream out) throws IOException {
  Writer writer = new OutputStreamWriter(out);
  writer.write("字符数据");
  writer.write("再写一次");
  writer.close();
 }

 /*
  * 该方法接收一个字节输入流(流中所有数据都是字符数据), 可以将流中的字符打印在屏幕上
  */
 public static void read1(InputStream in) throws IOException {
  int b;
  while ((b = in.read()) != -1) {
   byte b1 = (byte) b;
   if (b1 < 0) {
    byte b2 = (byte) in.read();
    System.out.print(new String(new byte[] { b1, b2 }));
   } else
    System.out.print((char) b);
  }
  in.close();
 }

 /*
  * 人工解码
  * 需要考虑最后一个是否是中文的一半
  */
 public static void read2(InputStream in) throws IOException {
  byte[] buffer = new byte[1024];
  int len;
  while ((len = in.read(buffer)) != -1)
   System.out.print(new String(buffer, 0, len));
  in.close();
 }

 /*
  * 在方法中我们获得了一个字节流, 需要从中读取字符的时候, 就可以用转换流来做
  * InputStreamReader可以从InputStream中读取字符
  * 自动解码
  */
 public static void read3(InputStream in) throws IOException {
  Reader r = new InputStreamReader(in);
  int ch;
  while ((ch = r.read()) != -1)
   System.out.print((char) ch);
  r.close();
 }

}

 

 

 

 10.       标准输入输出流

   System类中的成员变量:in,out。

   它们各代表了系统标准的输入和输出设备。

    默认输入设备是键盘,输出设备是显示器。

   System.in的类型是InputStream.

   System.out的类型是PrintStream是OutputStream的子类FilterOutputStream 的子类.

 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/*
 * System.in 是系统的标准输入流, 默认读取键盘输入数据, 是一个InputStream
 * 如果我们想从键盘输入读取字符, 那么就可以使用InputStreamReader将System.in转为字符流
 * 如果我们向一次从键盘输入中读取一行, 那么可以使用BufferedReader包装InputStreamReader
 */
public class ReadKeyInputDemo {

 public static void main(String[] args) throws IOException {
  InputStream in = System.in;   // 获取系统默认输入流, InputStream
  InputStreamReader isr = new InputStreamReader(in);  // 为了读字符方便, 转换为Reader
  BufferedReader br = new BufferedReader(isr);  // 为了读一行, 转换为BufferedReader
  
  // BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

  System.out.println(br.readLine());
  System.out.println(br.readLine());
  System.out.println(br.readLine());

 }

}

 

 

 

 11.       流基本应用小节

   流是用来处理数据的。

    处理数据时,一定要先明确数据源,或者数据目的地

    数据源可以是文件,可以是键盘或者其他设备。

    数据目的地可以是文件、显示器或者其他设备。

   而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。

 

 

 12.       File类

    用来将文件或者文件夹路径封装成对象

    方便对文件与文件夹进行操作。

    File对象可以作为参数传递给流的构造函数。

    了解File类中的常用方法。

File类的方法分类:

1,创建。
 boolean createNewFile()throws IOException
 static File createTempFile(String prefix, String suffix)
 boolean mkdir()
 boolean mkdirs()
 


2,删除。
 boolean delete();
 void deleteOnExit()
 
3,判断。
 exists();
 canExecute();
 canRead();
 canWrite();
 isHidden();
 isFile();
 isDirectory();
 isAbsolute();


4,获取。
 getName();
 getPath();
 getParent();
 getAbsolutePath();
 long lastModified()
          返回此抽象路径名表示的文件最后一次被修改的时间。
 long length()

 String[] list();
 File[] listFiles();

 

 


import java.io.File;

public class FileDemo {

 public static void main(String[] args) {
  //  test1();
  //  test2();  
  //  test3();  
  //  test4();
  //  test5();
 }

 private static void test5() {
  File parent = new File("F:/Itcast/20111015");
  
  File f1 = new File(parent, "day4");
  File f2 = new File(parent, "day5");
  File f3 = new File(parent, "day6");
  File f4 = new File(parent, "1015课表.xls");
  File f5 = new File(parent, "cmd.exe");

  System.out.println(f1.exists());
  System.out.println(f2.exists());
  System.out.println(f3.exists());
  System.out.println(f4.exists());
  System.out.println(f5.exists());
 }

 /*
  * 字符串类型父级路径
  */
 private static void test4() {
  String parent = "F:/Itcast/20111015";

  File f1 = new File(parent, "day4");
  File f2 = new File(parent, "day5");
  File f3 = new File(parent, "day6");
  File f4 = new File(parent, "1015课表.xls");
  File f5 = new File(parent, "cmd.exe");

  System.out.println(f1.exists());
  System.out.println(f2.exists());
  System.out.println(f3.exists());
  System.out.println(f4.exists());
  System.out.println(f5.exists());
 }

 /*
  * 判断是否是绝对路径
  */
 private static void test3() {
  File f1 = new File("F:/Itcast/20111015/day16/day16-笔记.txt"); // 绝对路径, 从盘符开始
  File f2 = new File("day16-笔记.txt");

  System.out.println(f1.isAbsolute()); // 是否是绝对路径
  System.out.println(f2.isAbsolute());
 }

 /*
  * 判断是否是文件, 是否是文件夹
  */
 private static void test2() {
  File f1 = new File("day16-笔记.txt"); // 指向文件
  File f2 = new File("src"); // 指向文件夹

  System.out.println(f1.isFile()); // 判断是否是存在的文件
  System.out.println(f2.isFile());

  System.out.println(f1.isDirectory()); // 判断是否是存在的文件夹
  System.out.println(f2.isDirectory());
 }

 /*
  * File f2 = new File("day16-笔记.txt");
  * 相对目录由运行环境不同而相对的路径也不同
  * 在Eclipse中运行时是找工程根目录下的 day16-笔记.txt
  * 在cmd中运行时是在当前目录下找 day16-笔记.txt
  */
 private static void test1() {
  File f1 = new File("F:/Itcast/20111015/day16/day16-笔记.txt"); // 绝对路径, 从盘符开始
  File f2 = new File("day16-笔记.txt"); // 相对路径, 在Eclipse中相对于工程根目录, cmd相对于当前目录
  System.out.println(f1.exists()); // 判断该File对象封装的路径是否存在
  System.out.println(f2.exists());
 }

}

 

 

 

 

 13.       递归

    函数自己调用自己。

   注意:递归时一定要明确结束条件。

    应用场景:

当某一功能要重复使用时。

 

 

  练习:

列出一个文件夹下所有的子文件夹以及子文件

/*

listFiles可以列出当前目录下的文件以及文件夹。
需求:
想要列出指定目录下的所有文件以及文件夹,包含子文件夹中的内容。

 

递归:编程手法。
特点:方法自身调用自身。
注意:在递归时,两个注意事项:
1,一定要定义递归的条件。
2,要注意递归的次数。

 

public void show()
{
 show();
}

*/
import java.io.*;


class FileDemo3
{
 public static void main(String[] args)
 {
  File dir = new File("d:\\java0217");
  //listAll(dir);

  //toBin(6);

  int num = getSum(30000);

  System.out.println("num="+num);
 }

 public static int getSum(int num)
 {
  if(num==1)
   return 1;
  return num+getSum(num-1);
 }

 public static void toBin(int num)
 {
  if(num>0)
  {
   toBin(num/2);
   System.out.println(num%2);
  }
 }

 public static void listAll(File dir)
 {
  File[] files = dir.listFiles();
  for(int x=0; x<files.length; x++)
  {
   if(files[x].isDirectory())
    listAll(files[x]);
   System.out.println(files[x]);
  }
 }
}

 

 14.       IO包中的其他类

  序列流

SequenceInputStream

可以将多个字节输入流整合成一个流,在使用这个流读取的时候,读到第一个流的末尾时继续读第二个,第二个读到末尾则继续读第三个,以此类推,直到读到最后一个流的末尾返回-1

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

public class SequenceInputStreamDemo {

 public static void main(String[] args) throws IOException {
  //  test1();
  //  test2();
  //  test3();
  //  test4();
 }
 
 private static <X> Enumeration<X> enumeration(final Collection<X> c) {
  return new Enumeration<X>() {
   Iterator<X> iter = c.iterator();
   public boolean hasMoreElements() {
    return iter.hasNext();
   }
   public X nextElement() {
    return iter.next();
   }
  };
 }

 private static void test4() throws FileNotFoundException, IOException {
  FileInputStream fis1 = new FileInputStream("1.txt");
  FileInputStream fis2 = new FileInputStream("2.txt");
  FileInputStream fis3 = new FileInputStream("3.txt");
  
  ArrayList<FileInputStream> list = new ArrayList<FileInputStream>();
  Collections.addAll(list, fis1, fis2, fis3);       // 添加3个输入流
  Enumeration<FileInputStream> e = Collections.enumeration(list);  // 从List获取Enumeration
  
  SequenceInputStream sis = new SequenceInputStream(e);    // 整合
  FileOutputStream fos = new FileOutputStream("4.txt");
  byte[] buf = new byte[1024];
  int len;
  while((len = sis.read(buf)) != -1)
   fos.write(buf, 0, len);
  sis.close(); // 这里会关闭被整合的流
  fos.close();
 }

 private static void test3() throws FileNotFoundException, IOException {
  FileInputStream fis1 = new FileInputStream("1.txt");
  FileInputStream fis2 = new FileInputStream("2.txt");
  FileInputStream fis3 = new FileInputStream("3.txt");
  
  Vector<FileInputStream> v = new Vector<FileInputStream>();  // 为了获取Enumeration, 创建Vector
  v.add(fis1);
  v.add(fis2);
  v.add(fis3);
  Enumeration<FileInputStream> e = v.elements();     // 获取Enumeration
  
  SequenceInputStream sis = new SequenceInputStream(e);   // 整合
  FileOutputStream fos = new FileOutputStream("4.txt");
  
  byte[] buf = new byte[1024];
  int len;
  while((len = sis.read(buf)) != -1)
   fos.write(buf, 0, len);
  
  sis.close(); // 这里会关闭被整合的流
  fos.close();
 }

 private static void test2() throws FileNotFoundException, IOException {
  FileInputStream fis1 = new FileInputStream("1.txt");
  FileInputStream fis2 = new FileInputStream("2.txt");
  FileInputStream fis3 = new FileInputStream("3.txt");
  
  SequenceInputStream sis1 = new SequenceInputStream(fis1, fis2);  // 整合1,2
  SequenceInputStream sis2 = new SequenceInputStream(sis1, fis3);  // 将1,2和3整合
  FileOutputStream fos = new FileOutputStream("4.txt");
  
  byte[] buf = new byte[1024];
  int len;
  while((len = sis2.read(buf)) != -1)
   fos.write(buf, 0, len);
  
  sis2.close(); // 这里会关闭被整合的流
  fos.close();
 }

 private static void test1() throws FileNotFoundException, IOException {
  FileInputStream fis1 = new FileInputStream("1.txt");
  FileInputStream fis2 = new FileInputStream("2.txt");
  
  SequenceInputStream sis = new SequenceInputStream(fis1, fis2);  // 创建序列流, 整合2个输入流
  FileOutputStream fos = new FileOutputStream("3.txt");
  
  byte[] buf = new byte[1024];
  int len;
  while((len = sis.read(buf)) != -1)
   fos.write(buf, 0, len);
  
  sis.close(); // 这里会关闭被整合的流
  fos.close();
 }

}

 

   打印流

PrintStream 、PrintWriter

       相比普通的OutputStream和Writer增加了print()和println()方法,这两个方法可以输出实参的toString()方法的返回值

       这两个类还提供自动flush()的功能

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

import cn.itcast.day17.domain.Person;

/*
 * 00000000 00000000 00000000 01100001  97
 * 00000000 00000000 01101010 01100001  27233
 *
 * ps.print(i);
 *
 * Integer integer = new Integer(i)
 * ps.print(integer.toString());
 *
 * 如果我们需要输出一个对象的toString()返回值时使用
 * 在每次写出之后时需要flush()时使用
 * 在每次写出之后需要换行时使用
 */
public class PrintStreamDemo {

 public static void main(String[] args) throws Exception {
  //  test1();
  //  test2();
  //  test3();
  //  test4();
 }

 private static void test4() throws FileNotFoundException, UnsupportedEncodingException {
  FileOutputStream fos = new FileOutputStream("dest.txt");
  PrintStream ps = new PrintStream(fos, true, "GBK");  // 包装字节流, 每次写出时flush(), 指定码表
  ps.println(123);
  ps.println("中文");
  ps.close();
 }

 private static void test3() throws Exception {
  Person p = new Person("沙诗博", 22);
  int i = 27233;
  PrintStream ps = new PrintStream("dest.txt", "UTF-8");
  ps.println(i); // 写出的是实参对象的toString()返回值, 基本数据类型会先转成包装类对象
  ps.println(p);
  ps.close();
 }

 private static void test2() throws IOException {
  int i = 27233;
  FileWriter fw = new FileWriter("dest.txt");
  fw.write(i); // 字符流写出, 先转char再写出
  fw.close();
 }

 private static void test1() throws FileNotFoundException, IOException {
  int i = 27233;
  FileOutputStream fos = new FileOutputStream("dest.txt");
  fos.write(i); // 字节输出流, 每次写出一个字节, 会将int类型的实参转为byte类型写出
  fos.close();
 }

}

 

 

 

   操作对象

ObjectOutputStream

       可以将实现了Serializable的接口的对象转成字节写出到流中

ObjectInputStream

       可以从流中读取一个ObjectOutputStream流写出的对象


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;

import cn.itcast.day17.domain.Person;

/*
 * 如果要将一个对象写出, 必须将其序列化.
 * 序列化: 将对象转为可传输或存储的形式. 把对象转为字节数据. 
 *
 * 将对象持久化的一种方式
 */
public class ObjectStreamDemo {

 public static void main(String[] args) throws Exception {
  //  test1();
  //  test2();

  //  test3();
  //  test4();
  

  //  test5();
  //  test6();
 }

 private static void test6() throws IOException, FileNotFoundException, ClassNotFoundException {
  ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dest.txt"));
  ArrayList<Person> list = (ArrayList<Person>) ois.readObject();  // 一次读取一个容器
  ois.close();
  for (Person p : list)
   System.out.println(p);  // 遍历容器得到每一个对象
 }

 private static void test5() throws IOException, FileNotFoundException {
  Person p1 = new Person("沙 ", 22);
  Person p2 = new Person(" 成龙", 23);
  Person p3 = new Person("高 ", 24);
  ArrayList<Person> list = new ArrayList<Person>();  // 创建一个容器
  Collections.addAll(list, p1,p2,p3);      // 将多个对象装入容器
  ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dest.txt"));
  oos.writeObject(list);         // 一次性写出
  oos.close();
 }

 private static void test4() throws IOException, FileNotFoundException, ClassNotFoundException {
  ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dest.txt"));
  System.out.println(ois.readObject());
  System.out.println(ois.readObject());
  System.out.println(ois.readObject());
  ois.close();
 }

 // 写出多个对象
 private static void test3() throws IOException, FileNotFoundException {
  Person p1 = new Person("沙 ", 22);
  Person p2 = new Person(" 成龙", 23);
  Person p3 = new Person("高 ", 24);
  ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dest.txt"));
  oos.writeObject(p1);
  oos.writeObject(p2);
  oos.writeObject(p3);
  oos.close();
 }

 private static void test2() throws IOException, FileNotFoundException, ClassNotFoundException {
  ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dest.txt"));
  Person p = (Person) ois.readObject();  // 读取一个对象
  System.out.println(p);
  ois.close();
 }

 private static void test1() throws IOException, FileNotFoundException {
  Person p = new Person("沙 ", 22);
  ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dest.txt"));
  oos.writeObject(p);  // 写出对象
  oos.close();
 }

}

 

 

 

 

    操作内存缓冲数组

ByteArrayOutputStream: 写出到字节数组(内存)中,可以获取写出的内容装入一个字节数组。通常我们用这个流来缓冲数据。

ByteArrayInputStream:可以从一个字节数组中读取字节。

CharArrayWriter:写出字符到字符数组(内存)中,可以获取写出的内容装入一个字符数组。

CharArrayReader:可以从一个字符数组中读取字符。


import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * ByteArrayOutputStream 通常用来缓存数据, 可以把数据暂时写到内存中
 */
public class ByteArrayOutputStreamDemo {

 public static void main(String[] args) throws IOException {
  //  test1();
  //  test2();
 }

 private static void test2() throws FileNotFoundException, IOException {
  // 将流中所有数据都写到内存中
  FileInputStream fis = new FileInputStream("day17-笔记.txt");
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  byte[] buf = new byte[1024];
  int len;
  while((len = fis.read(buf))!=-1)
   baos.write(buf,0,len);     
  fis.close();
  baos.close();
  
  // 将字节数据转为字符串
  String s = new String(baos.toByteArray());
  System.out.println(s);
 }

 private static void test1() throws FileNotFoundException, IOException {
  FileInputStream fis = new FileInputStream("day17-笔记.txt");
  ByteArrayOutputStream baos = new ByteArrayOutputStream();  // 数据目的地为内存 
  byte[] buf = new byte[1024];
  int len;
  while((len = fis.read(buf))!=-1)
   baos.write(buf,0,len);     // 写出数据到内存中
  fis.close();
  baos.close();
  
  byte[] data = baos.toByteArray();   // 获取之前写出的所有数据
  FileOutputStream fos = new FileOutputStream("dest.txt");
  fos.write(data);       // 将内存中所有数据一次性写出到文件
  fos.close();
 }

}

 

 

 

    管道流

PipedInputStream:管道输入流,可以从管道输出流中读取数据

PipedOutputStream:管道输出流,可以向管道输入流中写出数据

   操作基本数据类型

DataInputStream、DataOutputStream

       可以按照基本数据类型占用空间大小读写数据

    随机访问文件

RandomAccessFile


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;

public class PipedStreamDemo {

 public static void main(String[] args) throws IOException {
  //  test1();
  //  test2();
 }

 private static void test2() throws IOException {
  PipedInputStream pis = new PipedInputStream();   // 创建管道输入流
  PipedOutputStream pos = new PipedOutputStream();  // 创建管道输出流
  pis.connect(pos);          // 将输入流和输出流连接
  
  PrintStream ps = new PrintStream(pos);
  BufferedReader br = new BufferedReader(new InputStreamReader(pis));
  
  ps.println("你好啊!");     // 管道输出流写出
  System.out.println(br.readLine());  // 管道输入流读取
  ps.println("再见!");
  System.out.println(br.readLine());
  
  ps.close();
  br.close();
 }

 private static void test1() throws IOException {
  PipedInputStream pis = new PipedInputStream();   // 创建管道输入流
  PipedOutputStream pos = new PipedOutputStream();  // 创建管道输出流
  
  pis.connect(pos);     // 将输入流和输出流连接
  
  pos.write("hi\r\n".getBytes());  // 使用输出流输出数据, 数据将流向输入流中
  pos.write("bye".getBytes()); 
  pos.close();
  
  int b;
  while((b = pis.read()) != -1)
   System.out.print((char)b);
  pis.close();
 }

}

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值