IO流专题复习
1、常用的文件操作
1.1、创建文件对象构造器(三种方法)
代码展示
package com.zhangjiangbo.cn.files;
import java.io.File;
import java.io.IOException;
/**
* 1、创建文件
*/
public class FileCreate {
public static void main(String[] args) {
// create01();
// create02();
create03();
}
// 方式1 new File(String pathname)
public static void create01(){
File file = new File("D:\\测试\\new.txt");
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 方式2 new File(File parent,String child) 根据父目录+子路径构建
public static void create02(){
File parent = new File("D:\\测试\\");
// 这里的file对象在java程序中只是一个java对象而已,存储在堆内存中
File file = new File(parent,"test01.txt");
try {
// 真正的执行了创建文件
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 方式3 new File(String parent,String child) 根据父级目录+子路径构建
public static void create03(){
String parent = "D:\\";
String child = "测试\\test02.txt";
File file = new File(parent,child);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
1.2、获取文件的信息常用方法
- getName 获取名称
- getAbsoutePath 获取绝对路径
- getParent 获取父级目录
- length 获取文件大小(按字节来算)
- exists 文件是否存在
- isFile 是否是一个文件
- isDirectory 是否是一个目录
代码展示
@Test
public void info(){
File file = new File("D:\\测试\\test01.txt");
// 获取文件名
System.out.println("文件名:"+file.getName());
// 获取绝对路径
System.out.println("绝对路径:"+file.getAbsolutePath());
// 获取文件父目录
System.out.println("文件父目录:"+file.getParent());
// 获取文件大小(按字节来算)
System.out.println("文件大小为:"+file.length());
// 判断文件是否存在
System.out.println("文件是否存在:"+file.exists()); // true
// 是不是一个文件
System.out.println("是不是一个文件:"+file.isFile());
// 是不是一个目录
System.out.println("是不是一个目录:"+file.isDirectory());
}
1.3 目录的操作和文件删除
注意:当创建目录是多级时需要用mkdirs,否则会报错,只有一级时用mkdir
代码展示
/**
* 判断文件是否存在,存在就删除
*/
@Test
public void test01(){
File file = new File("D:\\测试\\test02.txt");
if(file.exists()){
file.delete();
System.out.println("文件删除完成");
}else{
System.out.println("该文件不存在");
}
}
/**
* 判断文件夹是否存在
* 在java程序中,目录也被当做文件
*/
@Test
public void test02(){
File file = new File("D:\\测试\\测试是否存在");
if(file.exists()){
if(file.delete()){
System.out.println("文件删除完成");
}else{
System.out.println("文件删除有误");
}
}else{
System.out.println("文件不存在");
}
}
/**
* 判断文件是否存在,如果存在则提示已存在,不存在则创建文件
* 当创建目录是多级时需要用mkdirs,否则会报错,只有一级时用mkdir
*/
@Test
public void test03(){
File file = new File("D:\\测试\\test02\\a\\b\\c");
if(file.exists()){
System.out.println("目录已存在");
}else{
if(file.mkdirs()){
System.out.println("文件不存在,已创建新文件");
}else{
System.out.println("文件创建失败");
}
}
}
2、IO流原理及流的分类
2.1 JavaIO流原理
2.2 流的分类
3、IO流常用类
3.1、IO流体系图
3.2、FileInputStream
功能:读取文件的数据输出到程序的控制台
思路:创建对象,将要读取的文件路径通过构造器传给对象,调用对象的read() 方法,将读取到的数据输出到控制台,关闭流
两种读取方式:
- read() 单个字节读取
直接调用read方法,返回int类型的单个字符,当查询到末尾时返回 -1 (读取效率慢)
- read(byte[] b) 数组读取
根据数组读取指定个数的字节,将数据暂存到数组内,当查询到末尾时返回 -1 (推荐使用)
代码展示
package com.zhangjiangbo.cn.inputStreams;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 字节流 FileInputStream
* 演示FileInputStream的使用(字节输入流)
*/
public class FileStreamTest {
public static void main(String[] args) {
}
/**
* 读取文件中的内容
* 使用read()方法
*/
@Test
public void readFiel01(){
String pathName = "D:\\测试\\new.txt";
// 创建fileInputStream对象,读取文件
FileInputStream fileInputStream = null;
int count = 0;
try {
fileInputStream = new FileInputStream(pathName);
while (count != -1){
// 如果返回-1则表示数据已经读取到了末尾
count = fileInputStream.read();
// 返回的数据类型是int,需要转换成字符型
System.out.print((char) count);
}
System.out.println();
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
// 使用完之后一定要关闭,释放文件连接,否则会造成资源浪费
fileInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
* 使用read(byte[] b) 提高效率
*/
@Test
public void readFiel02(){
String path = "D:\\测试\\new.txt";
FileInputStream fileInputStream = null;
byte[] buf = new byte[3]; // 一次要读8个字符
int count = 0;
try {
fileInputStream = new FileInputStream(path);
while (count!=-1){
count = fileInputStream.read(buf);
if(count!=-1){
System.out.print(new String(buf,0,count));
}
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
3.3、FileOutputStream
功能:将程序内的数据输出到指定文件内
思路:创建对象,将要输出的文件地址通过构造器传给对象,将准备好的数据通过调用对象的write()方法输出到文件内,关闭流
注意点:
new FileOutputStream(pathName); 方式创建文件,当写入内容时,会覆盖之前文件的数据
new FileOutputStream(pathName,ture); 追加到文件内容的末尾,不会覆盖
三种输出方式
- write() 方法输出
直接调用 write方法一个一个字节输出
- write(byte[] b) 数组输出
将数据放到数组中,根据数组来输出
- write(byte b[], int off, int len) 输出
将数据放到数组中,指定输出的长度(推荐) 例如: fileOutputStream.write(bytes,0,bytes.length);
代码展示
package com.zhangjiangbo.cn.outputStream;
import org.junit.Test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 在a.txt文件中输出你好,世界,会自动创建文件(前提:文件夹必须存在)
*/
public class FileOutputStream01 {
public static void main(String[] args) {
}
/**
* 使用FileOutputStream 将数据写到文件中,如果文件不存在则创建该文件
* 如果没有文件,write方法会自动创建文件(前提:文件夹必须存在)
* new FileOutputStream(pathName); 方式创建文件,当写入内容时,会覆盖之前文件的数据
* new FileOutputStream(pathName,ture); 追加到文件内容的末尾,不会覆盖
*/
@Test
public void writeFile(){
String pathName = "D:\\测试\\test03.txt";
// 创建FileOutputStream对象
FileOutputStream fileOutputStream = null;
try {
// 判断文件是否存在
File file = new File(pathName);
if(file.exists()){
fileOutputStream = new FileOutputStream(pathName,true);
// 三种方式
// fileOutputStream.write('a');
String str = "hello,world";
byte[] bytes = str.getBytes();
// fileOutputStream.write(bytes);
fileOutputStream.write(bytes,0,bytes.length);
System.out.println("写入数据成功");
}else{
file.createNewFile();
fileOutputStream = new FileOutputStream(pathName);
fileOutputStream.write('a');
System.out.println("文件不存在,已创建新文件并成功写入数据");
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
应用实例
通过FileOutputStream和FileInputStream实现文件的拷贝
思路:创建输入流、输出流对象,将要复制的文件通过构造方法传给输入流,将要复制到的文件传给输出流,调用输入流的read()方法读取到数据,调用输出流的write方法输出数据到指定文件
代码展示
package com.zhangjiangbo.cn.outputStream;
import org.junit.Test;
import java.io.*;
import java.util.Objects;
/**
* 文件拷贝
*/
public class FileCopy {
public static void main(String[] args) {
}
/**
* 文件拷贝 将D:\测试\test02\mini.jpg 文件 拷贝到D:\测试\mini.jpg
* 思路:
* 1、创建文件的输入流,将文件写入程序
* 2、创建文件的输出流,将文件输出
*/
@Test
public void test01(){
String pathName = "D:\\测试\\test02\\mini.jpg";
String toPathName = "D:\\测试\\mini.jpg";
// 创建输入流
FileInputStream inputStream = null;
// 创建输出流
FileOutputStream fileOutputStream = null;
int count = 0;
try {
fileOutputStream = new FileOutputStream(toPathName);
inputStream = new FileInputStream(pathName);
byte[] bytes = new byte[1024];
while(count!=-1){
count = inputStream.read(bytes);
// 读取到文件之后写入文件 边读边写
fileOutputStream.write(bytes,0,bytes.length);
}
System.out.println("拷贝成功!");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
if(Objects.equals(null,fileOutputStream)){
inputStream.close();
}
if(Objects.equals(null,fileOutputStream)){
fileOutputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
3.4、FileReader
功能:读取文件中的字符到程序
思路:创建对象,将要读取的文件路径通过构造器传给对象,调用对象的read()方法读取数据,关闭流
常用方法
两种读取方式
- read()方法读取
直接调用read()方法,一个字符一个字符的读取,当读取到数据末尾时返回 -1 (读取效率慢)
- read(char cbuf[]) 读取
读取指定位数的数据,将读取到的数据暂时存放到数组中,当读取末尾时返回-1 (推荐使用)
代码展示
package com.zhangjiangbo.cn.reader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* 读取文件内的汉字
* 使用fileReader
*/
public class FileReaderTest {
public static void main(String[] args) {
String pathName = "D:\\测试\\test03.txt";
FileReader fileReader = null;
int count = 0;
try {
fileReader = new FileReader(pathName);
char[] bytes = new char[1024];
while(count!=-1){
// 一个字一个字的读
// count = fileReader.read();
// 读取数组
count = fileReader.read(bytes);
if(count!=-1){
System.out.println(new String(bytes,0,count));
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
3.5、FileWriter
功能:将程序的字符输出到指定文件内
思路:创建对象,将要输出的文件地址通过构造方法传给对象,调用对象的write()方法 输出到文件内
注意点:
new FileOutputStream(pathName); 方式创建文件,当写入内容时,会覆盖之前文件的数据
new FileOutputStream(pathName,ture); 追加到文件内容的末尾,不会覆盖
对象调用write方法之后一定要刷新流或者关闭流,否则数据不会写入到文件内
常用方法
五种输出方式
- write(String str) 方法
直接输出字符串
- write(int c)
输出单个字符
- write(char cbuf[])
将数据放到数组中,输出数组
- write(char cbuf[], int off, int len)
将数据放到数组中,输出数组指定位置的数据
- write(String str, int off, int len)
输出字符串指定位置的数据
代码展示
package com.zhangjiangbo.cn.write;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Objects;
/**
* 将指定内容输出到文件中
* 注意:一定要执行flush或者close才可以将数据写到文件中,否则数据只会存在内存中,不会写进文件内
*/
public class FileWriteTest {
public static void main(String[] args) {
String pathName = "D:\\测试\\test03.txt";
FileWriter fileWriter = null;
try {
// 注意点,true,如果添加了则代表追加,没有加true则直接覆盖之前的数据
fileWriter = new FileWriter(pathName,true);
// 1、写入字符串
// String str = "\n我们都很相爱";
// fileWriter.write(str);
// 2、写入单个字符
fileWriter.write('张');
// 3、写入数组
// char[] chars = {'张','江','博'};
// fileWriter.write(chars);
// 4、写入数组指定内容
// char[] chars = {'张','江','博'};
// fileWriter.write(chars,0,1);
// 5、写入字符串指定内容
String str = "你好啊,我的朋友们";
fileWriter.write(str,0,3);
// 注意点
fileWriter.flush();
System.out.println("数据写入完成");
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
if(Objects.equals(null,fileWriter)){
fileWriter.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
4、字节流和处理流
4.1、节点流和处理流的区别
- 节点流是底层流/低级流,直接跟数据源相接
- 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供方便的方法来完成输入输出。
- 处理流对节点流进行包装,使用了修饰器模式,不会直接与数据源相连
作用
- 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
- 操作的便捷:处理流可以提供一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
4.2 BufferReader
BufferReader中封装了Reader类,这使得Reader及子类都可以放到BufferReader内
实现思路:创建节点流,将节点流通过构造器传入到包装流BufferReader中,使用包装流使得功能更加强大
读取方式
readLine 按行读取
readLine 读取文本内的一行数据,当读取到最后一行为空是,返回null
代码展示
package com.zhangjiangbo.cn.reader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Objects;
/**
* 使用BufferReader读取文本文件
*/
public class BufferReaderTest {
public static void main(String[] args) {
String path = "D:\\测试\\new.txt";
FileReader fileReader = null;
try {
fileReader = new FileReader(path);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
// 创建bufferReader对象
BufferedReader bufferedReader = new BufferedReader(fileReader);
// 按行读取 效率高
String line = "";
// 说明
// 1、bufferedReader.readLing()是按照行读取文件
// 2、当返回null时,则表示文件读取完毕
try {
while ((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
// 关闭流,这里注意,只需要关闭BufferedReader(最外层)就可以了,因为底层会自动的去关闭节点流
bufferedReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
关于只关闭最外层的包装流的源码部分
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();
} finally {
in = null;
cb = null;
}
}
}
其中in 就是动态穿进去的节点流对象
4.3、BufferedWriter
注意
- Writer节点流的new FileWriter(path,true) 是否覆盖
- 将数据写入后注意调用flash方法,否则数据写不到文件内
- 关闭流时,只关闭最外层包装流即可,它会自动调用底层方法帮我们关闭节点流
使用方法
newLine()
newLine() 切换到下一行,当将数据写入到文件后使用此方法可以完成换行
write(String str)
write() 通过此方法写入数据
代码展示
package com.zhangjiangbo.cn.write;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/**
* 使用BufferedWriter将"hello,小迷你"写入到文件中去
*/
public class BufferedWriterTest {
public static void main(String[] args) {
String path = "D:\\测试\\new.txt";
// 创建节点流
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(path,true);
} catch (IOException e) {
throw new RuntimeException(e);
}
// 创建包装流
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
try {
bufferedWriter.newLine();
bufferedWriter.write("hello,小迷你");
// 插入一个和系统相关的换行符
bufferedWriter.newLine();
bufferedWriter.write("hello2,小迷你");
bufferedWriter.newLine();
bufferedWriter.write("hello3,小迷你");
bufferedWriter.newLine();
bufferedWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
// 关闭外层流即可,传入的FileWriter会在底层关闭
try {
bufferedWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
4.4、通过包装流实现文件的拷贝
// 通过包装流,进行文件拷贝
// BufferedReader 和 BufferedWriter是对字符进行操作的,
// 不要去操作二进制文件,如果去操作二进制文件会导致文件损坏
@Test
public void test02() throws IOException {
String pathName = "D:\\测试\\test03.txt";
String toPathName = "D:\\测试\\test04.txt";
// 创建读取节点流
FileReader fileReader = new FileReader(pathName);
// 创建输出节点流
FileWriter fileWriter = new FileWriter(toPathName);
// 创建读取包装流
BufferedReader bufferedReader = new BufferedReader(fileReader);
// 创建输出包装流
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
String line = null;
while ((line=bufferedReader.readLine())!=null){
bufferedWriter.write(line);
bufferedWriter.newLine();
}
bufferedWriter.flush();
bufferedWriter.close();
bufferedReader.close();
}
4.5、使用包装流实现对二进制文件(图片、音乐、视频等)的拷贝
@Test
public void test03() throws IOException {
String pathName = "D:\\测试\\test02\\mini.jpg";
String toPathName = "D:\\测试\\mini.jpg";
// 创建读取节点流
FileInputStream fileInputStream = new FileInputStream(pathName);
// 创建输出节点流
FileOutputStream fileOutputStream = new FileOutputStream(toPathName);
// 创建读取包装流
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
// 创建输出包装流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
byte[] chars = new byte[1024];
int count = 0;
while (true){
count = bufferedInputStream.read(chars);
if(count==-1){
break;
}
bufferedOutputStream.write(chars,0,count);
}
bufferedOutputStream.flush();
bufferedInputStream.close();
bufferedOutputStream.close();
}
4.6、ObjectInputStream和ObjectOutputStream
看一个需求
1、将int num = 100 这个int数据保存到文件中,注意不是100数字,而是int 100 并且能够从文件中直接回复 int 100
2、将Dog dog = new Dog(“小黄”,3)这个dog对象,保存到文件中,并且能够从文件回复
3、上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化
序列化和反序列化
- 序列化就是在保存数据时,保存数据的值和数据类型
- 反序列化就是在回复数据时,恢复数据的值和数据类型
- 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一
- Serizalizable // 这是一个标记接口,没有方法
- Externalizable // 该接口有方法需要实现,因此我们一般实现上面的Serializable接口
应用案例
1、使用ObjectOutputStream序列化基本数据类型和一个Dog对象(name,age),并保存到data.dat 文件中
package com.zhangjiangbo.cn.outputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 演示 ObjectOutStream的使用,完成数据的序列化
*/
public class ObjectOutStreamTest {
public static void main(String[] args) throws IOException {
// 序列化之后,保存的文件格式,不是存文本,而是按照他的格式来保存
String pathName = "D:\\测试\\data.dat";
// 创建节点流对象
FileOutputStream fileOutputStream = new FileOutputStream(pathName);
// 创建包装流对象
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
// 序列化数据到文件中
objectOutputStream.write(100); // int -> Integer 底层实现了自动装箱(实现了Serializable)
objectOutputStream.writeBoolean(true); // boolean -> Boolean (实现了Serializable)
objectOutputStream.writeChar('a'); // char -> Character (实现了Serializable)
objectOutputStream.writeDouble(8.6); // double -> Double (实现了Serializable)
objectOutputStream.writeUTF("张江博"); // String (实现了Serializable)
// 保存一个dog对象 Dog必须实现序列化接口,否则会报异常
objectOutputStream.writeObject(new Dog("小黄",3));
objectOutputStream.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
// 注意实现序列化接口
class Dog implements Serializable {
private String name;
private int age;
public Dog() {
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2、取出案例1保存在data.dat文件中的数据
注意点:取出时的顺序要和存储的顺序要保持一致,并且存储对象时必须是同一个包下的对象,因为保存的时候会将对象的报名也保存上,否则取出会报错
package com.zhangjiangbo.cn.inputStreams;
import com.zhangjiangbo.cn.bean.Dog;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 反序列化
* 取出案例1保存的序列化数据
*/
public class ObjectInputStreamTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
// 指定反序列化文件地址
String pathName = "D:\\测试\\data.dat";
// 创建节点流对象
FileInputStream inputStream = new FileInputStream(pathName);
// 创建包装流对象
ObjectInputStream objectOutputStream = new ObjectInputStream(inputStream);
// 读取的时候读取的顺序要与保存的保持一致
int read = objectOutputStream.readInt();
System.out.println(read);
boolean b = objectOutputStream.readBoolean();
System.out.println(b);
char c = objectOutputStream.readChar();
System.out.println(c);
double v = objectOutputStream.readDouble();
System.out.println(v);
String s = objectOutputStream.readUTF();
System.out.println(s);
Object o = objectOutputStream.readObject();
System.out.println(o);
objectOutputStream.close();
Dog dog = (Dog)o;
String name = dog.getName();
System.out.println(name);
int age = dog.getAge();
System.out.println(age);
}
}
注意点
- 读写顺序要一致
- 要求序列化或反序列化对象,需要实现Serializable接口
- 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
- 序列化对象时,默认将里面所有属性都进行序列化,但除了static(静态的)或transient(转瞬即逝的)修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口(比如其中一个属性是一个类,这个类也是要实现序列化的)
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
4.7、标准输入流输出流
类型 | 默认设备 | |
---|---|---|
System.in 标准输入 | InputStream | 键盘 |
System.out 标准输出 | PrintStream | 显示器 |
代码展示
package com.zhangjiangbo.cn.standard;
import java.util.Scanner;
/**
*
*/
public class InputAntOutPut {
public static void main(String[] args) {
// System.in
// System 类的 public final static InputStream in = null;属性
// System.in 编译类型 InputStream
// System.in 运行类型 BufferedInputStream
// 表示标准输入 键盘
System.out.println(System.in.getClass());
// System.out
// System 类的 public final static PrintStream out = null;
// 编译类型 PrintStream
// 运行类型 PrintStream
// 表示标准输出 显示器
System.out.println(System.out.getClass());
System.out.println("张江博,要加油鸭!!!");
// Scanner 扫描器
Scanner scanner = new Scanner(System.in);
System.out.println("输入内容");
String next = scanner.next();
System.out.println(next);
}
}
4.8、转换流-InputStreamReader 和 OutputStreamWriter
问题引导,中文出现乱码
/**
* 引导出问题,中文乱码问题
*/
public class CodeQuestion {
public static void main(String[] args) throws IOException {
// 读取一个字符文件将内容输出到控制台
// 默认情况下读取文件是按照utf-8编码
String pathName = "D:\\测试\\new.txt";
// 创建字符流
FileReader fileReader = new FileReader(pathName);
// 创建处理流
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = null;
while ((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
bufferedReader.close();
}
}
默认情况下读取文件是按照utf-8编码 当文件编码格式不是utf-8编码时就会发生中文乱码问题
此时需要转换流来处理 指定文件编码格式
解决办法 使用转换流多包装了一层,修改使用字节流读取文件,后使用bufferedReader转换
InputStreamReader()对象通过构造器传入节点流和编码格式,返回转换流之后在使用包装流包装读取数据
public class CodeQuestion {
public static void main(String[] args) throws IOException {
// 读取一个字符文件将内容输出到控制台
// 默认情况下读取文件是按照utf-8编码
String pathName = "D:\\测试\\new.txt";
// 创建字符流
FileInputStream fileInputStream = new FileInputStream(pathName);
// 创建转换流
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"gbk");
// 创建包装流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = null;
while ((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
bufferedReader.close();
}
}
将字节流FileOutputStream 包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式)
/**
* 演示OutputStreamWriter(转换流)的使用
* 将字节流FileOutputStream 包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式)
*/
@Test
public void test01() throws IOException {
String path = "D:\\测试\\test05.txt";
// 创建节点流 加true不会覆盖
FileOutputStream fileOutputStream = new FileOutputStream(path,true);
// 创建转换流
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"gbk");
// 创建包装流
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
String str = "张江博,要加油鸭!!!";
bufferedWriter.write(str);
bufferedWriter.newLine();
bufferedWriter.flush();
bufferedWriter.close();
}
4.9、打印流-PrintStream 和 PrintWriter
只有输出流没有输入流
PrintStream 字节流
PrintWriter 字符流
/**
* 演示 PrintStream 字节打印/输出流
*/
public class PrintStreamTest {
public static void main(String[] args) throws IOException {
PrintStream out = System.out;
// 在默认的情况下, PrintStream打印数据的位置是标准输出,即显示器
out.print("hello");
/**
*
* 底层调用方法
* public void print(String s) {
* if (s == null) {
* s = "null";
* }
* write(s);
* }
* 真正执行的是write方法
* 我们也可以直接调用write方法直接进行输出
*/
out.write("你好".getBytes());
out.close();
// 我们可以修改打印流输出的位置
System.setOut(new PrintStream("D:\\测试\\test05.txt"));
System.out.println("hello 这是文件输出");
}
}
/**
* PrintWriter 使用方法
*/
public class PrintWriterTest {
public static void main(String[] args) throws IOException {
// 会输出到控制台
// PrintWriter printWriter = new PrintWriter(System.out);
// 输出到文件
PrintWriter printWriter = new PrintWriter(new FileWriter("D:\\测试\\test05.txt"));
printWriter.print("hi,张江博");
// 一定要关闭,否则写不进文件 ,只有close之后才会将数据写进文件
printWriter.close();
}
}
4.10、 Properties类
从配置文件获取属性的值
要求配置文件中数据的格式
- 专门用于读写配置文件的集合类
- 配置文件格式:key=value- 注意:键值对不需要有空格,值不需要用引来引起来,默认类型是String
不使用Properties类获取
public class PropertiseTest {
public static void main(String[] args) throws IOException {
// 读取mysql.properties配置文件中的值
// 使用原先的方法
String path = "src/main/resources/mysql.properties";
FileReader fileReader = new FileReader(path);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = null;
while ((line = bufferedReader.readLine()) != null){
String[] split = line.split("=");
System.out.println(split[0]+"值为:"+split[1]);
}
}
}
Properties的常见方法
- load:加载配置文件的键值对到Properties对象
- list:将数据显示到指定设备
- getProperty(key):根据键获取值
- setProperty(key,value):设置键值对到Properties对象
- store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
/**
* 使用Propertise类获取配置文件数据
*/
@Test
public void test01() throws IOException {
// 创建Properties对象
Properties properties = new Properties();
String path = "src/main/resources/mysql.properties";
FileReader fileReader = new FileReader(path);
// 加载指定配置文件
properties.load(fileReader);
// 吧数据显示到控制台
properties.list(System.out);
// 根据key获取对应的值
String possword = properties.getProperty("possword");
System.out.println(possword);
}
/**
* 使用Propertise类来创建配置文件或者修改配置文件
*/
@Test
public void test02() throws IOException {
// 创建对象
Properties properties = new Properties();
// 创建
// 如果该文件没有key,就是创建
// 如果有这个key,就是修改
properties.setProperty("charset","utf-8");
properties.setProperty("user","张江博");
properties.setProperty("possword","xiaoxiaomini.521");
// 将k-v存储到文件中
properties.store(new FileOutputStream("src/main/resources/mysql2.properties"),null);
System.out.println("保存配置文件成功");
}
可能会遇到的问题
1、读取到文件中中文乱码,查看程序设置的字符集是否是UTF-8