1. 通配符的使用
1.1 无限制条件的通配符:?
@Test
public void test1(){
ArrayList<?> list1;
ArrayList<Person> list2 = new ArrayList<Person>();
ArrayList<Student> list3 = new ArrayList<Student>();
//合法
list1 = list2;
// list1 = list3;
//写入:list1是否可以添加数据? 不可以的
// list1.add(new Person());
//特例:
list1.add(null);
//读取:可以
list2.add(new Person());
Object obj = list1.get(1);
System.out.println(obj);
}
1.2 有限制条件的通配符的使用
/*
* ?
*
* ? extends T : A<? extends T> 可以看做是A<T>和 A<G>的父类。其中G类是T类的子类
*
* ? super Person: A<? super T> 可以看做是A<T>和 A<G>的父类。其中G类是T类的父类
*
* */
@Test
public void test2(){
ArrayList<? extends Person> list1 ;
ArrayList<? super Person> list2;
ArrayList<Object> list3 = new ArrayList<Object>();
ArrayList<Person> list4 = new ArrayList<Person>();
ArrayList<Student> list5 = new ArrayList<Student>();
//? extends T
// list1 = list3; //编译不通过
list1 = list4;
// list1 = list5;
//写入:不允许
list1.add(null);//特例
// list1.add(new Student());//编译不通过
// list1.add(new Person());//编译不通过
// list1.add(new Object());//编译不通过
//读取:合法
Person p1 = list1.get(0);
//####################################################
//? super Person
list2 = list3;
list2 = list4;
// list2 = list5;//编译不通过
//写入:
list2.add(null);
list2.add(new Student());//编译通过
list2.add(new Person());//编译通过
// list2.add(new Object());//编译不通过
//读取:
Object obj = list2.get(0);
}
2. 练习题
import java.util.*;
/**
* 定义个泛型类 DAO<T>,在其中定义一个Map 成员变量,Map 的键为 String 类型,值为 T 类型。
* <p>
* 分别创建以下方法:
* public void save(String id,T entity): 保存 T 类型的对象到 Map 成员变量中
* public T get(String id):从 map 中获取 id 对应的对象
* public void update(String id,T entity):替换 map 中key为id的内容,改为 entity 对象
* public List<T> list():返回 map 中存放的所有 T 对象
* public void delete(String id):删除指定 id 对象
*
*/
public class DAO<T> {
private Map<String, T> map;
public DAO(){
map = new HashMap<>();
}
//保存 T 类型的对象到 Map 成员变量中
public void save(String id, T entity) {
if(!map.containsKey(id)){
map.put(id,entity);
}
}
public T get(String id) {
return map.get(id);
}
//替换 map 中key为id的内容,改为 entity 对象
public void update(String id, T entity) {
if(map.containsKey(id)){
map.put(id,entity);
}
}
//返回 map 中存放的所有 T 对象
public List<T> list() {
Collection<T> values = map.values();
//错误的:
// return (List<T>) values;
System.out.println(values.getClass());
//正确的方式1
ArrayList<T> list = new ArrayList<>(values.size());
for(T t : values){
list.add(t);
}
return list;
//正确的方式2
// ArrayList<T> list = new ArrayList<>(values.size());
// list.addAll(values);
// return list;
//正确的方式3
// ArrayList<T> list = new ArrayList<T>(values);
// return list;
}
//删除指定 id 对象
public void delete(String id) {
map.remove(id);
}
}
/**
* 定义一个 User 类:
* 该类包含:private成员变量(int类型) id,age;(String 类型)name。
*
* hashCode() 与 equals()保持一致性!
*
*/
public class User {
private int id;
private int age;
private String name;
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public User() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
if (id != user.id) return false;
if (age != user.age) return false;
return name != null ? name.equals(user.name) : user.name == null;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + age;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
}
import java.util.List;
/**
* 创建 DAO 类的对象, 分别调用其 save、get、update、list、delete 方法来操作 User 对象,
* 使用 Junit 单元测试类进行测试。
*
*/
public class DAOTest {
public static void main(String[] args) {
DAO<User> dao = new DAO<User>();
dao.save("1",new User(1001,32,"周杰伦"));
dao.save("2",new User(1002,22,"昆凌"));
dao.update("2",new User(1003,25,"蔡依林"));
List<User> list = dao.list();
System.out.println(list);
}
}
3. File类的使用
/**
* File类的使用
*
* 1. File类及后续的各种流都声明在java.io 包下
* 2. File类的对象代表一个文件(.java,.mp3,.doc ,.txt,.avi )或文件目录
* 3. File通常都是作为IO流的端点出现的。从代码上看,将File类的对象作为参数传递到IO流的构造器中。
* 4. File类中涉及到文件或文件目录的新建、路径名、大小、删除等操作。具体读取文件内容的行为,File
* 是无能为力的,必须使用流来操作。
*
*/
public class FileTest {
/*
* File类的实例化
* public File(String pathname)
*
* public File(String parent,String child)
以parent为父路径,child为子路径创建File对象。
*
* public File(File parent,String child)
根据一个父File对象和子文件路径创建File对象
*文件(或文件目录)的路径
* 绝对路径:包含盘符在内的文件或文件目录的完整路径。比如:C:\Program Files (x86)\Bonjour\abc.txt
* 相对路径:通常都是相较于当前工程或当前module
*
* */
// String str = "我是一个\"好\"人";
// System.out.println(str);
@Test
public void test1(){
//表示文件
File file1 = new File("hello.txt");
File file2 = new File("abc/nello.txt");
//表示文件目录
File file3 = new File("C:\\Program Files (x86)\\Bonjour");
//File(String parent,String child)
File file4 = new File("C:\\Program Files (x86)\\Bonjour","abc.txt");
//public File(File parent,String child)
File file5 = new File(file3,"abc.txt");
}
/**
* File类的获取功能
* public String getAbsolutePath():获取绝对路径
* public File getAbsoluteFile():获取绝对路径表示的文件
* public String getPath() :获取路径
* public String getName() :获取名称
* public String getParent():获取上层文件目录路径。若无,返回null
* public long length() :获取文件长度(即:字节数)。不能获取目录的长度。
* public long lastModified() :获取最后一次的修改时间,毫秒值
*
*/
@Test
public void test2(){
File file1 = new File("hello.txt");
file1 = new File("d:\\io\\hello.txt");
file1 = new File("d:\\io");
System.out.println(file1.getAbsolutePath());
System.out.println(file1.getAbsoluteFile());
System.out.println(file1.getPath());
System.out.println(file1.getName());
System.out.println(file1.getParent());
System.out.println(file1.length());
System.out.println(new Date(file1.lastModified()));
System.out.println(file1.getAbsoluteFile().getParent());
}
//练习:创建一个与hello.txt文件在相同文件目录下的另一个名为abc.txt文件
@Test
public void test3(){
File file1 = new File("hello.txt");
//File(String parent,String child)
File dest = new File(file1.getAbsoluteFile().getParent(),"abc.txt");
}
/* public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
* public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组
*/
@Test
public void test4(){
File file1 = new File("D:\\code210301");
File[] files = file1.listFiles();
for(File f : files){
System.out.println(f);
}
}
/*
* public boolean isDirectory():判断是否是文件目录
public boolean isFile() :判断是否是文件
public boolean exists() :判断是否存在
public boolean canRead() :判断是否可读
public boolean canWrite() :判断是否可写
public boolean isHidden() :判断是否隐藏
* */
@Test
public void test5(){
File file1 = new File("D:\\code210301");
file1 = new File("d:\\io\\hello.txt");
System.out.println(file1.isDirectory());
System.out.println(file1.isFile());
System.out.println(file1.exists());//磁盘中是否存在此文件或文件目录
System.out.println(file1.canRead());
System.out.println(file1.canWrite());
System.out.println(file1.isHidden());
}
//思考:如何遍历一个文件目录下的所有的文件
@Test
public void test6(){
File file = new File("D:\\code210301");
printFileName(file);
}
public void printFileName(File file){
if(file.isFile()){
System.out.println(file.getAbsolutePath());
}else{
File[] files = file.listFiles();
for(File f : files){
printFileName(f);
}
}
}
//思考1:获取指定文件目录的大小
//思考2:删除指定的文件目录
/*
* public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建。
public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
* public boolean delete():删除文件或者文件夹
**/
@Test
public void test7() throws IOException {
File file1 = new File("d:\\io\\abc.txt");
if(!file1.exists()){//若文件不存在
System.out.println(file1.createNewFile()? "创建成功" : "创建失败");
}else{//若文件存在
System.out.println(file1.delete()? "删除成功":"删除失败");
}
}
@Test
public void test8(){
//mkdir():如果要创建的文件目录已存在,则创建失败。
// 如果要创建的文件目录的上层目录不存在,则创建失败。
File file1 = new File("d:\\io\\io2\\io3");
// System.out.println(file1.mkdir()? "创建成功" : "创建失败");
//mkdirs():如果要创建的文件目录的上层目录不存在,则一并创建
// 如果要创建的文件目录已存在,则创建失败。
System.out.println(file1.mkdirs()? "创建成功" : "创建失败");
file1.delete();
}
}
- 对应的思考题的答案
/**
* 3. 遍历指定目录所有文件名称,包括子文件目录中的文件。
拓展1:并计算指定目录占用空间的大小
拓展2:删除指定文件目录及其下的所有文件
*
*/
public class ListFilesTest {
public static void main(String[] args) {
// 递归:文件目录
/** 打印出指定目录所有文件名称,包括子文件目录中的文件 */
// 1.创建目录对象
File dir = new File("E:\\teach\\01_javaSE\\_尚硅谷Java编程语言\\3_软件");
// 2.打印目录的子文件
printSubFile(dir);
}
public static void printSubFile(File dir) {
// 打印目录的子文件
File[] subfiles = dir.listFiles();
for (File f : subfiles) {
if (f.isDirectory()) {// 文件目录
printSubFile(f);
} else {// 文件
System.out.println(f.getAbsolutePath());
}
}
}
// 方式二:循环实现
// 列出file目录的下级内容,仅列出一级的话
// 使用File类的String[] list()比较简单
public void listSubFiles(File file) {
if (file.isDirectory()) {
String[] all = file.list();
for (String s : all) {
System.out.println(s);
}
} else {
System.out.println(file + "是文件!");
}
}
// 列出file目录的下级,如果它的下级还是目录,接着列出下级的下级,依次类推
// 建议使用File类的File[] listFiles()
public void listAllSubFiles(File file) {
if (file.isFile()) {
System.out.println(file);
} else {
File[] all = file.listFiles();
// 如果all[i]是文件,直接打印
// 如果all[i]是目录,接着再获取它的下一级
for (File f : all) {
listAllSubFiles(f);// 递归调用:自己调用自己就叫递归
}
}
}
// 拓展1:求指定目录所在空间的大小
// 求任意一个目录的总大小
public long getDirectorySize(File file) {
// file是文件,那么直接返回file.length()
// file是目录,把它的下一级的所有大小加起来就是它的总大小
long size = 0;
if (file.isFile()) {
size += file.length();
} else {
File[] all = file.listFiles();// 获取file的下一级
// 累加all[i]的大小
for (File f : all) {
size += getDirectorySize(f);// f的大小;
}
}
return size;
}
// 拓展2:删除指定的目录
public void deleteDirectory(File file) {
// 如果file是文件,直接delete
// 如果file是目录,先把它的下一级干掉,然后删除自己
if (file.isDirectory()) {
File[] all = file.listFiles();
// 循环删除的是file的下一级
for (File f : all) {// f代表file的每一个下级
deleteDirectory(f);
}
}
// 删除自己
file.delete();
}
}
4. IO的概述
- 流的分类
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流
- 4个流的抽象基类
- 具体的子类 (深色的为重点)
5. FileReader/FileWriter
import org.junit.Test;
import java.io.*;
public class FileReaderWriterTest {
/*
使用单元测试方法的话,相对路径指的是当前module
使用main的话,相对路径指的是当前工程
*/
@Test
public void test1() throws IOException {
//1. 创建流(包含了创建文件)
FileReader fr = new FileReader(new File("hello.txt"));
//2. 具体的读取操作
//read():读取下一个字符,并返回。如果到达文件末尾,返回-1.
int data = fr.read();
while(data != -1){ //判断是否达到文件末尾
System.out.print((char)data);
data = fr.read();
}
//3. 关闭资源。一旦缺少关闭操作,就会出现内存泄漏
fr.close();
}
//升级操作:本章中凡是出现流资源的关闭操作,都需要使用try-catch-finally来处理。不能使用throws.
@Test
public void test2(){
FileReader fr = null;
try{
//1. 创建流(包含了创建文件)
fr = new FileReader(new File("hello.txt"));
//2. 具体的读取操作
int data = fr.read();
while(data != -1){ //判断是否达到文件末尾
System.out.print((char)data);
data = fr.read();
}
}catch(IOException e){
e.printStackTrace();
}finally{
//3. 关闭资源。一旦缺少关闭操作,就会出现内存泄漏
try {
if(fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//继续升级操作:每次读取数据使用一个数组。效率更高!
@Test
public void test3(){
FileReader fr = null;
try{
//1. 创建流(包含了创建文件)
fr = new FileReader(new File("hello.txt"));
//2. 具体的读取操作
char[] cbuffer = new char[5];
int len;//记录每次读入到cbuffer数组中的字符的个数
//read(char[] cbuf): 将数据读入到cbuf数组中,并返回读入到此数组中的个数。
while((len = fr.read(cbuffer)) != -1){ //判断是否达到文件末尾
//遍历cbuffer数组
//错误的
// for(int i = 0;i < cbuffer.length;i++){
// System.out.print(cbuffer[i]);
// }
//正确的:
// for(int i = 0;i < len;i++){
// System.out.print(cbuffer[i]);
// }
//正确的:
String str = new String(cbuffer,0,len);
System.out.print(str);
// Thread.sleep(3000);
}
}catch(IOException e){
e.printStackTrace();
}finally{
//3. 关闭资源。一旦缺少关闭操作,就会出现内存泄漏
try {
if(fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void test4() {
FileWriter fw = null;
try {
//1. 创建流(包含输出的文件的创建)
// fw = new FileWriter(new File("abc.txt"));
fw = new FileWriter(new File("abc.txt")t);
//2. 写出数据
fw.write("I love you!\n");
fw.write("you love him!".toCharArray());
fw.write("\n我很痛苦!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//3. 关闭资源
try {
if(fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* 小结:
*
* 1. FileReader \FileWriter因为涉及资源的关闭操作,所以有异常的话,必须使用try-catch-finally处理
* 2. 输入流在读取文件中的数据时,要求此文件必须存在。否则会报FileNotFoundException
* 3. 输出流在写出数据到指定文件时,写出的文件可以不存在。
* 3.1 如果写出的文件确实不存在,在执行的过程中,会自动的创建此文件。
* 3.2 如果写出的文件存在,使用FileWriter(File) 或 FileWriter(File,false)构造器时,在执行的过程中,会覆盖原有文件
* 使用FileWriter(File,true)构造器时,在执行的过程中,在原有文件的末尾添加新的数据
*
* */
//实现文本文件的复制
@Test
public void test5(){
FileReader fr = null;
FileWriter fw = null;
try {
//1. 创建流(包含文件的创建)
fr = new FileReader(new File("hello.txt"));
fw = new FileWriter(new File("hello_copy.txt"));
//不能处理非文本文件
// fr = new FileReader(new File("pony.jpg"));
// fw = new FileWriter(new File("pony_copy.jpg"));
//2. 数据的读取和写出
char[] cbuf = new char[5];
int len;//记录每次读入到cbuf[]中字符的个数
while((len = fr.read(cbuf)) != -1){
//操作1:
fw.write(cbuf,0,len);
//操作2:
// String str = new String(cbuf,0,len).toUpperCase();
// fw.write(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//3. 关闭流
//方式1:
// try {
// if(fw != null)
// fw.close();
// } catch (IOException e) {
// e.printStackTrace();
// }finally{
//
// try {
// if(fr != null)
// fr.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//方式2:
try {
if(fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6. FileInputStream / FileOutputStream
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 测试FileInputStream 和 FileOutputStream的使用
*
* 小结:
* 我们使用字符流来处理文本文件(.txt,.java,.py,....)
*
* 使用字节流来处理非文本文件(.doc , .mp3, .avi,.jpg,...)
* 补充:字节流也可以实现文本文件的复制。
*
*/
public class FileInputOutputStreamTest {
//实现图片的复制
@Test
public void test1() {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//1. 创建流(包括创建文件的过程)
fis = new FileInputStream(new File("pony.jpg"));
fos = new FileOutputStream(new File("pony_copy.jpg"));
// fis = new FileInputStream(new File("hello.txt"));
// fos = new FileOutputStream(new File("hello_copy1.txt"));
//2. 读取数据并写出数据
byte[] buffer = new byte[10];
int len;//记录每次读入到buffer[]中的字节的个数
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("复制成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
//3. 关闭资源
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7. 缓冲流
import com.sun.media.sound.SoftTuning;
import org.junit.Test;
import java.io.*;
/**
* 缓冲流的使用:提高数据的读写效率
*
*/
public class BufferedTest {
//应该使用try-catch-finally处理异常。
@Test
public void test1() throws IOException {
//1. 创建流(包括创建文件的过程)
FileInputStream fis = new FileInputStream(new File("pony.jpg"));
FileOutputStream fos = new FileOutputStream(new File("pony_copy.jpg"));
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//2. 读取数据并写出数据
byte[] buffer = new byte[10];
int len;//记录每次读入到buffer[]中的字节的个数
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
System.out.println("复制成功");
//3. 关闭资源
//如果涉及到节点流和处理流了,我们应该先关闭处理流,再关闭节点流。(先关外面的流,再关闭里面的流)
//外部流的关闭操作,自动会在内部将其内部的流关闭。
bos.close();
bis.close();
//省略了
// fos.close();
// fis.close();
}
//对比FileInputStream 、FileOutputStream 与 BufferedInputStream、BufferedOutputStream的执行效率
public void copyWithFile(String src,String dest){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//1. 创建流(包括创建文件的过程)
fis = new FileInputStream(new File(src));
fos = new FileOutputStream(new File(dest));
//2. 读取数据并写出数据
byte[] buffer = new byte[1024];
int len;//记录每次读入到buffer[]中的字节的个数
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("复制成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
//3. 关闭资源
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void copyWithBuffered(String src,String dest){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1. 创建流(包括创建文件的过程)
FileInputStream fis = new FileInputStream(new File(src));
FileOutputStream fos = new FileOutputStream(new File(dest));
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//2. 读取数据并写出数据
byte[] buffer = new byte[1024];
int len;//记录每次读入到buffer[]中的字节的个数
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
System.out.println("复制成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
//3. 关闭资源
try {
if(bos != null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(bis != null)
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void test2(){
long start = System.currentTimeMillis();
String src = "C:\\Users\\songhk\\Desktop\\考试\\王俊钿\\歌舞.flv";
String dest = "C:\\Users\\songhk\\Desktop\\考试\\王俊钿\\歌舞2.flv";
// copyWithFile(src,dest);
copyWithBuffered(src,dest);
long end = System.currentTimeMillis();
System.out.println("花费的总时间为:" + (end - start));//4701 - 937
}
//测试BufferedReader和BufferedWriter的使用
//应该使用try-catch-finally处理异常。
@Test
public void test3() throws IOException {
//1. 造流
BufferedReader br = new BufferedReader(new FileReader(new File("dbcp.txt")));
BufferedWriter bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));
//2. 读写过程
//方式1:
// char[] cbuf = new char[10];
// int len;
// while((len = br.read(cbuf)) != -1){
// bw.write(cbuf,0,len);
// }
//方式2:
String str;
while((str = br.readLine()) != null){
bw.write(str);
// bw.write("\n");
bw.newLine();
}
//3. 关闭操作
bw.close();
br.close();
}
}
8. 转换流
import org.junit.Test;
import java.io.*;
/**
* 测试转换流的使用
*
* InputStreamReader: 将输入型的字节流转换为输入型的字符流
* OutputStreamWriter: 将输出型的字符流转换为输出型的字节流
*
* 编码:字符、字符串 ---> 字节 、字节数组,对应着OutputStreamWriter
* 解码:字节 、字节数组 ---> 字符、字符串 ,对应着InputStreamReader
*
* 要想保证解码之后字符没有乱码,必须保证解码使用的字符集与编码使用的字符集相同!
*
*/
public class InputStreamReaderTest {
@Test
public void test1() throws IOException {
//1.
// InputStreamReader isr = new InputStreamReader(new FileInputStream("dbcp.txt"));//当前InputStreamReader使用IDEA默认的字符集
InputStreamReader isr = new InputStreamReader(new FileInputStream("dbcp.txt"),"UTF-8");//当前InputStreamReader显式使用UTF-8字符集
//2.
char[] cbuf = new char[10];
int len;
while((len = isr.read(cbuf)) != -1){
String str = new String(cbuf,0,len);
System.out.print(str);
}
//3.
isr.close();
}
@Test
public void test2() throws IOException {
//1.
// InputStreamReader isr = new InputStreamReader(new FileInputStream("dbcp_gbk.txt"),"UTF-8");//会出现乱码
InputStreamReader isr = new InputStreamReader(new FileInputStream("dbcp_gbk.txt"),"GBK");//不会出现乱码
//2.
char[] cbuf = new char[10];
int len;
while((len = isr.read(cbuf)) != -1){
String str = new String(cbuf,0,len);
System.out.print(str);
}
//3.
isr.close();
}
@Test
public void test3() throws IOException {
//1.
InputStreamReader isr = new InputStreamReader(new FileInputStream("dbcp_gbk.txt"),"GBK");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("dbcp_utf8.txt"),"UTF-8");
//2
char[] cbuf = new char[10];
int len;
while((len = isr.read(cbuf)) != -1){
osw.write(cbuf,0,len);
}
//3.
osw.close();
isr.close();
}
}
对后续知识的启示意义: