字符集/编码集
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/**
目标:字符集/编码集
字符集:各个国家为自己国家的字符取的一套编号规则。
计算机的底层是不能直接存储字符的。
计算机的底层只能存储二进制。01
二进制就是可以转成10进制的。10进制就是整数编号。
101 = 1*2^0 + 0*2^1 + 1*2^2 = 5
110 = 0*2^0 + 1*2^1 + 1*2^2 = 6
00 = 0
01 = 1
10 = 2
11 = 3
结论:计算机的底层可以存储编号。
一个开关是1b = 1位
1B = 8b 计算机中的最小单位是字节B.
美国人:
8个开关一组就可以编码字符。 1个字节。
2^8 = 256
一个字节存储一个字符完全够用了。
a 97 01100001
b 98
A 65
B 66
0 48
1 49
这套编码是ASCII编码。
结论:英文和数字在底层存储的时候都是采用1个字节存储的。
中国人:
中国人的字符很多:
中国人一般采用2个字节编码一个中文字符。
这套编码叫:GBK编码。
它也必须兼容ASCII编码表。
...
美国人:
我来收集全球所有的字符,统一编号。这套编码叫 Unicode编码(万国码)
UTF-8就是变种形式。
UTF-8一个中文一般占3个字节。
它也必须兼容ASCII编码表。
小结:
字节是计算机的最小单位。
英文和数字在任何编码集中都是一样的,都占1个字节。
GBK编码中,1个中文字符一般占2个字节。
UTF-8编码中,1个中文字符一般占3个字节。
技术人员都应该使用UTF-8编码!
编码前与编码后的编码集必须一致才不会乱码!!
GBK 我爱你[oo oo oo] GBK 不会乱码!
GBK 我爱你[oo oo oo] UTF-8 会乱码!
英文和数字在任何编码集中可以通用,永远不会乱码!!
*/
public class CharsetDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
// 1、编码
String name = "ab1我爱你中国";
// 以默认编码UTF-8提取字节到字节数组中返回
byte[] bytes = name.getBytes();
System.out.println(bytes.length);
System.out.println(Arrays.toString(bytes));
// 以指定的编码GBK提取字节数
byte[] bytes1 = name.getBytes("GBK");
System.out.println(bytes1.length);
System.out.println(Arrays.toString(bytes1));
// 2、解码
String rs1 = new String(bytes); // 字节是UTF-8 默认代码是UTF-8解码 不乱码
System.out.println(rs1);
String rs11 = new String(bytes1); // 字节是GBK 默认代码是UTF-8解码 乱码的
System.out.println(rs11);
String rs2 = new String(bytes1 , "GBK"); // 字节是GBK ,代码指定GBK解码
System.out.println(rs2);
}
}
字节流
文件字节输入流-每次读取一个字节
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
/**
目标:字节输入流的使用。
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类,可以使用的)
文件字节输入流:FileInputStream
-- 作用:以内存为基准,把磁盘文件中的数据以字节的形式读取到内存中去。
按照字节读文件数据到内存中。
-- 构造器:
public FileInputStream(File file):创建字节输入流管道与源文件对象接通
public FileInputStream(String pathname):创建字节输入流管道与源文件路径接通。
-- 方法:
public int read(): 每次读取一个字节返回,读取完毕返回-1。
小结:
一个一个字节读取中文数据输出其实是被淘汰的,性能极差!
一个一个字节读取中文数据输出,会出现截断中文字节的情况,无法避免读取中文输出乱码的问题。
*/
public class FileInputStreamDemo01 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输入流管道与源文件对象接通
//File file = new File("day10_demo\\src\\itheima02.txt");
//InputStream is = new FileInputStream(file);
// 简化做法:
// 2、创建一个文件字节输入流管道与源文件路径接通
InputStream is = new FileInputStream("day10_demo\\\\src\\\\itheima02.txt");
// 3、public int read(); 每次读取一个字节返回,读取完毕返回-1
// int b1 = is.read(); // 读取1个字节(1滴水)
// System.out.println((char) b1);
//
// int b2 = is.read(); // 读取1个字节(1滴水)
// System.out.println((char) b2);
//
// int b3 = is.read(); // 读取1个字节(1滴水)
// System.out.println((char) b3);
//
// int b4 = is.read(); // 读取完毕返回-1
// System.out.println(b4);
// 4、使用循环读取字节,直到结束
// 定义一个整数变量存储读取的字节 : a b 2 我
// o o o [ooo]
int b;
while ( (b = is.read()) != -1){
System.out.print((char) b);
}
is.close();
}
}
文件字节输入流-每次读取一个字节数组
import java.io.FileInputStream;
import java.io.InputStream;
/**
目标:字节输入流的使用-按照字节数组读取。
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类)
a.FileInputStream文件字节输入流。
-- 作用:以内存为基准,把磁盘文件中的数据按照字节的形式读入到内存中的流。
简单来说,就是按照字节读取文件数据到内存。
-- 构造器:
1.public FileInputStream(File path):创建一个字节输入流管道与源文件对象接通。
2.public FileInputStream(String pathName):创建一个字节输入流管道与文件路径对接。
-- 方法:
1.public int read():每次读取一个字节返回!读取完毕会返回-1。
2.public int read(byte[] buffer):从字节输入流中读取字节到字节数组中去,
返回读取的字节数量,没有字节可读返回-1。
小结:
一个一个字节数组读取内容,性能得到了优化。
但是依然无法避免读取中文输出乱码的问题,会存在截断中文字节的可能!
*/
public class FileInputStreamDemo02 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输入流管道与源文件接通
InputStream is = new FileInputStream("day10_demo/src/itheima03.txt");
// ab2 ab2 cd
// ooo ooo oo
// [ab2] [ab2] [cd2]
// 2、public int read(byte[] buffer):从字节输入流中读取字节到字节数组中去,
// 返回读取的字节数量,没有字节可读返回-1。
// byte[] buffer = new byte[3];
// int len = is.read(buffer);
// String rs1 = new String(buffer);
// System.out.println("读取的个数:" + len);
// System.out.println(rs1);
//
// int len2 = is.read(buffer);
// String rs2 = new String(buffer);
// System.out.println("读取的个数:" + len2);
// System.out.println(rs2);
//
// int len3 = is.read(buffer);
// // 必须读取多少就倒出多少
// String rs3 = new String(buffer, 0 , len3);
// System.out.println("读取的个数:" + len3);
// System.out.println(rs3);
//
// int len4 = is.read(buffer);
// System.out.println(len4); // 返回-1 读取完毕了
// ab2 ab2 cd
// ooo ooo oo
// [cd2]
// ab2 ab2 cd 我 爱你中国
// ooo ooo oo [ooo]
byte[] buffer = new byte[3];
int len ; // 记录每次读取的字节数量
while ((len = is.read(buffer)) != -1){
// 必须读取多少就倒出多少
String result = new String(buffer , 0 , len);
System.out.print(result);
}
is.close();
}
}
拓展:解决字节输入流读取中文内容输出乱码的问题。
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
/**
拓展:解决字节输入流读取中文内容输出乱码的问题。
引入:
一个一个字节读取中文输出
一个一个字节数组读取中文输出均无法避免乱码。
如何实现读取可以避免乱码呢?
我们需要提供一个与文件字节刚刚好一样大的字节数组一桶水读完即可输出!
小结:
虽然字节输入流可以通过直接一个字节数组读取完全部内容避免中文乱码输出,但是当文件过大,会出现内存溢出!
所以:字节流读取文件文件内容输出根本不合适,要么乱码要么可能内存溢出,读取文本文件内容输出建议使用字符流!
*/
public class FileInputStreamDemo03 {
public static void main(String[] args) throws Exception {
// File file = new File("day10_demo/src/itheima04.txt");
// InputStream is = new FileInputStream(file);
// // 定义一个字节数组与文件的大小正好一模一样大。
// byte[] buffer = new byte[(int) file.length()];
// int len = is.read(buffer);
// System.out.println("读取的数量:" + len);
// System.out.println("读取的数量:" + file.length());
// System.out.println(new String(buffer));
InputStream is = new FileInputStream("day10_demo/src/itheima04.txt");
byte[] buffer = is.readAllBytes(); // JDK官方
System.out.println(new String(buffer));
is.close();
}
}
字节输出流的使用
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
/**
目标:字节输出流的使用。
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类)
a.FileOutputStream文件字节输出流。
-- 作用:以内存为基准,把内存中的数据,按照字节的形式写出到磁盘文件中去。
简单来说,把内存数据按照字节写出到磁盘文件中去。
-- 构造器:
public FileOutputStream(File file):创建一个字节输出流管道通向目标文件对象。
public FileOutputStream(String file):创建一个字节输出流管道通向目标文件路径。
public FileOutputStream(File file , boolean append):创建一个追加数据的字节输出流管道通向目标文件对象。
public FileOutputStream(String file , boolean append):创建一个追加数据的字节输出流管道通向目标文件路径。
-- 方法:
public void write(int a):写一个字节出去 。
public void write(byte[] buffer):写一个字节数组出去。
public void write(byte[] buffer , int pos , int len):写一个字节数组的一部分出去。
参数一,字节数组;参数二:起始字节索引位置,参数三:写多少个字节数出去。
小结:
记住。
换行: os.write("\r\n".getBytes()); // 换行
追加数据管道: OutputStream os = new FileOutputStream("day10_demo/out01.txt" , true); // 追加管道!!
*/
public class OutputStreamDemo04 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输出流管道与目标文件接通
// 写数据到文件,文件不需要我们自己创建!!因为会自动创建文件。
// OutputStream os = new FileOutputStream("day10_demo/src/itheima05_out.txt"); // 覆盖管道。一出生就删除数据。再写
OutputStream os = new FileOutputStream("day10_demo/src/itheima05_out.txt" , true); // 追加数据管道
// 2、写数据出去
// a.public void write(int a):写一个字节出去 。
os.write(97); // 写一个字节
os.write('A'); // 写一个字节
// os.write('磊'); // 写一个字节 【ooo】 会乱码
// 换行
os.write("\r\n".getBytes());
// b.public void write(byte[] buffer):写一个字节数组出去。
byte[] buffer = "我爱你中国abc".getBytes();
os.write(buffer);
// 换行
os.write("\r\n".getBytes());
// c. public void write(byte[] buffer , int pos , int len):写一个字节数组的一部分出去。
byte[] buffer1 = "我爱你中国abc".getBytes();
os.write(buffer1, 0 , 15);
// 换行
os.write("\r\n".getBytes());
// 注意:写数据必须刷新,或者关闭管道,否则数据可能写入失败
// os.flush(); // 刷新数据出去到文件中,流可以继续使用
os.close(); // 关闭包含了刷新的,关闭之后流不可以继续使用了。
}
}
IO流释放资源的方式
import java.io.*;
/**
目标:字节流做文件复制
源文件:C:\图片资源\meimei.jpg
目标文件:C:\图片资源\meimei-beauty.jpg
*/
public class CopyDemo05 {
public static void main(String[] args) {
try {
// 1、创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream("C:\\图片资源\\meimei.jpg");
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("C:\\图片资源\\meimei-beauty.jpg");
// 3、定义一个字节数组,负责复制数据
byte[] buffer = new byte[1024]; // 1KB
// 4、从字节输入流读取数据,倒出到字节输出流中去
int len ; // 读多少倒出多少
while ((len = is.read(buffer)) != -1){
os.write(buffer , 0 , len);
}
// 5、释放资源
os.close(); // 包含了刷新
is.close();
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
释放资源的方式-try-catch-finally
import java.io.*;
/**
目标:字节流做文件复制
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有资源释放操作;
}
手动释放资源
*/
public class CopyResourceDemo01 {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
// 1、创建一个字节输入流管道与源文件接通
is = new FileInputStream("C:\\图片资源\\meimei.jpg");
// 2、创建一个字节输出流管道与目标文件接通
os = new FileOutputStream("C:\\图片资源\\meimei-beauty.jpg");
// 3、定义一个字节数组,负责复制数据
byte[] buffer = new byte[1024]; // 1KB
// 4、从字节输入流读取数据,倒出到字节输出流中去
int len ; // 读多少倒出多少
while ((len = is.read(buffer)) != -1){
os.write(buffer , 0 , len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 5、释放资源
try {
if(os != null) os.close(); // 包含了刷新
} catch (IOException e) {
e.printStackTrace();
}
try {
if(is != null) is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
资源用完最终自动释放
import java.io.*;
/**
try(定义流对象){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
# 资源用完最终自动释放
定义输入流对象;
定义输出流对象;
try(输入流对象;输出流对象){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
# 资源用完最终自动释放
*/
public class CopyResourceDemo02 {
public static void main(String[] args) {
// JDK 1.7
try (
// 1、创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream("test/picture.png");
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("test/copy.png");
// int age = 23 ; // 这里只能放置资源对象,否则报错!
MyConn conn = new MyConn(); // 自定义资源。自动调用close方法
) {
// 3、定义一个字节数组,负责复制数据
byte[] buffer = new byte[1024]; // 1KB
// 4、从字节输入流读取数据,倒出到字节输出流中去
int len ; // 读多少倒出多少
while ((len = is.read(buffer)) != -1){
os.write(buffer , 0 , len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyConn implements Closeable{
@Override
public void close() throws IOException {
System.out.println("我是资源,我被人尴尬~~~~~~");
}
}
字节流做文件复制
import java.io.*;
/**
目标:字节流做文件复制
源文件:C:\图片资源\meimei.jpg
目标文件:C:\图片资源\meimei-beauty.jpg
*/
public class CopyResourceDemo03 {
public static void main(String[] args) throws FileNotFoundException {
// 1、创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream("C:\\图片资源\\meimei.jpg");
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("C:\\图片资源\\meimei-beauty.jpg");
// JDK 1.9
try (is ; os) {
// 3、定义一个字节数组,负责复制数据
byte[] buffer = new byte[1024]; // 1KB
// 4、从字节输入流读取数据,倒出到字节输出流中去
int len ; // 读多少倒出多少
while ((len = is.read(buffer)) != -1){
os.write(buffer , 0 , len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符流
字符输入流的使用
import java.io.FileReader;
import java.io.Reader;
/**
目标:字符输入流的使用。
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类)
c.FileReader:文件字符输入流。
-- 作用:以内存为基准,把磁盘文件的数据以字符的形式读入到内存。
简单来说,读取文本文件内容到内存中去。
-- 构造器:
public FileReader(File file):创建一个字符输入流与源文件对象接通。
public FileReader(String filePath):创建一个字符输入流与源文件路径接通。
-- 方法:
public int read(): 读取一个字符的编号返回! 读取完毕返回-1
public int read(char[] buffer):读取一个字符数组,读取多少个字符就返回多少个数量,读取完毕返回-1
小结:
字符流一个一个字符的读取文本内容输出,可以解决中文读取输出乱码的问题。
字符流很适合操作文本文件内容。
但是:一个一个字符的读取文本内容性能较差!!
*/
public class FileReaderDemo01 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字符输入流与源文件接通
Reader fr = new FileReader("day10_demo/src/itheima06.txt");
// ab徐
// 2、public int read(): 读取一个字符的编号返回! 读取完毕返回-1
// int ch1 = fr.read();
// System.out.println((char)ch1);
//
// int ch2 = fr.read();
// System.out.println((char)ch2);
//
// int ch3 = fr.read();
// System.out.println((char)ch3);
// 3、使用循环读取
int ch; // 定义一个整数存储每次读取的字符编号
while ((ch = fr.read()) != -1){
System.out.print((char) ch);
}
}
}
字符输入流的使用-按照字符数组读取
import java.io.FileReader;
import java.io.Reader;
/**
目标:字符输入流的使用-按照字符数组读取。
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类)
c.FileReader:文件字符输入流。
-- 作用:以内存为基准,把磁盘文件的数据以字符的形式读入到内存。
简单来说,读取文本文件内容到内存中去。
-- 构造器:
public FileReader(File file):创建一个字符输入流与源文件对象接通。
public FileReader(String filePath):创建一个字符输入流与源文件路径接通。
-- 方法:
public int read(): 读取一个字符的编号返回! 读取完毕返回-1
public int read(char[] buffer):读取一个字符数组,
读取多少个字符就返回多少个数量,读取完毕返回-1
小结:
字符流按照字符数组循环读取数据,可以解决中文读取输出乱码的问题,而且性能也较好!!
*/
public class FileReaderDemo02 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字符输入流与源文件接通
Reader fr = new FileReader("day10_demo/src/itheima06.txt");
// 1024 + 1
// 2、定义一个字符数组桶
char[] buffer = new char[1024]; // 1K字符
int len ; // 定义一个变量存储每次读取的字符数量。
while ((len = fr.read(buffer)) != -1) {
System.out.print(new String(buffer , 0 , len));
}
}
}
字符输出流的使用
import java.io.FileWriter;
import java.io.Writer;
/**
目标:字符输出流的使用。
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类)
d.FileWriter文件字符输出流的使用。
-- 作用:以内存为基准,把内存中的数据按照字符的形式写出到磁盘文件中去。
简单来说,就是把内存的数据以字符写出到文件中去。
-- 构造器:
public FileWriter(File file):创建一个字符输出流管道通向目标文件对象。
public FileWriter(String filePath):创建一个字符输出流管道通向目标文件路径。
public FileWriter(File file,boolean append):创建一个追加数据的字符输出流管道通向目标文件对象。
public FileWriter(String filePath,boolean append):创建一个追加数据的字符输出流管道通向目标文件路径。
-- 方法:
a.public void write(int c):写一个字符出去
b.public void write(String c)写一个字符串出去:
c.public void write(char[] buffer):写一个字符数组出去
d.public void write(String c ,int pos ,int len):写字符串的一部分出去
e.public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
小结:
字符输出流可以写字符数据出去,总共有5个方法写字符。
覆盖管道:
Writer fw = new FileWriter("Day10Demo/src/dlei03.txt"); // 覆盖数据管道
追加数据管道:
Writer fw = new FileWriter("Day10Demo/src/dlei03.txt",true); // 追加数据管道
换行:
fw.write("\r\n"); // 换行
结论:读写字符文件数据建议使用字符流。复制文件建议使用字节流。
*/
public class FileWriterDemo03 {
public static void main(String[] args) throws Exception {
// 1、创建一个字符输出流管道与目标文件接通
// Writer fw = new FileWriter("day10_demo/src/itheima07_out.txt"); // 覆盖管道
Writer fw = new FileWriter("day10_demo/src/itheima07_out.txt", true); // 追加管道
// a.public void write(int c):写一个字符出去
fw.write(97); // a
fw.write('A'); //
fw.write('磊'); // 无问题,真的是一个字符看待的。
fw.write("\r\n"); // 换行
// b.public void write(String c)写一个字符串出去
fw.write("我爱你中国abc");
fw.write("我爱你中国abc2");
fw.write("\r\n"); // 换行
// c.public void write(char[] buffer):写一个字符数组出去
char[] buffer1 = "此情可成追忆,只是当时已懵逼".toCharArray();
fw.write(buffer1);
fw.write("\r\n"); // 换行
// d.public void write(String c ,int pos ,int len):写字符串的一部分出去
fw.write("我爱你中国abc2" , 0 , 5);
fw.write("\r\n"); // 换行
// e.public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
char[] buffer2 = "此情可成追忆,只是当时已懵逼".toCharArray();
fw.write(buffer2, 0, 6);
fw.write("\r\n"); // 换行
// fw.flush(); // 刷新
fw.close(); //关闭流管道
}
}
缓冲流
import java.io.*;
public class ByteBufferDemo {
public static void main(String[] args) {
try (
// 这里只能放置资源,用完会自动释放的
// 1、字节输入流管道与源文件接通
InputStream is = new FileInputStream("C:/图片资源/zuiai.png");
// a、把低级的字节输入流管道包装成高级的缓冲字节输入流管道
BufferedInputStream bis = new BufferedInputStream(is);
// 2、字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("C:/图片资源/dlei-new.png");
// b、把低级的字节输出流管道包装成高级的缓冲字节输出流管道
BufferedOutputStream bos = new BufferedOutputStream(os);
){
// 3、定义一个字节数组
byte[] buffer = new byte[1024];
// 4、定义一个变量记录每次读取的字节数量 。 1024 + 1024 + 52 字节
int len ;
while ((len = bis.read(buffer)) != -1 ) {
bos.write(buffer , 0 , len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
利用字节流的复制统计各种写法形式下缓冲流的性能执行情况
import java.io.*;
/**
目标:利用字节流的复制统计各种写法形式下缓冲流的性能执行情况。
复制流:
(1)使用低级的字节流按照一个一个字节的形式复制文件。
(2)使用低级的字节流按照一个一个字节数组的形式复制文件。
(3)使用高级的缓冲字节流按照一个一个字节的形式复制文件。
(4)使用高级的缓冲字节流按照一个一个字节数组的形式复制文件。
源文件:C:\course\3-视频\18、IO流-文件字节输出流FileOutputStream写字节数据出去.avi
目标文件:C:\course\
小结:
使用高级的缓冲字节流按照一个一个字节数组的形式复制文件,性能好,建议开发使用!
*/
public class ByteBufferTimeDemo {
private static final String SRC_FILE = "C:\\course\\Java就业班154期\\day08-多线程一\\day08\\17、线程通信.avi";
private static final String DEST_FILE = "C:\\course\\";
public static void main(String[] args) {
// copy01(); // 使用低级的字节流按照一个一个字节的形式复制文件:实在慢的无法忍受,直接淘汰,永远禁止书写。
copy02(); // 使用低级的字节流按照一个一个字节数组的形式复制文件:较慢:不建议使用
copy03(); // 缓冲流一个一个字节复制: 较慢:不建议使用
copy04(); // 缓冲流一个一个字节数组复制: 飞快,建议使用。
}
//(4)使用高级的缓冲字节流按照一个一个字节数组的形式复制文件。
private static void copy04() {
long startTimer = System.currentTimeMillis();
try (
// 这里只能放置资源,用完会自动释放的
// 1、字节输入流管道与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
// a、把低级的字节输入流管道包装成高级的缓冲字节输入流管道
BufferedInputStream bis = new BufferedInputStream(is);
// 2、字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE +"4.avi");
// b、把低级的字节输出流管道包装成高级的缓冲字节输出流管道
BufferedOutputStream bos = new BufferedOutputStream(os);
){
// 3、定义一个字节数组
byte[] buffer = new byte[1024];
// 4、定义一个变量记录每次读取的字节数量 。 1024 + 1024 + 52 字节
int len ;
while ((len = bis.read(buffer)) != -1 ) {
bos.write(buffer , 0 , len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
long endTimer = System.currentTimeMillis();
System.out.println("缓冲流一个一个字节数组复制:" + (endTimer - startTimer) / 1000.0 + "s");
}
// (3)使用高级的缓冲字节流按照一个一个字节的形式复制文件。
private static void copy03() {
long startTimer = System.currentTimeMillis();
try (
// 这里只能放置资源,用完会自动释放的
// 1、字节输入流管道与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
// a、把低级的字节输入流管道包装成高级的缓冲字节输入流管道
BufferedInputStream bis = new BufferedInputStream(is);
// 2、字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE +"3.avi");
// b、把低级的字节输出流管道包装成高级的缓冲字节输出流管道
BufferedOutputStream bos = new BufferedOutputStream(os);
){
int bt ;
while ((bt = bis.read()) != -1 ) {
bos.write(bt );
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
long endTimer = System.currentTimeMillis();
System.out.println("缓冲流一个一个字节复制:" + (endTimer - startTimer) / 1000.0 + "s");
}
// (2)使用低级的字节流按照一个一个字节数组的形式复制文件。
private static void copy02() {
long startTimer = System.currentTimeMillis();
try (
// 这里只能放置资源,用完会自动释放的
// 1、字节输入流管道与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
// 2、字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE +"2.avi");
){
byte[] buffer = new byte[1024]; // 1KB
int len ;
while ((len = is.read(buffer)) != -1 ) {
os.write(buffer , 0 , len );
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
long endTimer = System.currentTimeMillis();
System.out.println("低级流一个一个字节数组复制:" + (endTimer - startTimer) / 1000.0 + "s");
}
// (1)使用低级的字节流按照一个一个字节的形式复制文件。
private static void copy01() {
long startTimer = System.currentTimeMillis();
try (
// 这里只能放置资源,用完会自动释放的
// 1、字节输入流管道与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
// 2、字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE +"1.avi");
){
int bt ;
while ((bt = is.read()) != -1 ) {
os.write(bt );
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
long endTimer = System.currentTimeMillis();
System.out.println("低级流一个一个字节复制:" + (endTimer - startTimer) / 1000.0 + "s");
}
}
字符缓冲输入流的使用
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;
/**
目标:字符缓冲输入流的使用。
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
字符缓冲输入流:BufferedReader
-- 作用:字符缓冲输入流可以把字符输入流包装成一个高级的缓冲字符输入流,
可以提高字符输入流读数据的性能。
-- 构造器:public BufferedReader(Reader reader):
-- 原理:缓冲字符输入流默认会有一个8K的字符缓冲池,可以提高读字符的性能。
-- 缓冲字符输入流除了提高了字符输入流的读数据性能,
缓冲字符输入流还多了一个按照行读取数据的功能(重点):
public String readLine(): 读取一行数据返回,读取完毕返回null;
小结:
缓冲字符输入流可以包装低级的字符输入流提高读文本的性能
除此之外多了一个按照行读取数据的功能:(经典做法)
public String readLine(): 读取一行数据返回,读取完毕返回null;
*/
public class BufferedReaderDemo01 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字符输入流与源文件接通
Reader fr = new FileReader("day11-demo/src/dlei01.txt");
// a.把低级的字符输入流包装成高级的缓冲字符输入流管道
BufferedReader br = new BufferedReader(fr);
// 2、按照缓冲字符输入流按照行读取 (经典代码)
String line ;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
}
字符缓冲输出流的使用
import java.io.*;
/**
目标:字符缓冲输出流的使用。
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
字符缓冲输出流:BufferedWriter
-- 作用:把字符输出流包装成一个高级的缓冲字符输出流,提高写字符数据的性能。
-- 构造器:public BufferedWriter(Writer writer):
-- 原理:高级的字符缓冲输出流多了一个8k的字符缓冲池,写数据性能极大提高了!
-- 字符缓冲输出流除了提高字符输出流写数据的性能,还多了一个换行的特有功能:
public void newLine():新建一行。
小结:
-- 字符缓冲输出流除了提高字符输出流写数据的性能,还多了一个换行的特有功能:
public void newLine():新建一行。
*/
public class BufferedWriterDemo02 {
public static void main(String[] args) throws Exception {
// 1、创建一个字符输出流管道与目标文件接通
// Writer fw = new FileWriter("day11-demo/src/dlei02-out.txt"); // 覆盖管道
Writer fw = new FileWriter("day11-demo/src/dlei02-out.txt", true); // 追加管道
BufferedWriter bw = new BufferedWriter(fw);
// a.public void write(int c):写一个字符出去
bw.write(97); // a
bw.write('A'); //
bw.write('磊'); // 无问题,真的是一个字符看待的。
bw.newLine(); // 换行
// b.public void write(String c)写一个字符串出去。
bw.write("我爱你中国abc");
bw.write("我爱你中国abc2");
bw.newLine(); // 换行
// c.public void write(char[] buffer):写一个字符数组出去
char[] buffer1 = "此情可成追忆,只是当时已懵逼".toCharArray();
bw.write(buffer1);
bw.newLine(); // 换行
// d.public void write(String c ,int pos ,int len):写字符串的一部分出去
bw.write("我爱你中国abc2" , 0 , 5);
bw.newLine(); // 换行
// e.public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
char[] buffer2 = "此情可成追忆,只是当时已懵逼".toCharArray();
bw.write(buffer2, 0, 6);
bw.newLine(); // 换行
// fw.flush(); // 刷新
bw.close(); //关闭流管道
}
}
出师表
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
思路:
1、定义一个缓冲字符输入流与源文件接通。
2、创建一个List集合存储每行文章。
3、按照行读取每行文章存入到集合中。
4、对List集合按照行首字符排序。
5、定义一个缓冲字符输出流。
6、遍历List集合的每行文章,写出去,且换行。
*/
public class ExecDemo03 {
public static void main(String[] args) {
try (
// 1、定义一个缓冲字符输入流与源文件接通。
BufferedReader br = new BufferedReader(new FileReader("day11-demo/src/csb.txt"));
// 5、定义一个缓冲字符输出流。
BufferedWriter bw = new BufferedWriter(new FileWriter("day11-demo/src/newcsb.txt"));
) {
// 2、创建一个List集合存储每行文章。
List<String> datas = new ArrayList<>();
// 3、按照行读取每行文章存入到集合中。
String line ;
while ((line = br.readLine()) != null) {
datas.add(line);
}
System.out.println(datas);
// 自定义大小规则,必须一一罗列
List<String> sizes = new ArrayList<>();
Collections.addAll(sizes , "零","一","二","三","四","五","陆","柒","八","九","十","十一");
// 4、对List集合按照行首字符排序。
Collections.sort(datas, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// o1 : 陆....
// o2 : 十一...
// 取索引:根据元素内容获取索引值
return sizes.indexOf(o1.substring(0 , o1.indexOf(".")))
- sizes.indexOf(o2.substring(0 , o2.indexOf(".")));
}
});
System.out.println(datas);
// 6、遍历List集合的每行文章,写出去,且换行。
for (String data : datas) {
bw.write(data);
bw.newLine();
}
System.out.println("完成!");
}catch (Exception e){
e.printStackTrace();
}
}
}
字符流不同编码读取乱码的问题
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;
/**
目标:字符流不同编码读取乱码的问题。
引入:
我们之前用的代码编码和文件编码都是UTF-8编码,字符流读取没有出现乱码!!
字符流读取:
代码编码 文件编码 中文情况。
UTF-8 UTF-8 不乱码!
GBK GBK 不乱码!
UTF-8 GBK 乱码!
小结:
如果读取文本文件内容的编码是不同的,那么会出现乱码!
*/
public class ReaderDemo {
public static void main(String[] args) throws Exception {
// 1、创建一个低级的字符输入流
// 代码是UTF-8 文件也是UTF-8 不乱码
// Reader fr = new FileReader("day11-demo/src/dlei01.txt");
// 代码是UTF-8 文件是GBK 乱码
Reader fr = new FileReader("test\\data.txt");
// 2、把低级的字符输入流包装成高级的缓冲字符输入流
BufferedReader br = new BufferedReader(fr);
// 3、按照行读取文本内容
String line ; // 存储一行数据
while ((line = br.readLine())!=null){
System.out.println(line);
}
}
}
字符转换流
字符输入转换流InputStreamReader的使用
import java.io.*;
/**
目标:字符输入转换流InputStreamReader的使用。
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter
字符输入转换流InputStreamReader:
-- 作用:可以解决字符流读取不同编码乱码的问题。
也可以把原始的字节流按照指定编码转换成字符输入流
-- 构造器:
public InputStreamReader(InputStream is):可以使用当前代码默认编码转换成字符流,几乎不用!
public InputStreamReader(InputStream is,String charset):可以指定编码把字节流转换成字符流(核心)
小结:
字符输入转换流InputStreamReader:作用:可以解决字符流读取不同编码乱码的问题。
public InputStreamReader(InputStream is,String charset):可以指定编码把字节流转换成字符流(核心)
*/
public class InputStreamReaderDemo01 {
public static void main(String[] args) throws Exception {
// 代码UTF-8 文件 UTF-8 FileReader
// 代码UTF-8 文件 GBK 必须使用转换流
// 1、提取GBK的原始字节输入流
InputStream is = new FileInputStream("test/data.txt");
// 2、指定编码把GBK的字节流转换成字符输入流
// Reader fr = new InputStreamReader(is); // 不建议,默认还是用的UTF-8转换成字符。
Reader fr = new InputStreamReader(is , "GBK"); // 指定使用GBK转换成字符输入流
// 3、把字符输入流转换成高级的缓存字符输入流
BufferedReader br = new BufferedReader(fr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
字符输出转换OutputStreamWriter流的使用
import java.io.*;
import java.nio.Buffer;
/**
目标:字符输出转换OutputStreamWriter流的使用。
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter
字符输出转换流:OutputStreamWriter
-- 作用:可以指定编码把字节输出流转换成字符输出流。
可以指定写出去的字符的编码。
-- 构造器:
public OutputStreamWriter(OutputStream os) : 用当前默认编码UTF-8把字节输出流转换成字符输出流
public OutputStreamWriter(OutputStream os , String charset):指定编码把字节输出流转换成字符输出流
小结:
字符输出转换流OutputStreamWriter可以指定编码把字节输出流转换成字符输出流。
从而实现指定写出去的字符编码!
*/
public class OutputStreamWriterDemo02 {
public static void main(String[] args) throws Exception {
// 1、定义原始的字节输出流管道写数据到文件
OutputStream os = new FileOutputStream("test/data-out.txt");
// 把低级的字节输出流转换成字符输出流
//Writer fw = new OutputStreamWriter(os); // FileWriter : UTF-8
Writer fw = new OutputStreamWriter(os , "GBK"); // GBK
BufferedWriter bw = new BufferedWriter( fw );
bw.write("我爱你中国");
bw.newLine();
bw.write("我爱你中国abc");
bw.close();
}
}
序列化对象
对象序列化技术
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
目标:对象序列化技术。
对象序列化:就是把Java对象数据直接存储到文件中去。 对象 => 文件中
对象反序列化:就是把Java对象的文件数据恢复到Java对象中。 文件中 => 对象
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter
ObjectInputStream ObjectOutputStream
对象序列化流(对象字节输出流):ObjectOutputStream
-- 作用:把内存中的Java对象数据保存到文件中去。
-- 构造器: public ObjectOutputStream(OutputStream out)
-- 序列化方法:public final void writeObject(Object obj)
注意:对象如果想参与序列化,对象必须实现序列化接口 implements Serializable ,否则序列化失败!
*/
public class SerializeDemo01 {
public static void main(String[] args) {
try (
// 1、创建一个对象字节输出流,用于序列化对象
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream("day11_demo/src/data.txt"));
){
// 序列化:把对象数据存入到文件中去
User user = new User("admin" , "003197" , "管理员",23);
// 2、开始序列化对象
oos.writeObject(user);
System.out.println("序列化成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
对象序反列化技术
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
目标:对象序反列化技术。
序列化:就是把Java对象数据直接存储到文件中去。 对象 => 文件中
反序列化:把Java对象的文件数据恢复到Java对象中。 文件中 => 对象
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter
ObjectInputStream ObjectOutputStream
对象反序列化(对象字节输入流):ObjectInputStream
-- 作用:读取序列化的对象文件恢复到Java对象中。
-- 构造器:public ObjectInputStream(InputStream is)
-- 方法:public final Object readObject()
transient修饰的成员变量:不参与序列化!
// 加入序列版本号
private static final long serialVersionUID = 1L;
注意:序列化采用的版本号和反序列化采用的版本号必须一致才不会出错!
*/
public class SerializeDemo02 {
public static void main(String[] args) throws Exception {
try (
// 1、把低级的字节输入流管道包装成高级的对象字节输入流管道
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("day11_demo/src/data.txt"));
){
// 开始反序列化对象
User u = (User) ois.readObject();
System.out.println(u);
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.Serializable;
// 1、序列化对象必须实现序列化接口
public class User implements Serializable {
private String loginName;
// transient只能修改成员变量,修改的成员变量将不参与序列化
private transient String passWord;
private String userName;
private int age;
public User(){
}
public User(String loginName, String passWord, String userName, int age) {
this.loginName = loginName;
this.passWord = passWord;
this.userName = userName;
this.age = age;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"loginName='" + loginName + '\'' +
", passWord='" + passWord + '\'' +
", userName='" + userName + '\'' +
", age=" + age +
'}';
}
}
打印流
打印流PrintStream / PrintWriter(写数据的)
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
拓展:打印流PrintStream / PrintWriter(写数据的)
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter
ObjectInputStream ObjectOutputStream
PrintStream PrintWriter
打印流的作用:
1.可以方便,快速的写数据出去。
2.可以实现打印啥出去,就是啥出去。
打印流的构造器:
public PrintStream(OutputStream os):
public PrintStream(String filepath):
小结:
打印流PrintStream(也可以写字节出去) / PrintWriter(也可以写字符出去)作用:
1.可以方便,快速的打印数据出去。
2.可以实现打印啥出去,就是啥出去。
*/
public class PrintStreamDemo01 {
public static void main(String[] args) throws Exception {
//PrintStream ps = new PrintStream(new FileOutputStream("day11_demo/src/itheima04_out.txt" ));
// PrintStream ps = new PrintStream("day11_demo/src/itheima04_out.txt");
PrintStream ps = new PrintStream(new FileOutputStream("day11_demo/src/itheima04_out.txt" , true));
// PrintWriter ps = new PrintWriter(new FileOutputStream("day11_demo/src/itheima04_out.txt" ));
ps.println(97);
ps.println('a');
ps.println("我爱你苍老师");
ps.println(true);
ps.println(98.9);
ps.close();
}
}
打印流改变输出的流向。重定向
import java.io.PrintStream;
/**
目标:打印流改变输出的流向。重定向。
System:
public static void setOut(PrintStream out) :让系统的输出流向打印流。
*/
public class PrintStreamDemo02 {
public static void main(String[] args) throws Exception {
PrintStream sys = System.out;
System.out.println("春花秋月何时了");
PrintStream ps = new PrintStream("day11_demo/src/log.txt");
System.setOut(ps); // 改变系统输出流向,走向自己的打印流管道
System.out.println("往事知多少");
System.out.println("小楼昨夜又东风");
System.setOut(sys); // 从新回到控制台
System.out.println("故国不堪回首月明中");
}
}
Properties
Properties的概述和使用(框架底层使用,了解这个技术即可)(保存数据到属性文件)
import java.io.FileWriter;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
/**
目标:Properties的概述和使用(框架底层使用,了解这个技术即可)(保存数据到属性文件)
Properties: 属性集对象。
其实就是一个Map集合。也就是一个键值对集合,但是我们一般不会当集合使用,
因为有HashMap。
Properties核心作用:
Properties代表的是一个属性文件,可以把键值对的数据存入到一个属性文件中去。
属性文件:后缀是.properties结尾的文件,里面的内容都是 key=value。
大家在后期学的很多大型框架技术中,属性文件都是很重要的系统配置文件。
users.properties
admin=123456
dlei=dlei
需求:使用Properties对象生成一个属性文件,里面存入用户名和密码信息。
Properties的方法:
-- public Object setProperty(String key, String value) : 保存一对属性。 (put)
-- public String getProperty(String key) : 使用此属性列表中指定的键搜索属性值 (get)
-- public Set<String> stringPropertyNames() : 所有键的名称的集合 (keySet())
-- public void store(OutputStream out, String comments): 保存数据到属性文件中去
-- public void store(Writer fw, String comments): 保存数据到属性文件中去
小结:
Properties可以保存键值对数据到属性文件
*/
public class PropertiesDemo01 {
public static void main(String[] args) throws Exception {
// Properties 可以把键值对数据存入到属性文件中去。
Properties properties = new Properties();
properties.setProperty("admin" , "123456");
properties.setProperty("dlei" , "003197");
System.out.println(properties);
// 重点:键值对的属性集对象数据存入到属性文件中去。
/**
参数一:保存的管道
参数二:保存心得。
*/
properties.store(new FileWriter("day11_demo/src/users.properties")
, "i am very happy!this is users!!");
}
}
目标:Properties读取属性文件中的键值对信息。(读取)
import java.io.FileReader;
import java.util.Properties;
import java.util.Set;
/**
目标:Properties读取属性文件中的键值对信息。(读取)
Properties的方法:
-- public Object setProperty(String key, String value) : 保存一对属性。
-- public String getProperty(String key) :使用此属性列表中指定的键搜索属性值
-- public Set<String> stringPropertyNames() :所有键的名称的集合
-- public void store(OutputStream out, String comments):保存数据到属性文件中去
-- public synchronized void load(InputStream inStream):加载属性文件的数据到属性集对象中去
-- public synchronized void load(Reader fr):加载属性文件的数据到属性集对象中去
小结:
属性集对象可以加载读取属性文件中的数据!!
*/
public class PropertiesDemo02 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
System.out.println(properties);
properties.load(new FileReader("day11_demo/src/users.properties"));
System.out.println(properties);
// 得到全部键
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
String value = properties.getProperty(key);
System.out.println(key + "-->" + value);
}
properties.forEach((k , v ) -> {
System.out.println(k +"====>" + v);
});
}
}