数据读写API——IO流
1.Java 中的IO的作用
IO指的是Input和Output,主要目的是实现数据在存储介质之间的传输。【流:数据流,类比与水流的流动】
2.IO分类
按照操作单元来划分,可以分为字节流和字符流。
3.字节流和字符流的区别
字节流顾名思义操作的数据单元是1个字节,也就是8位;
那么问题来了,一个中文字符用GBK编码占用两个字节,用UTF-8占用三个字符。
字节流在传输有中文字符的数据时会产生编码错误。
而字符流可操作2个字节,也就是16位。那么在GBK的编码下,支持中文数据传输。
总结如下
- 字节流一次读取一个字节,字符流两个
- 字节流可以处理所有类型数据,字符流只能处理字符类数据
4.字符编码的前世今生
ASCII 码
计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0
和1
两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。
也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000
到11111111
。
上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。
【ASCII 码==英文字符和二进制之间的映射关系】
Unicode
世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。电子邮件常常出现乱码就是因为发信人和收信人使用的编码方式不一样。
可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码。
Unicode 当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639
表示阿拉伯字母Ain
,U+0041
表示英语的大写字母A
,U+4E25
表示汉字严
。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表。
Unicode 的问题
Unicode虽然实现了编码的一统,但Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
比如,汉字严
的 Unicode 是十六进制数4E25
,转换成二进制数足足有15位(100111000100101
),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题,第一个问题是,如何才能区别 Unicode 和 ASCII ?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0
,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:
1)出现了 Unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示 Unicode。
2)Unicode 在很长一段时间内无法推广,直到互联网的出现。
UTF-8
互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。
这里的关系是,UTF-8 是 Unicode 的实现方式之一。
UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
5.节点流,处理流
节点流:直接从数据源或目的地读写数据
处理流:不直接连接到数据源或目的地,而是“连接”在已存 在的流(节点流或处理流)之上,通过对数据的处理为程序提 供更为强大的读写功能。
常用流
InputStream/Reader:向外边读数据
OutpusStream/Writer:向外边写数据
节点流(文件流)
import java.io.*;
public class Main {
public static void main(String args[]) throws IOException
{
/**
* 读取文件
* 1.建立一个流对象,将已存在的一个文件加载进流。
* FileReader fr = new FileReader(new File(“Test.txt”));
* 2.创建一个临时存放数据的数组。
* char[] ch = new char[1024];
* 3.调用流对象的读取方法将流中的数据读入到数组中。
* fr.read(ch);
* 4. 关闭资源。
* fr.close();
*/
FileReader fr = null;
fr = new FileReader(new File("c:\\file.txt"));
char[] buf = new char[1024];
int len;
while ((len = fr.read(buf)) != -1)
{
System.out.print(new String(buf, 0, len));
}
fr.close();
/**
* 写入文件
* 1.创建流对象,建立数据存放文件
* FileWriter fw = new FileWriter(new File(“Test.txt”));
* 2.调用流对象的写入方法,将数据写入流
* fw.write(“atguigu-songhongkang”);
* 3.关闭流资源,并将流中的数据清空到文件中。
* fw.close();
*/
FileWriter fw = new FileWriter(new File("d:\\filewriter.txt"));
fw.write("9999999999999");
fw.close();
/**
* 在写入一个文件时,如果使用构造器FileOutputStream(file),则目录下有同名文
* 件将被覆盖。
* 如果使用构造器FileOutputStream(file,true),则目录下的同名文件不会被覆盖,
* 在文件内容末尾追加内容。
*/
}
}
缓冲流(一种处理流)
为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类 时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
BufferedInputStream 和 BufferedOutputStream
BufferedReader 和 BufferedWriter
只要关闭最外层流即可,关闭最外层流也 会相应关闭内层节点流。
flush()方法的使用:手动将buffer中内容写入文件。
import java.io.*;
public class Main {
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new FileReader("d:\\br.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\bw.txt"));
String str;
while ((str = br.readLine()) != null) { // 一次读取字符文本文件的一行字符
System.out.println(str);
bw.write(str); // 一次写入一行字符串
bw.newLine(); // 写入行分隔符
}
bw.flush(); // 刷新缓冲区
br.close();
bw.close();
}
}
转换流
转换流提供了在字节流和字符流之间的转换
Java API提供了两个转换流:
InputStreamReader:将InputStream转换为Reader
OutputStreamWriter:将Writer转换为OutputStream
- 字节流中的数据都是字符时,转成字符流操作更高效。
- 很多时候我们使用转换流来处理文件乱码问题。实现编码和 解码的功能。
import java.io.*;
public class Main {
public static void main(String args[]) throws IOException
{
/**
* 将old.txt中的文件读出写入到new.txt里
*/
FileInputStream fis = new FileInputStream("d:\\old.txt");
FileOutputStream fos = new FileOutputStream("d:\\new.txt");
InputStreamReader isr = new InputStreamReader(fis, "GBK");
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
BufferedReader br = new BufferedReader(isr);
BufferedWriter bw = new BufferedWriter(osw);
String str = null;
while ((str = br.readLine()) != null) {
bw.write(str);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}
参考资料:
字符编码笔记:ASCII,Unicode 和 UTF-8https://link.zhihu.com/?target=http%3A//www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
数据读写API——IO流的更多相关文章
- Java API —— IO流(数据操作流 & 内存操作流 & 打印流 & 标准输入输出流 & 随机访问流 & 合并流 & 序列化流 & Properties & NIO)
1.操作基本数据类型的流 1) 操作基本数据类型 · DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型.应用程序可以使用数据输出 ...
- Java API —— IO流( FileInputStream & FileOutputStream & BufferedInputStream & BufferedOutputStream )
1.IO流概述 · IO流用来处理设备之间的数据传输 · 上传文件和下载文件 · Java对数据的操作是通过流的方式 · Java用于操作流的对象都在IO包中 2.IO ...
- 【Android】数据存储-java IO流文件存储
1.数据持久化:将在内存中的瞬时数据保存在存储设备中.瞬时数据:设备关机数据丢失.持久化技术提供一种机制可以让数据在瞬时状态和持久状态之间转换. 2.Android中简单的三种存储方式:文件存储.Sh ...
- Java API —— IO流小结
练习题: 1.复制文本文件 package cn.itcast_01; import java.io.BufferedReader; import java.io.BufferedWriter; im ...
- 四种读写方案IO流 (JAVA)
File类用于访问文件或目录的属性 流:指一连串流动的字符,是以先进先出的方式发送信息的通道.程序和数据源之间是通过流联系起来的. 第一套:字节流读取写入方案 FileInputStream :字节流 ...
- java IO流体系--通识篇
1.I/O流是什么 Java的I/O流是实现编程语言的输入/输出的基础能力,操作的对象有外部设备.存储设备.网络连接等等,是所有服务器端的编程语言都应该具备的基础能力. I = Input(输入),输 ...
- 分享知识-快乐自己:IO流基本操作
点我参考常用API: IO图解: 相关理论: 流的概念和作用: 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将 ...
- java IO流详解
流的概念和作用 学习Java IO,不得不提到的就是JavaIO流. 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
- IO流
流的概念和作用 学习JavaIO,不得不提到的就是JavaIO流. 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特 ...
随机推荐
- RabbitMQ 从入门到精通(二)
目录 1. 消息如何保障百分之百的投递成功? 1.1 方案一:消息落库,对消息状态进行打标 1.2 方案二:消息的延迟投递,做二次确认,回调检查 2. 幂等性 2.1 幂等性是什么? 2.2 消息端幂 ...
- JAVA 使用 POI进行读取Excel表格示例
导包 编码 public class PoiTest { /** * 最终效果 * 表头一内容0 表头二内容1 表头三内容2 表头一内容1 表头二内容2 表头三内容3 表头一内容2 表头二内容3 表头 ...
- TensorFlow笔记-模型的保存,恢复,实现线性回归
模型的保存 tf.train.Saver(var_list=None,max_to_keep=5) •var_list:指定将要保存和还原的变量.它可以作为一个 dict或一个列表传递. •max_t ...
- Adaboost原理推导
Adaptive Boosting是一种迭代算法.每轮迭代中会在训练集上产生一个新的学习器,然后使用该学习器对所有样本进行预测,以评估每个样本的重要性(Informative).换句话来讲就是,算法会 ...
- ArcGIS API For JavaScript 开发(三)使用小部件设计页面框架
其实上一个的鹰眼.比例尺.图例等都是小部件:这篇文章主要是页面布局设计,dojo提供了非常多的小部件,从功能的角度可以分为3大类:表单小部件.布局小部件和应用小部件. 表单小部件于HTML中的表单部件 ...
- C# Winform程序如何使用ClickOnce发布并自动升级(图解)
有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...
- java并发笔记之java线程模型
警告⚠️:本文耗时很长,先做好心理准备 java当中的线程和操作系统的线程是什么关系? 猜想: java thread —-对应-—> OS thread Linux关于操作系统的线程控制源码: ...
- 负载分配—DNS的域名解析
DNS(Domain Name System)是因特网的一项服务,它作为域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网.人们在通过浏览器访问网站时只需要记住网站的域名即可,而不需 ...
- Android 开发环境之 VMware 虚拟机(android8.1)
VM版本14 在官网下载androidx86的VMDK文件 官方下载地址 (VMDK文件是VMware的专用文件,比iso镜像文件安装要简便许多,内部已经配置好了,只需要按照虚拟机安装普通流程即可) ...
- ASP.NET Core Identity自定义数据库结构和完全使用Dapper而非EntityFramework Core
前言 原本本节内容是不存在的,出于有几个人问到了我:我想使用ASP.NET Core Identity,但是我又不想使用默认生成的数据库表,想自定义一套,我想要使用ASP.NE Core Identi ...