java常用到的知识点总结之IO流

原创 2016年08月31日 15:25:23

IO流:
IO流在java中是会经常用到的,下面对IO流做一个总结。今天主要介绍IO流中的字节流、字符流、转换流、对象流。

首先我们来看字节流,字节流就是对字节进行操作的流对象,对字节进行操作的流对象的基类有两个,一个是InputStream(字节输入流),另外一个是OutputStream(字节输出流).
下面我们来看看这两种流的使用:
首先看InputStream,由于InputStream是一个抽象类,不能够创建对象,所以这里我借助FileInputStream这个类来对一个文件进行读取,FileInputStream是InputStream的一个子类。
public static void main(String[] args) {
		InputStream is = null;
		try {
			is = new FileInputStream("a.txt");
			int len = -1;
			while ((len = is.read()) != -1) {
				System.out.println((char) len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
见如上代码:我们能够知道在java Project的项目根目录中有一个a.txt的文件,定义了一个int类型的变量len,然后使用while循环,循环的条件是(len=is.read())!=-1,输入流读取数据的时候,read()读取到的是当前字节所对应的int值,如果到文件的末尾也就是流的末尾的时候就返回-1,接着我们将len转换为char类型就可以看到文件中的内容了。
对于读取到的内容要注意,很多初学者有疑问,我使用字节流去读文件,为什么汉子部分都是?号,英文和数字却是完好无损的,因为英文和数字都只占一个字节,而汉子的话占用2个字节,UTF-8码表中的汉子更是占三个字节。当我们一个字节一个字节地读的话,那么汉字显然就被拆分了,在ASCII码表中查找不到就显示?号了。
那么如果我们一定要字节流能够读取汉字而且能够完好无损地显示该怎么办呢?看如下代码:
<span style="white-space:pre">			</span>..........................
<span style="white-space:pre">			</span>is = new FileInputStream("a.txt");
			int len = -1;
			byte[] bt = new byte[1024];
			while ((len = is.read(bt)) != -1) {
				System.out.println(new String(bt,0,len));
			}
<span style="white-space:pre">			</span>................................

我们可以看到修改的部分,使用InputStream的read方法的一个重载方法read(byte[] b):
参数:b - 存储读入数据的缓冲区。 返回:读入缓冲区的总字节数;如果因为已经到达流末尾而不再有数据可用,则返回 -1。 这样我们的字节数组定义为1024个字节,那么文件中根本达不到1024个字节,所以可以一次性读取出来,然后通过转换成字符串输出这样就可以将汉字完整输出了,因为汉字并没有被拆分。如果文件中的内容大于1024个字节的话,while循环就会进行两次,就会造成换行输出,也就是输出两行。
接着看OutputStream,OutputStream是字符输出流,输出意味着它能够将一些数据输出出去,由于OutputStream也是抽象类不能够创建对象,所以利用多态采用FileOutputStream为例。
public static void main(String[] args) {
		OutputStream os = null;
		try {
			os = new FileOutputStream("b.txt");
			os.write("呵呵\n".getBytes());
			os.write(97);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

通过上面代码我们可以看到,os = new FileOutputStream("b.txt");我们操作的是项目目录下的文件b,如果在write的时候该文件不存在就会自动创建,如果文件存在就write,但是会将文件之前的内容覆盖掉,如果让它不覆盖呢,我们就使用FileOutputStream(String name,boolean append);这个重载的构造方法,后面的一个布尔值的参数代表是否追加内容。传入true代表追加,不覆盖,false代表不追加 就覆盖。这样我们可以利用os.write()方法对字节或者是字节数组进行写入,这里我们可以写汉字,ASCII表所对应的内容,写汉字时需要将String转换为字节数组写入。
下面我们来接触一下字符流:字符流很显然,可以读取或者写入字节,它们对应的基类是 Writer和Reader,继承自它们的有FileReader和FileWriter.下面来看一下FileReader:
public static void main(String[] args) {
		FileReader reader = null;
		try {
			reader = new FileReader("b.txt");
			char c = (char)reader.read();
			System.out.println(c);;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
代码中使用的是字符流FileReader,它一次可以读取一个字符,所以char c = (char)reader.read();若读取的是汉字转换成字符后也不会变成问号。下面看一下FileWriter
<span style="font-weight: normal;"><span style="white-space:pre">		</span>FileWriter writer = null;
		try {
			writer = new FileWriter("b.txt");
			writer.write("字符流");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}</span>
代码中FileWriter作为字符流,能够直接写出一个字符串,因为字符串也就是一个字符数组。字符流相对于字节流要方便很多。
字符流中最后为大家介绍两种高效流,为什么说他们高效呢?是因为它们在内存中存在一个缓存区,它们分别是BufferedWriter和BufferedReader,和上面两个方法的不同之处在于他们多了两个方法,BufferedWriter拥有newLine()可以换一行,BufferedReader可以readLine()可以一行一行地读取。

转换流:InputStreamReader和OutputStreamWriter.转换流的作用:转换流有两个作用,1.它可以将一个字节流转换为字符流。2.它们在读取或者写入的时候可以指定编码方式。我们来看看InputStreamReader和OutputStreamWriter.
public static void main(String[] args) {
		InputStreamReader reader = null;
		try {
			reader = new InputStreamReader(new FileInputStream("b.txt"));
			int len = -1;
			while((len = reader.read())!=-1){
				System.out.println((char)len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
通过上面的代码,我们看到InputStreamReader可以读出来的内容转换为char类型,就算是汉字也不会变成?,说明它就是按照字符进行读取的,这就证明了它将FileInputStream字节流转换成了字符流,当然它也可以将内容读取到一个char数组中,原理是和字节流读取到字节数组中一样的。reader = new InputStreamReader(new FileInputStream("b.txt"),"utf-8");可以指定读取时的编码。下面看看字符输出流:
OutputStreamWriter writer = null;
		try {
			writer = new OutputStreamWriter(new FileOutputStream("b.txt"));
			writer.write("字符流");
上面代码看到,字符输出流可以直接输出一个字符串,我们知道字符串也就是一个字符数组,所以它能够直接输出一个字符串是正常的。证明OutputStreamWriter将FileOutputStream转换成了字符流。writer = new OutputStreamWriter(new FileOutputStream("b.txt"),"utf-8");可以指定输出内容的编码格式。
对象流:ObjectOutputStream、ObjectInputStream
对象流其实就是将一个对象转换成流的形式,和将一个流转换为对象。这就需要对象能够进行序列化。那么一个对象如何能够进行序列化和反序列化呢?我们需要了解一个接口,这个接口是标记接口,它是Serializable接口,为什么说它是标记接口呢?因为它的内部什么都没有,它只起到标记的作用,实现了它的类就代表能够被序列化和反序列化。下面我们需要将一个对象以流的形式存入文件中,具体看代码:
public class Test {
	public static void main(String[] args) throws Exception{
		Person p = new Person("张三",15);
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file.txt"));
		oos.writeObject(p);
		
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file.txt"));
		Person p1 = (Person) ois.readObject();
		System.out.println(p1);
		oos.close();
		ois.close();
	}
}

class Person implements Serializable{
	public String name;
	public int age;
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}
代码中Person类实现了Serializabale接口,代表它可以被序列化,这样我们就可以实例化一个ObjectOutputStream,调用其writeObject方法将Person对象p,写入带文件file.txt中。也可以实例化一个ObjectInputStream将其从文件中读取出来,readObject()方法返回的是一个Object对象,这里我们知道其实他就是Person对象,所以我们可以使用多态的向下转型,将其转换成Person对象,最终输出结果是Person [name=张三, age=15]。
好了今天IO流就总结这些吧!





版权声明:本文为博主原创文章,未经博主允许不得转载。

Java基础之IO流知识点总结三

File类: 该类的出现是对文件系统中的文件以及文件夹进行对象的封装。可以通过对象的思想来操作文件以及文件夹。   1.  构造函数: File(String filename):将一...
  • MF_Mofy
  • MF_Mofy
  • 2017年12月05日 10:41
  • 36

黑马程序员-Java中IO流知识点总结

一、流的分类  1、按功能分   读取流:InputStream Reader   写出流:OutPutStream Writer  2、按流的类型分类            字节流:Inp...

Java基础之IO流知识点总结一

Java基础知识----IO流(包括字节输入流和输出流,字符输入流和输出流)

Java IO流知识点总结

本主要对java的IO流知识点做比较全面的总结,但是没有很深入阐述。

Java基础之IO流知识点总结二

字节流的缓冲区 缓冲区的出现提高了对流的操作效率。 原理:其实就是将数组进行封装。 对应的对象:    BufferedWriter:       特有方法:newLine():跨平台的换行符。   ...
  • MF_Mofy
  • MF_Mofy
  • 2017年12月05日 10:39
  • 21

Java IO知识点总结三(字符流)

在程序中一个字符等于两个字节,Java提供了Reader和Writer两个专门操作字符的类。 1.字符流输出Writer类 同样,该类本身为一个抽象类,通过其子类实现具体的操作 FileWr...

Java中IO流知识点总结

一、流的分类   1、按功能分   读取流:InputStream Reader   写出流:OutPutStream Writer   2、按流的类型分类   字节流:...

java中IO流的知识点总结

1.流的概念流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。2.IO流...

黑马程序员 知识点总结-Java IO(二)字符流

---------------------- ASP.Net+Android+IOS">http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发...

黑马程序员 知识点总结-Java IO(三)字节流

---------------------- ASP.Net+Android+IOS">http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java常用到的知识点总结之IO流
举报原因:
原因补充:

(最多只允许输入30个字)