Java中IO流的相关操作

1 字节流

FileInputStreamFileOutputStream

        // IO流的读取与写入
        private static void demo01() throws IOException {
        // 如果是追加内容,则使用第二个参数为true的重载构造函数
        FileOutputStream fos = new FileOutputStream("1.txt");
        fos.write(97);
        fos.write(98);
        fos.write(99);
        fos.close();

        FileInputStream fis = new FileInputStream("1.txt");
        // 字节读取返回的是读取的字节十进制值,并且自动向后偏移,如果返回-1则表过读取完毕
        int data = fis.read();
        System.out.println((char) data);
        fis.close();

        // 一次读取多个字节
        FileInputStream fis2 = new FileInputStream("1.txt");
        int length = 0;
        byte[] bytes = new byte[1024];
        while((length = fis2.read(bytes)) != -1) {
            System.out.print(new String(bytes, 0, length));
        }
        fis2.close();
    }

2 字符流

FileReaderFileWrite

        // 字符流的读取与写入
    private static void demo02() throws IOException {
        // 如果是追加,则第二个参数传true
        FileWriter fw = new FileWriter("1.txt");
        fw.write(new char[]{'中', '国'});
        // 字符的写入是先保存在内存缓存区,需要调用flush方法才会真正的写入到文件
        fw.flush();

        // 单个字符读取
        FileReader fr = new FileReader("1.txt");
        // 文件的读取会以字符的单位一个一个读取,如果返回值为-1则表示读取完毕
        int c = fr.read();
        System.out.println((char) c);

        // 一次读取多个字符
        FileReader fr2 = new FileReader("1.txt");
        int length = 0;
        char[] charArray = new char[1024];
        while((length = fr2.read(charArray)) != -1) {
            System.out.print(new String(charArray, 0, length));
        }
        fr2.close();
    }

3 异常处理

关于换行符号

* Windows中插入字节 \r\n
* Linux中插入字节 /n
* MacOS中插入字节 /r

异常处理,对于IO操作都需要对异常进行处理

  • 一种方式是直接方法中抛出throws IOException

  • 另一种方式则是在代码中进行try...catch手动处理

    // 异常处理try...catch
    private static void demo03() {
      // JDK1.7之前必须在finally中释放资源
      FileWriter fw = null;
      try {
          fw = new FileWriter("1.txt");
          fw.write('A');
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
          if (fw == null) return;
          try {
              fw.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
    
      // JDK1.7之后实现了Closeable接口的类,可以在try(){}中被自动释放
      try (FileWriter fw1 = new FileWriter("1.txt")) {
          fw1.write("HelloWorld");
      } catch(IOException e) {
          e.printStackTrace();
      }
    }
    

4 对象的IO读写

Properties

public class PropertiesDemo {
    /**
     * Properties是HashTable的子类,HashTable是Map集合的一个实现类
     * HashTab在JDK1.2之后被HashMap及其子类所取代,但Properties有与IO交互的能力一直被延用
     * Properties是HashTable的特殊形式,即键与值都是字符串类型,并且可以将字符串序列化到本地或者在本地读取文件反序列化成对象
     * @param args
     */
    public static void main(String[] args) {
        demo01();
        demo02();
    }

    // 本地文件数据加载到对象中
    private static void demo02() {
        Properties p = new Properties();
        try (FileReader fr = new FileReader("1.txt")) {
            p.load(fr);
            for (String key : p.stringPropertyNames()) {
                System.out.println(p.get(key));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 对象序列化到本地文件
    private static void demo01() {
        Properties p = new Properties();
        p.setProperty("one", "第一");
        p.setProperty("two", "第二");
        p.setProperty("three", "第三");
        for (String key : p.stringPropertyNames()) {
            System.out.println(p.get(key));
        }
        // 可以使用FileOutputStream对象,但中文编码会有问题?!   
        try(FileWriter fw = new FileWriter("1.txt")) {
            p.store(fw, "properties store method");
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

文件内容:

#properties store method
#Tue Nov 17 15:36:59 CST 2020
one=第一
two=第二
three=第三

5 带缓冲的IO读写

public class BufferedDemo {
    public static void main(String[] args) {
        demo01();
    }

    // 字符流的读写操作
    private static void demo02() {
        // 写
        try (
                FileWriter fw = new FileWriter("1.txt");
                BufferedWriter bw = new BufferedWriter(fw);
        ) {
            fw.write("中文写入测试...");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 读
        try (
                FileReader fr = new FileReader("1.txt");
                BufferedReader br = new BufferedReader(fr);
        ) {
            int data = 0;
            while ((data = br.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 带缓冲字节流的读写操作
    private static void demo01() {
        // 写
        try (
                FileOutputStream fos = new FileOutputStream("1.txt");
                BufferedOutputStream bos = new BufferedOutputStream(fos);
        ) {
            bos.write("Buffered write...中文".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 读
        try (
                FileInputStream fis = new FileInputStream("1.txt");
                BufferedInputStream bis = new BufferedInputStream(fis)
        ) {
            int data = 0;
            ArrayList<Integer> array = new ArrayList<>();
            while ((data = bis.read()) != -1) {
                array.add(data);
            }
            // 存储的时候使用的是字符串的getBytes()方法存储的,所以原则上可以还原中文
            byte[] byteArray = new byte[array.size()];
            for (int i = 0; i < array.size(); i++) {
                byteArray[i] = array.get(i).byteValue();
            }
            System.out.println(new String(byteArray));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 带缓冲的字符流的读写操作
    private static void demo03() {
        // 写
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("1.txt"))) {
            for (int i = 0; i < 10; i++) {
                bw.write("中文-中华人民共和国");
                // 字符的写操作有写入换行的操作
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 读
        try (BufferedReader br = new BufferedReader(new FileReader("1.txt"))) {
            String str = null;
            // 字符流的读取操作有读行的方法
            while ((str = br.readLine()) != null) {
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6 普通字节流的读写与带缓冲读写对比

public class CompareDemo {
    public static void main(String[] args) {
        demo01();
        demo02();
    }

    // 带缓冲区的字节流复制文件,默认缓冲区大小是8192字节
    private static void demo02() {
        try (
                FileInputStream fis = new FileInputStream("1.txt");
                BufferedInputStream bis = new BufferedInputStream(fis);
                FileOutputStream fos = new FileOutputStream("2.txt");
                BufferedOutputStream bos = new BufferedOutputStream(fos);
        ) {
            long s = System.currentTimeMillis();

            int data = 0;
            while ((data = bis.read()) != -1) {
                bos.write(data);
            }

            long e = System.currentTimeMillis();
            System.out.println("Time: " + (e - s));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 字节流的文件复制
    private static void demo01() {
        try (
                FileInputStream fis = new FileInputStream("1.txt");
                FileOutputStream fos = new FileOutputStream("2.txt");
        ) {
            long s = System.currentTimeMillis();
            // 多字节复制
            byte[] bytes = new byte[256];
            int length = 0;
            while ((length = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, length);
            }

            long e = System.currentTimeMillis();
            System.out.println("Time: " + (e - s));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

7 指定编码集的读写操作

public class CharsetDemo {
    public static void main(String[] args) {
        String str = "中文字符串测试";
        writeToFileWithCharset(str, "1.txt", "gbk");
        System.out.println(readFileWithCharset("1.txt", "gbk"));
    }

    // 将字符串以指定的编码集写入文件
    private static void writeToFileWithCharset(String str, String fileName, String charsetName) {
        try (
                FileOutputStream fos = new FileOutputStream(fileName);
                OutputStreamWriter osw = new OutputStreamWriter(fos, charsetName);
        ) {
            osw.write(str);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 用指定的编码集从文件读取字符串
    private static String readFileWithCharset(String fileName, String charsetName) {
        try (
                FileInputStream fis = new FileInputStream(fileName);
                InputStreamReader isr = new InputStreamReader(fis, charsetName);
        ) {
            int data = 0;
            // 取出所有的数据到ArrayList
            ArrayList<Integer> array = new ArrayList<>();
            while ((data = isr.read()) != -1) {
                array.add(data);
            }
            // 将Integer类型的List转换为char数组
            char[] chars = new char[array.size()];
            for (int i = 0; i < chars.length; i++) {
                Integer b = array.get(i);
                chars[i] = (char) b.intValue();
            }
            // 转换为字符串返回
            return new String(chars);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

8 对象序列化与反序列化

相关类:ObjectInputStreamObjectOutputStream

自定义对象

public class Person implements Serializable {

    private static final long serialVersionUID = 42L;

    String name;

    Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class ObjectStreamDemo {

    public static void main(String[] args) {
        writeObject(new Person("Sian"));
        Object obj = readObject();
        System.out.println(obj);
    }

    // 序列化对象到本地
    private static void writeObject(Object obj) {
        try (
                FileOutputStream fos = new FileOutputStream("1.txt");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
        ) {
            oos.writeObject(obj);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 本地读取反序列化为对象
    private static Object readObject() {
        try (
                FileInputStream fis = new FileInputStream("1.txt");
                ObjectInputStream ois = new ObjectInputStream(fis);
        ) {
            return ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

9 打印输出流

相关类PrintStream

  • PrintStream继承自OutputStream
  • System.out就是一个PrintStream对象
  • System.setOut()方法可以指定打印的场所
  System.out.println("我是正常输出...");
  try {
      // 注意:不能被释放,否则输出无效!!!
      System.setOut(new PrintStream("print.txt"));
  } catch (IOException e) {
      e.printStackTrace();
  }
  System.out.println("我是修改后的输出...");
  System.out.println("我是修改后的输出...");

Leave a Reply