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. 小米oj 找小"3"(数位dp)

     找小"3" 序号:#40难度:困难时间限制:1000ms内存限制:10M 描述 给定一个奇数n,可得到一个由从1到n的所有奇数所组成的数列,求这一数列中数字3所出现的总次数.例如 ...

  2. [Luogu] Mayan游戏

    https://www.luogu.org/problemnew/show/P1312 太恶心了 #include <cstdio> #include <algorithm> ...

  3. Poj 2887 Big String(块状数组)

    Big String Time Limit: 1000MS Memory Limit: 131072K Description You are given a string and supposed ...

  4. HGOI20191115 模拟赛 题解

    Problem A 表演 有$n$个有点权的点,$m$个有边权的边.对于每个点$u$,输出从这个点出发到$v$,其路径权值的两倍加上v的点权和最小的值. 对于$100\%$的数据,满足$1 \leq ...

  5. Django基础之命名URL和URL反向解析

    在使用Django项目时,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等). 人们强烈希望不要硬编码这些URL(费力 ...

  6. Android学习——MediaProvider与Music模块

    一.MediaProvider数据库介绍 1. 关系型数据库 关系模型的物理表示是一个二维表格,由行和列组成. 2. MediaProvider数据库存储位置     /data/data/com.a ...

  7. linux中wget未找到命令

    (转)linux中wget未找到命令   转:https://blog.csdn.net/djj_alice/article/details/80407769 在装数据库的时候发现无法使用wget命令 ...

  8. Go之GOPATH与工作空间

    来自: GOPATH与工作空间 GOPOATH 设置 go 命令依赖一个重要的环境变量:$GOPATH 在类 Unix 环境下大概这样设置: exprt GOPATH=/home/apple/mygo ...

  9. 单调队列优化dp(捡垃圾的机器人)

    /************************************************************************* > File Name: a.cpp > ...

  10. quartz 定时器时间表达式

    按顺序依次为 秒(~) 分钟(~) 小时(~) 天(月)(~,但是你需要考虑你月的天数) 月(~) 天(星期)(~ =SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT) .年份(-) ...