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

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流就总结这些吧!






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,作为文本AI助手,我无法绘制思维导图。但是,我可以为您提供一个简要的java IO流知识点总结Java IO流Java中用于处理输入和输出的机制。它提供了一种有效的方式来读取和写入数据,以及与文件、网络和其他设备进行交互。 Java IO流包括字节流字符流两种类型。字节流以字节为单位进行操作,适用于处理二进制数据。而字符流以字符为单位进行操作,适用于处理文本数据。 常用字节流包括InputStream和OutputStream类,用于读取和写入字节数据。常用字符流包括Reader和Writer类,用于读取和写入字符数据。可以通过使用字节流字符流的组合来实现不同类型数据的读写操作。 在Java IO流中,还有一些特殊的,如缓冲、转换对象等。缓冲提供了缓冲区来提高IO性能。转换用于处理字符编码和解码。对象用于对Java对象进行读写操作。 此外,Java IO流还包括一些常用的类和方法,如File类用于处理文件和目录,RandomAccessFile类用于对文件进行随机访问,FileInputStream和FileOutputStream类用于读写文件等。 通过组合和使用不同类型的和类,您可以实现各种复杂的IO操作,如读写文件、网络通信、序列化对象等。 希望这个简要总结对您有所帮助。如果您有任何更具体的问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [万字长文+思维导图帮你梳理 Java IO ,还学不会你来打我(值得收藏)](https://blog.csdn.net/a1405/article/details/116766237)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值