1 输入流和输出流

输入流,数据从源数据源流入程序的过程称为输入流。可以理解为从源数据源读取数据到程序的过程。

输出流,数据从程序流出到目的地的过程称为输出流。可以理解为把数据从程序写入目的地的过程。

数据源一般指提供数据的原始媒介,一般常见有文件、数据库、云端、其他硬件等能提供数据的媒介。

2 流的分类

3 InputStream/OutputStream

InputStream 是所有字节输入流的抽象父类,提供了以下方法:

  • read() 读取一个字节
  • read(byte[] buf) 读取一定量的字节到缓冲区数组 buf中。

FileInputStream 文件字节输入流,是 InputStream 的一个子类,专门用于从文件中读取字节到程序内存中。

 //需求:从文件读取一个字节
public static void main(String[] args) {
File file = new File("d:\\javatest\\a.txt"); // 【1】创建管道
FileInputStream in = null; try {
in = new FileInputStream(file); // 【2】从管道读取一个字节
/*
int t;
t = in.read();
t = in.read();
t = in.read();
t = in.read();
*/
// System.out.println(t); // 循环读取一个字节
int t;
StringBuilder sb = new StringBuilder();
while( (t=in.read()) != -1 ) {
sb.append((char)t);
}
System.out.println(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} // 【3】关闭流管道
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
 //一次读取多个字节
public static void main(String[] args) {
File file = new File("d:\\javatest\\a.txt"); // 【1】创建管道
FileInputStream in = null; try {
in = new FileInputStream(file); // 【2】从管道读取多个字节到缓冲区
/*
byte[] buf = new byte[5];
int len;
len = in.read(buf);
len = in.read(buf);
len = in.read(buf);
len = in.read(buf); for(byte b:buf) {
System.out.print((char)b+"\t");
}
System.out.println(len);
*/ // 通过循环读取文件
byte[] buf = new byte[5];
int len;
StringBuilder sb = new StringBuilder();
while( (len=in.read(buf)) != -1 ) {
// 读取的内容是原始二进制流,需要根据编码的字符集解码成对于字符
String str = new String(buf,0,len);
sb.append(str);
}
System.out.println(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} // 【3】关闭流管道
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}

OutputStream 是所有字节输出流的抽象父类,提供了以下方法

  • write() 写入一个字节
  • write(byte[] buf) 写入一定量的字节到输出流

FileOutputStream 文件字节输出流,专门用于从内存中写入字节到文件中。

 public static void main(String[] args) {
File file = new File("d:\\javatest\\c.txt"); FileOutputStream out = null; try {
// 【1】创建输出流管道
out = new FileOutputStream(file); // 【2】写入数据到管道中
// 一次写入一个字节
/*
out.write(97);
out.write(98);
out.write(99);
*/ // 一次写入多个字节
String str = "hello world";
// gbk
/*
byte[] buf = str.getBytes();
out.write(buf);
*/ byte[] buf = str.getBytes("UTF-8");
out.write(buf); System.out.println("写入完成!"); } catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} // 【3】关闭流
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}

注意:

  1. 字符串写入文件时一定会存在编码问题。
  2. 通过字节流写入文件时,向管道写入一个字节,该字节立即写入文件中。

InputStream/OutputStream 用于字节的读写。主要用于读写二进制文件(图片、音频、视频),较少用于读写文本型文件。对于文本型文件可以使用 Reader/Writer 类。

4 Reader/Writer

Reader 是字符输入流的抽象父类,提供了

  • read() 一次读取一个字符
  • read(char[] cbuf) 一次读取多个字符到字符缓冲区cbuf,返回长度表示读取的字符个数。

FileReader 文件字符输入流,专门用于读取默认字符编码文本性文件。

 //需求:一次读取一个字符/多个字符到cbuf
public static void main(String[] args) throws IOException { File file = new File("d:\\javatest\\d.txt"); FileReader reader = new FileReader(file); // 【1】一次读取一个字符
/*
int c;
c = reader.read();
c = reader.read();
c = reader.read();
c = reader.read();
c = reader.read();
System.out.println((char)c);
*/ // 【2】一次读取多个字符到cbuf中
/*
char[] cbuf = new char[2];
int len;
len = reader.read(cbuf);
len = reader.read(cbuf);
len = reader.read(cbuf);
len = reader.read(cbuf);
System.out.println(Arrays.toString(cbuf));
System.out.println(len);
*/ char[] cbuf = new char[2];
int len;
StringBuilder sb = new StringBuilder();
while( (len=reader.read(cbuf)) != -1 ) {
sb.append(cbuf,0,len);
} System.out.println(sb);
}

Writer 是字符输出流的抽象父类,提供了

  • write()
  • write(char[] cbuf)
  • write(String str)

FileWriter 文件字符输出流,专门用于写入默认字符编码的文本性文件。为了提高效率,File-Writer内部存在一个字节缓冲区,用于对待写入的字符进行统一编码到字节缓冲区,一定要在关闭流之前,调用flush方法刷新缓冲区,才能完成写入。

 //需求:写入字符到文件中
public static void main(String[] args) throws IOException {
File file = new File("d:\\javatest\\f.txt"); FileWriter writer = new FileWriter(file); // 【1】一次写入一个字符
/*writer.write('中');
writer.write('国');*/ // 【2】一次写入多个字符
/*char[] cbuf = {'h','e','l','l','o','中','国'};
writer.write(cbuf);*/ // 【3】一次写入一个字符串
String str = "hello你好";
writer.write(str); // 刷新字节缓冲区
writer.flush(); // 关闭流通道
writer.close(); System.out.println("写入完成");
}

5 转换流

InputStreamReader继承于Reader,是字节流通向字符流的桥梁,可以把字节流按照指定编码 解码 成字符流。

OutputStreamWriter 继承于 Writer,是字符流通向字节流的桥梁,可以把字符流按照指定的编码 编码 成字节流。

  • 把一个字符串以utf8编码写入文件
 public class Test {
public static void main(String[] args) throws IOException { String str = "hello中国";
File file = new File("d:\\javatest\\g.txt"); // 【1】创建管道
FileOutputStream out = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(out, "utf8"); // 【2】写入管道
writer.write(str); // 【3】刷新缓冲区
writer.flush(); // 【4】关闭管道
out.close();
writer.close(); System.out.println("写入完成");
}
}
  • 读取utf8文件
 public class Test01 {
public static void main(String[] args) throws IOException { File file = new File("d:\\javatest\\g.txt"); // 【1】建立管道
FileInputStream in = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(in, "UTF-8"); char[] cbuf = new char[2];
int len; StringBuilder sb = new StringBuilder();
while( (len=reader.read(cbuf))!=-1 ) {
sb.append(cbuf, 0, len);
}
System.out.println(sb.toString()); }
}

Windows 平台默认的 utf8 编码的文本性文件带有 BOM 标识,java 转换流写入的 utf8 文件不带 BOM 标识。所以用 java 读取手动创建的 utf8 文件会出现一点乱码(?hello中国,"?"是 BOM 标识导致的)。

6 BufferedReader/BufferedWriter

BufferedReader 继承于Reader,提供了

  • read()
  • read(char[] cbuf)
  • readLine() 用于读取一行文本,实现对文本的高效读取。

BufferedReader 初始化时需要一个 Reader,本质上 BufferedReader 在 Reader 的基础上增加 readLine() 的功能。

 //需求:读取一首诗
public static void main(String[] args) throws IOException { // 按行读取gbk文本性文件 File file = new File("d:\\javatest\\i.txt"); // 【1】创建管道
FileReader reader = new FileReader(file);
BufferedReader br = new BufferedReader(reader); // 【2】读取一行
/*
String line = br.readLine();
line = br.readLine();
line = br.readLine();
line = br.readLine();
*/ String line;
while( (line=br.readLine()) != null) {
System.out.println(line);
}
}

BufferedWriter继承于Writer,提供了

  • write()
  • write(char[] cbuf)
  • write(String str)
  • newline() 写入一个行分隔符。
 //需求:以gbk编码写入一首诗到文件
public static void main(String[] args) throws IOException { File file = new File("d:\\javatest\\j.txt"); // 【1】创建gbk管道
FileWriter writer = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(writer); // 【2】写入一行
bw.write("窗前明月光,");
bw.newLine(); bw.write("疑似地上霜。"); // for win
// bw.write("\r\n"); // for unix/linux/mac
// bw.write("\n"); bw.write("举头望明月,");
bw.newLine(); // 【3】flush
bw.flush(); // 【4】关闭管道
bw.close();
writer.close();
}
 //需求:以utf8编码高效写入文件
public static void main(String[] args) throws IOException { File file = new File("d:\\javatest\\j-utf8.txt"); // 【1】创建utf8管道
FileOutputStream out = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
BufferedWriter bw = new BufferedWriter(writer); // 【2】写入一行
bw.write("窗前明月光,");
bw.newLine(); bw.write("疑似地上霜。"); // for win
bw.write("\r\n"); // for unix/linux/mac
// bw.write("\n"); bw.write("举头望明月,");
bw.newLine(); // 【3】flush
bw.flush(); // 【4】关闭管道
bw.close();
writer.close();
}

IO(上)的更多相关文章

  1. 终端IO(上)

    一.综述 终端IO有两种不同的工作方式: 规范方式输入处理.在这种方式中,终端输入以行为单位进行处理.对于每个读要求,终端驱动程序最多返回一行. 非规范方式输入处理.输入字符不以行为单位进行装配 如果 ...

  2. commons io上传文件

    习惯了是用框架后,上传功能MVC框架基本都提供了.如struts2,springmvc! 可是假设项目中没有使用框架.而是单纯的使用jsp或servlet作为action,这时我们就能够使用commo ...

  3. 解决 docker.io 上拉取 images Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout

    处理方式 使用如下命令获取 registry-1.docker.io 可用的 ip dig @114.114.114.114 registry-1.docker.io 看到如下输出结果 ; <& ...

  4. spartan6不能直接把时钟连到IO上

    1.问题的提出:spartan6中不允许时钟信号直接连到IO口上面? 2.解决办法: ODDR2的使用 ODDR2Primitive: Double Data Rate Output D Flip-F ...

  5. Redis持久化磁盘IO方式及其带来的问题   有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持

    转自:http://blog.csdn.net/kaosini/article/details/9176961 一.对Redis持久化的探讨与理解    redis是一个支持持久化的内存数据库,也就是 ...

  6. 弃用!Github 上用了 Git.io 缩址服务的都注意了

    GitHub 是面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub.对程序员来说,GitHub 可以说是开源精神之所系.在 GitHub 任何职业程 ...

  7. 关于解决python线上问题的几种有效技术

    工作后好久没上博客园了,虽然不是很忙,但也没学生时代闲了.今天上博客园,发现好多的文章都是年终总结,想想是不是自己也应该总结下,不过现在还没想好,等想好了再写吧.今天写写自己在工作后用到的技术干货,争 ...

  8. Linux网络编程-IO复用技术

    IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了.Linux中,提 ...

  9. 如何在ASP.NET 5上搭建基于TypeScript的Angular2项目

    一.前言 就在上月,公司的一个同事建议当前的前端全面改用AngularJs进行开发,而我们采用的就是ASP.NET 5项目,原本我的计划是采用TypeScript直接进行Angular2开发.所以借用 ...

  10. 使用Jekyll在Github上搭建博客

    最近在玩github,突然发现很多说明网站或者一些介绍页面全部在一个域名是*****.github.io上. 好奇!!!真的好奇!!!怎么弄的?我也要一个~~~ 于是去网站上查询了一下,找到了http ...

随机推荐

  1. Java事务不回滚的原因总结

    1.首先要检查数据的引擎,InnoDB支持事务,MyIsam不支持事务 2.  默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚.     spring aop  异常 ...

  2. BDD行为驱动简介及Pytest-bdd基础使用

    目录 BDD介绍 需求描述/用户场景 场景解析/实现 场景测试 Pytest-bdd的参数化 运行环境: pip insall pytest pytest-bdd pytest-selenium BD ...

  3. Java字节码例子解析

    举个简单的例子: public class Hello {     public static void main(String[] args) {         String string1 = ...

  4. Jmeter(十三)阶梯式压测

    阶梯式压测,就是对系统的压力呈现阶梯性增加的过程,每个阶段压力值都要增加一个数量值,最终达到一个预期值.然后保持该压力值,持续运行一段时间. Jmeter中有个插件可以实现这个场景,这个插件就是:Co ...

  5. HDU 2176 取(m堆)石子游戏 —— (Nim博弈)

    如果yes的话要输出所有情况,一开始觉得挺难,想了一下也没什么. 每堆的个数^一下,答案不是0就是先取者必胜,那么对必胜态显然至少存在一种可能性使得当前局势变成必败的.只要任意选取一堆,把这堆的数目变 ...

  6. Leetcode题目236.二叉树的最近公共祖先(中等)

    题目描述: 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先 ...

  7. 软工-js learning

    使用教程JavaScript Standards Reference Guide-阮一峰 9.6-9.15学习进程: 1.导论 概述 JavaScript的历史 2.语法 基本语法 数据类型 数值 字 ...

  8. git-本机内容git至github

    1.修改仓库的名字 github中右上角/settings/Account: 修改后显示的变化: 2.本地和github账号创建联系 (base) localhost:~ ligaijiang$ ss ...

  9. 2.jdk1.8+springboot中http1.1之tcp连接复用实现

    接上篇:https://www.cnblogs.com/Hleaves/p/11284316.html 环境:jdk1.8 + springboot 2.1.1.RELEASE + feign-hys ...

  10. 【Makefile】Makefile的自动化变量$@、$^ 、$<等

    所谓自动化变量,就是这种变量会把“模式”中所定义的一系列的文件自动地挨个取出,直至所有的符合模式的文件都取完了.这种自动化变量只应出现在规则的命令中. $@ 表示规则中的目标文件集.在模式规则中,如果 ...