Java io 处理流

节点流和处理流概述

Java流可以分节点流和处理流两类。

节点流是面向各种物理节点的流,比如面向读写文件的FileInputStream和FileOutputStream;面向对象的ObjectInputStream和ObjectOutputStream等等。

处理流则需要依附于节点流,用来对节点流的功能进行拓展和加强。比如BufferedInputStream,用它来包装FileInputStream(或者其他的节点输入流也一样)以后 ,直接调用BufferedInputStream的read方法,这个read方法的效果和FileInputStream的read方法的效果相比,就多出来一个缓存的功能。

java缓冲流本身不具IO功能,只是在别的流上加上缓冲提高效率,像是为别的流装上一种包装。当对文件或其他目标频繁读写或操作效率低,效能差。这时使用缓冲流能够更高效的读写信息。因为缓冲流先将数据缓存起来,然后一起写入或读取出来。所以说,缓冲流还是很重要的,在IO操作时记得加上缓冲流提升性能。

<1>处理流之缓冲流

缓冲流分为字节和字符缓冲流

字节缓冲流为:

BufferedInputStream—字节输入缓冲流

BufferedOutputStream—字节输出缓冲流

字符缓冲流为:

BufferedReader—字符输入缓冲流

BufferedWriter—字符输出缓冲流

BufferedWriter

    public static void main(String[] args) throws IOException {
String filePath = "d:" + File.separator + "test.txt";
File file = new File(filePath);
FileWriter writer = new FileWriter(file);
BufferedWriter bufferedWriter = new BufferedWriter(writer);
bufferedWriter.write("c++");
bufferedWriter.newLine();
bufferedWriter.write("java");
bufferedWriter.newLine();
bufferedWriter.write(98);
bufferedWriter.flush();
bufferedWriter.newLine();
char[] chars = "测试代码".toCharArray();
bufferedWriter.write(chars, 1, chars.length - 1);
bufferedWriter.close();
writer.close();
/* c++
java
b
试代码*/
}

BufferedReader

public static void main(String[] args) throws IOException {
String filePath = "d:" + File.separator + "test.txt";
File file = new File(filePath);
FileReader reader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(reader);
int len;
char[] chars = new char[1024];
String res = "";
while ((len = bufferedReader.read(chars)) != -1) {
res += new String(chars, 0, len);
}
System.out.println(res);
bufferedReader.close();
reader.close();
}

FileInputStream

public static void main(String[] args) throws IOException {
String filePath = "d:" + File.separator + "test.txt";
File file = new File(filePath);
FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
int len;
byte[] bytes = new byte[2];
String res = "";
while ((len = bufferedInputStream.read(bytes)) != -1) {
res += new String(bytes, 0, len);
}
System.out.println(res);
bufferedInputStream.close();
fileInputStream.close();
}

FileOutputStream

public static void main(String[] args) throws IOException {
String filePath = "d:" + File.separator + "test.txt";
File file = new File(filePath);
FileOutputStream fileOutputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
bufferedOutputStream.write(97);
//换行
bufferedOutputStream.write(10);
byte[] bytes = "hello world".getBytes();
bufferedOutputStream.write(bytes, 0, bytes.length - 1);
bufferedOutputStream.close();
fileOutputStream.close();
//输出
//a
//hello worl
}

<2>处理流之转换流

转换流提供了在字节流和字符流之间的转换

Java API提供了两个转换流:

  • InputStreamReader :将InputStream 转换为Reader
  • OutputStreamWriter :将Writer 转换为OutputStream

字节流中的数据都是字符时,转成字符流操作更高效。很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。

InputStreamReader

实现将字节的输入流按指定字符集转换为字符的输入流。

构造器
  • public InputStreamReader(InputStream in)
  • public InputSreamReader(InputStream in,String charsetName)

    如: Reader isr = new InputStreamReader(System.in,”gbk”);

OutputStreamWriter

实现将字符的输出流按指定字符集转换为字节的输出流。

构造器
  • public OutputStreamWriter(OutputStream out)
  • public OutputSreamWriter(OutputStream out,String charsetName)
    public void testMyInput() throws Exception {
FileInputStream fis = new FileInputStream("dbcp.txt");
FileOutputStream fos = new FileOutputStream("dbcp5.txt");
InputStreamReader isr = new InputStreamReader(fis, "GBK");
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
BufferedReader br = new BufferedReader(isr);
BufferedWriter bw = new BufferedWriter(osw);
String str = null;
while ((str = br.readLine()) != null) {
bw.write(str);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}

常见的编码表

  • ASCII:美国标准信息交换码。用一个字节的7位可以表示。
  • ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示。
  • GB2312:中国的中文编码表。最多两个字节编码所有字符。
  • GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码。
  • Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。
  • UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。

<3>处理流之数据流

DataOutputStream数据输出流允许应用程序将基本Java数据类型写到基础输出流中,而DataInputStream数据输入流允许应用程序以机器无关的方式从底层输入流中读取基本的Java类型.

DataInputStream

DataInputStream中的方法

public final int read(byte b[]) throws IOException {}
public final int read(byte b[], int off, int len) throws IOException {}
public final void readFully(byte b[]) throws IOException {}
public final void readFully(byte b[], int off, int len) throws IOException {}
public final int skipBytes(int n) throws IOException {}
public final boolean readBoolean() throws IOException {}
public final byte readByte() throws IOException {}
public final int readUnsignedByte() throws IOException {}
public final short readShort() throws IOException {}
public final int readUnsignedShort() throws IOException {}
public final char readChar() throws IOException {}
public final int readInt() throws IOException {}
public final long readLong() throws IOException {}
public final float readFloat() throws IOException {}
public final double readDouble() throws IOException {}
public final String readUTF() throws IOException {}

使用示例:

public static void main(String[] args) throws IOException {
String filePath = "d:" + File.separator + "test.txt";
File file = new File(filePath);
FileInputStream inputStream = new FileInputStream(file);
DataInputStream dataInputStream = new DataInputStream(inputStream);
char c = dataInputStream.readChar();
String s = dataInputStream.readUTF();
float v = dataInputStream.readFloat();
System.out.println(c);
System.out.println(s);
System.out.println(v);
}

DataOutputStream

DataOutputStream中的方法:

private void incCount(int value) {}
public synchronized void write(int b) throws IOException {}
public synchronized void write(byte b[], int off, int len) throws IOException {}
public void flush() throws IOException {}
public final void writeBoolean(boolean v) throws IOException {}
public final void writeByte(int v) throws IOException {}
public final void writeShort(int v) throws IOException {}
public final void writeChar(int v) throws IOException {}
public final void writeInt(int v) throws IOException {}
public final void writeLong(long v) throws IOException {}
public final void writeFloat(float v) throws IOException {}
public final void writeDouble(double v) throws IOException {}
public final void writeBytes(String s) throws IOException {}
public final void writeChars(String s) throws IOException {}
public final void writeUTF(String str) throws IOException {}
public final int size() {}

使用示例:

public static void main(String[] args) throws IOException {
String filePath = "d:" + File.separator + "test.txt";
File file = new File(filePath);
FileOutputStream outputStream = new FileOutputStream(file);
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF("hello");
dataOutputStream.write(97);
dataOutputStream.writeChars("\n");
dataOutputStream.writeBoolean(true);
dataOutputStream.writeChar(10);
dataOutputStream.writeDouble(7.62);
dataOutputStream.flush();
dataOutputStream.close();
outputStream.close();
}

<4>处理流之对象流

ObjectInputStream 和OjbectOutputSteam用于存储和读取基本数据类型数据或 对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

  • 序列化:用ObjectOutputStream类 保存基本类型数据或对象的机制
  • 反序列化:用ObjectInputStream类 读取基本类型数据或对象的机制
  • ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
序列化

对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从

而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传

输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原

来的Java对象。

序列化的好处在于可将任何实现了Serializable接口的对象转化为 字节数据,

使其在保存和传输时可被还原。序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是JavaEE 平台的基础。如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。否则,会抛出NotSerializableException异常。

  • Serializable
  • Externalizable

实现了Serializable 接口的对象,可将它们转换成一系列字节,并可在以后

完全恢复回原来的样子。 这一过程亦可通过网络进行。这意味着序列化机

制能自动补偿操作系统间的差异。在 换句话说,可以先在Windows 机器上创

台 建一个对象,对其序列化,然后通过网络发给一台Unix 机器,然后在那里

准确无误地重新“装配”。不必关心数据在不同机器上如何表示,也不必

关心字节的顺序或者其他任何细节。

凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:

private static final long serialVersionUID;

serialVersionUID用来表明类的不同版本间的兼容性。 简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容。

如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议,显式声明

简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验

证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同

就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异

常。(InvalidCastException)

使用对象流序列化对象

若某个类实现了 Serializable 接口,该类的对象就是可序列化的:

创建一个 ObjectOutputStream, 调用 ObjectOutputStream 对象的 writeObject( 对象) 方法输出可 序列化对象,注意写出一次,操作flush() 一次。

反序列化,创建一个 ObjectInputStream, 调用 readObject() 方法读取流中的对象。

如果某个类的属性不是基本数据类型或 String 类型,而是另一个

引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的

Field 的类也不能序列化

示例:

public static void main(String[] args) throws IOException, ClassNotFoundException {
String filePath = "d:" + File.separator + "test.txt";
File file = new File(filePath);
InputStream inputStream = new FileInputStream(file);
OutputStream outputStream = new FileOutputStream(file);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
Person lilei = new Person("李雷", 25, 1.78, true, 58);
objectOutputStream.writeObject(lilei);
objectOutputStream.flush();
objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
Person p = (Person) objectInputStream.readObject();
System.out.println(p);
objectInputStream.close();
//Person{name='李雷', age=25, height=1.78, isMale=true, weight=58.0}
}

Person类:

import java.io.Serializable;
public class Person implements Serializable {
public String name;
public int age;
public double height;
public boolean isMale;
public double weight; public Person(String name, int age, double height, boolean isMale, double weight) {
this.name = name;
this.age = age;
this.height = height;
this.isMale = isMale;
this.weight = weight;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
", isMale=" + isMale +
", weight=" + weight +
'}';
}
}

<5>处理流之标准输入输出流

System.in和System.out分别代表了系统标准的输入和输出设备

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

System.in的类型是InputStream

System.out的类型是PrintStream,其是OutputStream的子类

public static void main(String[] args) throws IOException, ClassNotFoundException {
System.out.println("请输入信息(退出输入e或exit):");
// 把"标准"输入流(键盘输入)这个字节流包装成字符流,再包装成缓冲流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s = null;
try {
while ((s = br.readLine()) != null) { // 读取用户输入的一行数据 --> 阻塞程序
if ("e".equalsIgnoreCase(s) || "exit".equalsIgnoreCase(s)) {
System.out.println("安全退出!!");
break;
}
System.out.println("-->:" + s.toUpperCase());
System.out.println("继续输入信息");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close(); // 关闭过滤流时,会自动关闭它包装的底层节点流
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Java IO<3>处理流:缓冲流 数据流 转换流 对象流的更多相关文章

  1. Java IO详解(六)------序列化与反序列化(对象流)

    File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878.html Java IO 流的分类介绍:http://www.cnblogs.com/ysocea ...

  2. JAVA IO分析一:File类、字节流、字符流、字节字符转换流

    因为工作事宜,又有一段时间没有写博客了,趁着今天不是很忙开始IO之路:IO往往是我们忽略但是却又非常重要的部分,在这个讲究人机交互体验的年代,IO问题渐渐成了核心问题. 一.File类 在讲解File ...

  3. java IO之 编码 (码表 编码 解码 转换流)

    编码 什么是编码? 计算机中存储的都是二进制,但是要显示的时候,就是我们看到的却可以有中国 ,a  1 等字符 计算机中是没有存储字符的,但是我们却看到了.计算机在存储这些信息的时候,根据一个有规 则 ...

  4. Java基础知识强化之IO流笔记38:字符流缓冲流之BufferedWriter / BufferedReader使用

    1. 字符流缓冲流: 字符流为了高效读写,也提供了对应的字符缓冲流. BufferedWriter:字符缓冲输出流 BufferedReader:字符缓冲输入流 2. BufferedWriter使用 ...

  5. Java IO学习笔记(三)转换流、数据流、字节数组流

    转换流 1.转换流:将字节流转换成字符流,转换之后就可以一个字符一个字符的往程序写内容了,并且可以调用字符节点流的write(String s)方法,还可以在外面套用BufferedReader()和 ...

  6. java——io、字节流缓冲区拷贝文件、字节缓冲流

    使用try catch finally关闭文件流: 写入文件: import java.io.*; public class exp{ public static void main(String[] ...

  7. 缓冲字符流 java.io.BufferedWriter ,java.io.BufferedReader,缓冲字符输出流:PrintWriter

    package seday07; import java.io.IOException;import java.io.PrintWriter; /*** @author xingsir * 缓冲字符流 ...

  8. Java IO流

    File类 ·java.io.File类:文件和目录路径名的抽象表示形式,与平台无关 ·File能新建.删除.重命名文件和目录,但File不能访问文件内容本身.如果需要访问文件内容本身,则需要使用输入 ...

  9. JAVA.IO流学习笔记

    一.java.io 的描述 通过数据流.序列化和文件系统提供系统输入和输出.IO流用来处理设备之间的数据传输 二.流 流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数 ...

  10. java.IO输入输出流:过滤流:buffer流和data流

    java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...

随机推荐

  1. python pandas csv 大文件 DataFrame转换为List

    python 将大文件读取为 DataFrame 时,直接对整个文件进行读取会比较耗时,甚至内存还会不足. https://pandas.pydata.org/pandas-docs/stable/u ...

  2. vue 格式化时间戳

    前言 有时候我们需要前端处理后端传过来的时间戳进行格式化为日期. Html部分 template中这样使用,需要处理的字段名,再加上过滤器方法 <el-table-column label=&q ...

  3. Go语言遍历字符串——获取每一个字符串元素

    遍历字符串有下面两种写法. 遍历每一个ASCII字符 遍历 ASCII 字符使用 for 的数值循环进行遍历,直接取每个字符串的下标获取 ASCII 字符,如下面的例子所示. theme := &qu ...

  4. jquery submit 解决多次提交

    jquery submit 解决多次提交 web应用中常见的问题就是多次提交,由于表单提交的延迟,有时几秒或者更长,让用户有机会多次点击提交按钮,从而导致服务器端代码的种种麻烦. 为了解决这个问题,我 ...

  5. Delphi CheckListBox 用法

    for i := CheckListBox1.Items.Count-1 downto 0 do //从后面往前面删 begin if CheckListBox1.Checked[i] then // ...

  6. [源码系列:手写spring] IOC第三节:Bean实例化策略InstantiationStrategy

    主要内容 在第二节中AbstractAutowireCapableBeanFactory类中使用class.newInstance()的方式创建实例,仅适用于无参构造器.  大家可以测试一下,将第二节 ...

  7. 方法重写-java se 进阶-day01

    1.方法重写的介绍 当子父类中,某方法存在相同的定义(方法名.参数.返回值)时,子类的方法会将父类的方法进行重写操作(覆盖) 2.方法重写与方法重载的区别 1.方法重载:又称Overload,在同一个 ...

  8. Ubuntu 分辨率设置不了

    最近换了个显示器,Ubuntu下竟然只能显示低分辨率,瞬间zhuo ji了,解决,留爪. 问题就不多说了,直接记录正题, 主要涉及2个命令cvt和xrandr, 主要注意的一点是:刚刚开始直接用命令写 ...

  9. mybatis报错Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.ArrayList and java

    原因 传入参数为List<String>不能用lists != '' 判断 解决 将lists != '' 的判断去掉或者改为lists .size>0 其他 如果是Integer类 ...

  10. Python+Appium+unittest案例

    代码如下: # coding=utf-8 import time import unittest from appium import webdriver class MyTestCase(unitt ...