一、概念

在Java中,文件的输入和输出是通过流(Stream)来实现的。一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是 Internet 上的某个 URL。对于流而言,我们不用关心数据是如何传输的,只需要向源端输入数据,从目的端获取数据即可。

流按照处理数据的单位,可以分为字节流和字符流。字节流的处理单位是字节,通常用来处理二进制文件,例如音乐、图片文件等。而字符流的处理单位是字符,因为Java采用Unicode编码,Java字符流处理的即为Unicode字符,所以在操作汉字、国际化等方面,字符流具有优势。

二、字节流

所有的字节流类都继承自InputStream 和 OutputStream 这两个抽象类,下面列举了5个输入字节流类,输出字节流类和输入字节流类存在对应关系,这个就不一一列举了。

  • FileInputStream:把一个文件作为输入源,从本地文件系统中读取数据字节,实现对文件的读取操作。
  • ByteArrayInputStream:把内存中的一个缓冲区作为输入源,从内存数组中读取数据字节。
  • ObjectInputStream:对以前使用过ObjectOuputStream写入的基本数据和对象进行反序列化,用于恢复那些以前序列化的对象,注意这个对象所属的类必须实现Serializable接口。
  • PipeInputStream:实现了管道的概念,从线程通道中读取线程字节。主要在线程中使用,用于两个线程间通信。
  • SequenceInputStream:表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
  • System.in:从用户控制台读取数据字节,在System类中,in是 InputStream 类的静态导入。
    public static void main(String[] args) {
InputStream in = null;
OutputStream out = null; try {
//得到输入流
in = new FileInputStream("E:\\test\\a.txt");
//得到输出流
File file = new File("E:\\test\\b.txt");
if (!file.exists()) {
file.createNewFile();
}
out = new FileOutputStream(file, true);
int i;//从输入流读取一定数量的字节,返回 0 到 255 范围内的 int 型字节值
while ((i = in.read()) != -1) {
out.write(i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

三、字符流

所有的字符流类都继承自Reader 和 Writer 这两个抽象类,其中Reader是用于读取字符流的抽象类,Writer是用于写入字符流的抽象类。

Reader 和 Writer 要解决的最主要问题是国际化。原先的 I/O 类库只支持8位的字节流,因此不能很好的处理16位的Unicode字符。Unicode 是国际化的字符集,这样增加了Reader 和 Writer之后,就可以自动在本地字符集和Unicode国际化字符集之间进行转换。

  • FileReader:与FileInputStream对应,从文件系统中读取字符序列。
  • CharArrayReader:与ByteArrayInputStream 对应,从字符数组中读取数据。
  • PipedReader:与PipedInputStream 对应,从线程管道中读取字符序列。
  • StringReader:从字符串中读取字符序列。
    /**
* 由于是字符,存在编码不一致导致乱码的问题
* @param args
*/
public static void main(String[] args) {
Reader reader = null;
Writer writer = null; try {
//得到输入流
reader = new FileReader("E:\\test\\a.txt");
//得到输出流
writer = new FileWriter("E:\\test\\c.txt", true);
char[] chars = new char[50];
int i;
while ((i = reader.read(chars)) != -1) {
writer.write(chars, 0, i);
writer.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

四、缓冲流

前面介绍的字节流、字符流都是无缓冲的输入、输出流,这就意味着,每一次的读、写操作都会交给操作系统来处理。这样的做法可能会对系统的性能造成很大的影响,因为每一次操作都可能引起磁盘硬件的读、写或网络的访问。因此,对于字节流和字符流,一般不直接使用。

缓存流是一种装饰器类,目的是让原字节流、字符流 新增缓冲的功能。以字符缓冲流为例进行说明,字符缓冲流从字符流中读取、写入字符,不立刻要求系统进行处理,而是缓冲部分字符,从而实现按规定字符数、按行等方式高效的读取或写入。

字节缓冲流:

    public static void main(String[] args) {
BufferedInputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new FileInputStream("E:\\test\\a.txt"));
out = new BufferedOutputStream(new FileOutputStream("E:\\test\\e.txt", true));
byte[] b = new byte[1024];
int i;
// 并不是每次都能读到 1024 个字节,所以用 i 作为每次数据读取的长度,否则会出现文件损坏的错误
while ((i = in.read(b)) != -1) {
out.write(b, 0, i);
out.flush();//手动刷新该流的缓冲,立即将他们写入预期目标
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

字符缓冲流:

    public static void main(String[] args) {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
//设置文件编码,解决文件乱码问题
//将字节流转换为字符流,实际上使用了一种设计模式——适配器模式
InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\test\\a.txt"), "GBK");
bufferedReader = new BufferedReader(isr);
bufferedWriter = new BufferedWriter(new FileWriter("E:\\test\\d.txt"));
String s;
while ((s = bufferedReader.readLine()) != null) {
bufferedWriter.write(s);
bufferedWriter.newLine();//按行读取,写入一个分行符,否则所有内容都在一行显示
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (bufferedWriter != null) {
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Java 文件流操作.的更多相关文章

  1. java文件流操作

    package common; import java.io.*;import java.math.BigDecimal;import java.util.ArrayList;import java. ...

  2. Java IO流操作汇总: inputStream 和 outputStream【转】

    我们在进行Android java 开发的时候,经常会遇到各种IO流操作.IO流操作一般分为两类:字符流和字节流.以“Reader”结尾都是字符流,操作的都是字符型的数据:以“Stream”结尾的都是 ...

  3. java字符流操作flush()方法及其注意事项

    java字符流操作flush()方法及其注意事项   flush()方法介绍 查阅文档可以发现,IO流中每一个类都实现了Closeable接口,它们进行资源操作之后都需要执行close()方法将流关闭 ...

  4. delphi 基础之三 文件流操作

    文件流操作 Delphi操作流文件:什么是流?流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具.在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的, ...

  5. (C/C++学习)2.C语言中文件流操作基本函数总结

    函数所在头文件:stdio.h 说明:前半部分主要为对各个文件流操作函数的例举,后半部分着重于上机运行分析.文中部分引用自王桂林老师的C/C++课件. 1.FIELE *fopen(const cha ...

  6. 全面吃透JAVA Stream流操作,让代码更加的优雅

    全面吃透JAVA Stream流操作,让代码更加的优雅 在JAVA中,涉及到对数组.Collection等集合类中的元素进行操作的时候,通常会通过循环的方式进行逐个处理,或者使用Stream的方式进行 ...

  7. java 文件类操作(转载)

    11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...

  8. java文件读写操作

    Java IO系统里读写文件使用Reader和Writer两个抽象类,Reader中read()和close()方法都是抽象方法.Writer中 write(),flush()和close()方法为抽 ...

  9. java文件读写操作类

    借鉴了项目以前的文件写入功能,实现了对文件读写操作的封装 仅仅需要在读写方法传入路径即可(可以是绝对或相对路径) 以后使用时,可以在此基础上改进,比如: 写操作: 1,对java GUI中文本框中的内 ...

随机推荐

  1. Java中的NIO基础知识

    上一篇介绍了五种NIO模型,本篇将介绍Java中的NIO类库,为学习netty做好铺垫 Java NIO 由3个核心组成,分别是Channels,Buffers,Selectors.本文主要介绍着三个 ...

  2. Dubbo 源码分析 - 服务引用

    1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...

  3. Python selenium webdriver设置加载页面超时

    1.  pageLoadTimeout: pageLoadTimeout方法用来设置页面完全加载的超时时间,完全加载即页面全部渲染,异步同步脚本都执行完成.没有设置超时时间默认是等待页面全部加载完成才 ...

  4. 深度学习Tensorflow生产环境部署(上·环境准备篇)

    最近在研究Tensorflow Serving生产环境部署,尤其是在做服务器GPU环境部署时,遇到了不少坑.特意总结一下,当做前车之鉴. 1 系统背景 系统是ubuntu16.04 ubuntu@ub ...

  5. 一键访问Google和YouTube等国外知名网站

    1.首先打开快速安全通道网站,点击注册!网站地址 https://www.faststunnel.xyz/GWx6uy0M 2.注册好之后下载插件 3.将插件下载完后拖到浏览器安装 4.登录插件,即可 ...

  6. document.getElementById 和 document.getElementsByClassName获取DOM元素的区别

    想必小伙伴们对于 JS 获取DOM的几种方法早已烂熟于心,了然于胸,   尤其是 document.getElementById 和 document.getElementsByClassName, ...

  7. QMQ去哪儿网-mq中间件(启动失败)

    简介 去哪儿网近日宣布开源其内部广泛使用的消息中间件 QMQ .QMQ 自 2012 年诞生以来在去哪儿网所有业务场景中广泛的应用,包括跟交易息息相关的订单场景: 也包括报价搜索等高吞吐量场景.目前在 ...

  8. 用 VSCode 编写 python

    一.coding 1.选择一个Python解释器 通过命令选项板(⇧⌘P),键入Python:Select Interpreter命令,然后选择一个解释器. 成功后左下角出现: 2.运行代码 二.重构 ...

  9. AI - Tips

    01- Playground http://playground.tensorflow.org TensorFlow的网页工具Playground提供了几种简单类型的data,可以调节网络结构.学习率 ...

  10. Xamarin.Android 使用 SimpleAdapter 打造 ListView 万能适配器

    第一步:创建 layout1.axml 来展示列表详细内容 <?xml version="1.0" encoding="utf-8"?> <L ...