文件数据IO操作:
1、 Reader和Writer
2、 转换流
3、 PrintWriter
4、 BufferedReader
扩展:
1、字符型与字符的编码:
Unicode万国码:为全球的每个文字分配一个唯一的数字。
2、如何将文字存储到文件?如何“编码”?
1、 java中的文字是16位整数序列
2、 文件中的数据是8位byte序列
3、 如何将字符char拆分为byte序列?采用“编码”
4、 字符编码:将字符序列拆分为byte序列的拆分方法称为字符的编码。
3、UTF-16BE编码:
1、 UTF-16BE编码:将字符切半
如:A:65 00000000 01000001
使用方法:String.getByte(“utf-16be”),输出时前面的0会省略
public void testUTF16() throws Exception {
String str="AB";//A是65 00000000 01000001
//B是66 00000000 01000010
byte[] utf16=str.getBytes("UTF-16BE");//分割为8位一个byte,显示的时候前面的0会省略
for(byte b:utf16) {
System.out.println(Integer.toBinaryString(b));//0/1000001/0/1000010
}
}
添加第三方的库:项目->新建文件夹->将解压出来的压缩文件添加进去,然后配环境,项目上面点击右键->属性->Java Build Path->右侧add jars,然后找到库名.jar文件->ok->将第一个小瓶子点开,选择source attachment->添加上面解压出来的压缩文件中的sources.jar->项目下面会多出来Referenced Libraries
2、 UTF-16BE的特点:支持65535个字符,中英文都是2个byte,定长编码;缺点:英文浪费空间,只能支持unicode4.0
4、UTF-8编码
采用的是变长字节:1~4字节:按照数值小到大采用1~4字节编码。支持全部的unicode,包括11万字,如果文字中英文为主体,编码最短。UTF-8是国际化(i18n)最优方案。支持世界上的所有文字。
5、GBK
中国国家标准,是变长编码,英文1字节,中文2字节,支持20000+中英文,GBK是中国本地化(l10n)最优方案!只有中文和英文。GB2312是GBK的子集(6000+字符)。
6、String.getBytes
Java API中的String.getBytes(“编码”)将字符串进行编码,编码为指定编码的结果。
.getBytes()是按照本地计算机默认编码
中文Windows:GBK
Linux:UTF-8/GBK
7、如何查询本地编码?
String encoding=System.getProperty("file.encoding");
public void testEncoding() {
String encoding=System.getProperty("file.encoding");
System.out.println(encoding);//GBK
}
8、如何解码?
new String(bytes):使用默认编码方案解码
new String(bytes,encoding):指定编码方案
new String(bytes,0,length.encoding):数组中的一部分指定编码
public void testUtf8() throws Exception {
//文字的编码测试
String str="AB中国";
byte[] utf8=str.getBytes("utf-8");//编码
for(byte b:utf8) {
String bin=Integer.toBinaryString(b&0xff);
//发生了自动类型转换,将8位数b转换为32位int,高位自动填充1,将1去掉的方法是&0xff
System.out.println(bin);
}
System.out.println();
String s=new String(utf8,"utf-8");//解码
String ss=new String(utf8,"GBK");//编码方案不一样,会出现乱码
System.out.println(s);
System.out.println(ss);
}
9、编码方案、编码、解码
编码方案:编码和解码的规则
编码:按照方案进行编码的动作
解码:按照方案进行解码的动作
如果编码和解码时候“编码方案”不一致,会出现乱码问题!
10、最后:ISO8859-1就是ASCII只支持英文256,不支持用中文,会将一个char转换为一个byte。
11、Java提供了读写文本文件的API,封装了文字的编码处理!
Reader和Writer:
1、字符流原理:
Reader是字符输入流的父类。
Writer是字符输出流的父类。
字符流是以字符(char)为单位读写数据的。一次处理一个unicode。
字符流的底层仍然是基本的字节流。
2、Reader与Writer常用方法,是抽象方法,不能单独用:
1、Reader的常用方法:
1、--int read()
读取一个字符,返回的int值“低16位”有效
2、--int read(char[] chs)
从该流中读取一个字符数组的length个字符并存入该数组,返回值为实际读取到的字符量。
2、Writer的常用方法:
1、--void write(int c)
写出一个字符,写出给定int值“低16位”表示的字符。
2、--void write(char[] chs)
将给定字符数组中所有字符写出。
3、--void write(String str)
将给定的字符写出。
4、--void write(char[] chs,int offset,int len)
将给定的字符数组中从offset处开始连续的len个字符写出。
转换流:
1、字符转换流原理:
下面两个类是扩展流,必须依赖于节点流。
1、InputStreamReader:字符输入流
使用该流可以设置字符集,并按照指定的字符集从流中按照该编码将字节数据转换为字符并读取。
2、OutputStreamWriter:字符输出流
使用该流可以设置字符集,并按照指定的字符集将字符转换为对应字节后通过该流写出。
2、指定字符编码InputStreamReader
InputStreamReader的构造方法允许我们设置字符集:
--InputStreamReader(InputStreamin,String charsetName)
基于给定的字节输入流以及字符编码创建ISR
--InputStreamReader(InputStream in)
该构造方法会根据系统默认字符集创建ISR
3、指定字符编码OutputStreamWriter
OutputStreamWriter构造方法:
--OutputStreamWriter (OutputStream out,String charsetName)
基于给定的字节输出流以及字符编码创建OSW
-- OutputStreamWriter (InputStream in)
该构造方法会根据系统默认字符集创建OSW
public void testTextFile() throws Exception {
OutputStreamWriter out=new OutputStreamWriter(
new BufferedOutputStream(//缓冲区
new FileOutputStream("demo.txt")),"UTF-8");
out.write('中');
out.write("ABC中国");
out.close();
}
public void testReaText() throws Exception {
InputStreamReader in=new InputStreamReader(
new BufferedInputStream(
new FileInputStream("demo.txt")),"utf-8");
// InputStreamReader in=new InputStreamReader(
// new BufferedInputStream(
// new FileInputStream("demo.txt")),"GKB");//会出现不支持这个编码异常
//in.read()从文件中读取byte然后解码为字符返回,填充到int的低16位
int c;
while((c=in.read())!=-1) {//如果没有读到文件末尾
char ch= (char)c;
System.out.print(ch+" ");//中 A B C 中 国
}
in.close();
}
PrintWriter:
扩展流,不能单独工作。
1、 print与println方法
PrintWriter提供了丰富的重载print和println方法。
2、 PrintWriter是具有自动行刷新的缓冲字符输出流,其提供了比较丰富的构造方法。其中一个方法:
---PrintWriter(OutputStream out,Boolean autoflush)
该方法提供了一个可以传入boolean值参数,该参数用于表示PrinterWriter是否具有自动行刷新。在网络通讯的时候使用。
public void testPrintWriter() throws Exception {
//最常见的文本文件输出
PrintWriter out=new PrintWriter(
new OutputStreamWriter(
new BufferedOutputStream(
new FileOutputStream("t.txt")),"GBK"));
out.println("Hello World!");
out.println("世界欢迎您!");
out.close();
}
public void testPrintWriter2() throws Exception {
PrintWriter out=new PrintWriter("t2.txt");//默认编码的简化版
out.println("Hello World!");
out.println("世界欢迎您!");
out.close();
}
public void testAutoFlush() throws Exception {
PrintWriter out=new PrintWriter(
new OutputStreamWriter(
new BufferedOutputStream(
new FileOutputStream("x.txt"))),true);
//如果自动打开flush功能文件中会出现Hi;如果没有打开,文件中可能没有Hi,原因是Hi在缓冲区,还没有及时写入到文件中
out.println("Hi");
//println()方法会自动执行flush()
//print()方法不会自动执行flush()
//不关闭文件是一个错误的写法,这里只是演示。
}
BufferedReader:
1、使用BF读取字符串
BufferedReader提供了一个可以便于读取一行字符串的方法
---String readLine()
该方法连续读取一行字符串,直到读取到换行符为止,返回的字符串中不包含该换行符。
2、构建BufferedReader
BufferedReader是缓冲字符输入流,其内部提供了缓冲区,可以提高读取效率。
BufferedReader的常用构造方法:
---BufferedReader(Reader reader)
public void testBufferedReader() throws Exception {
//最常见的文本文件读取方式
BufferedReader in=new BufferedReader(
new InputStreamReader(
new BufferedInputStream(
new FileInputStream("t.txt")),"GBK"));
String line;
//每次读取一行,返回null表示读取到EOF
while((line=in.readLine())!=null) {
System.out.println(line);
}
in.close();
}
总结:
文件的处理原则:每次读写一个byte
流:是一套非常便于扩展的API(使用了装饰器模式)
1、输入流:读取文件 in.read()
2、输出流:写出文件 out.write()
3、节点流:是流的扩展基础点
4、处理流(扩展流、过滤流):对节点流进行的功能扩展,扩展以后使用方便,一般都使用高级流,但是这些高级流必须都依赖节点流。
5、文本流:封装了文本 “编码、解码” 处理的输入输出流,也是高级流,必须依赖节点流,每次读写一个字符
6、字节流:每次读写一个字节,有节点流和扩展流
7、Java内存中的字符:16位整数,unicode编码值
8、文件中的数据:8位的byte
9、编码:解决了字符数据存储到“流”(文件)的矛盾
10、 文本文件:保存的是文本经过编码之后的byte数列,文本文件的长度,不是字符的长度。
11、 编码:UTF-8 UTF-16BE GBK(GB2312)
12、 Java提供了API解决编码问题:
1、String API 在内存中进行编码转换
char[]<-> byte[] 之间的转换
getBytes()
new String()
2、Reader Writer 是String(char)到文件的编码转换
char[]<-> 文件
read() 文件(byte[])à 内存字符char
write() 内存字符(char) à 文件(byte)
3、真正实现文字编码的API
InputStreamReader
OutputStringWriter
4、最常用的文本API,按行读写
PrintWriter
BufferedReader