java文本文件的读取操作(字符流)
文章目录
java文本文件的读取操作(字符流)
前面的博文了解的是字节流的输入和输出的操作,本文是字符流,有所不同的哦。
Reader类及其子类
Reader类和FileReader类的常用方法
-
字符输入流Reader类的常用方法
int read()
int read(char [] c)
int read(char [] c,int off,int len)
void close()
Reader是作为抽象基类不可以创建对象,所以需要其子类FileReader类创建对象,接下来了解一下FileReader类的构造方法
-
FileReader类的构造方法
FileReader(File file)
FileReader(String pathname)
Reader类的常用方法的说明可以参考上一篇博文的说明,只不过是将字节流换成了字符流。
示例
-
FileReader读取文件
引入资源
创建FileReader对象
调用相应的read()读取文件
关闭字符流
package Test;
//1.引入资源
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
//借助字符输入流FileReader读取文件
public class FileReaderDemoTest {
public static void main(String[] args) {
FileReader fr = null;
//2.创建字符输入流FileReader对象
try {
fr = new FileReader("E:\\file\\code\\java\\day01\\src\\Test\\test.txt");
//3.调用FileReader对象的read()方法读取文件
StringBuffer s = new StringBuffer();
char[] ch = new char[1024];
int len = -1;
while ((len = fr.read(ch)) != -1) {
s.append(ch);
}
System.out.println(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭字符输入流
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
在从文本文件中读取字符到控制台时可能会出现乱码问题,其实根本问题是文本文件的编码格式和程序环境中编码格式不一致导致的,如果要改正的话就需要调整到一致即可。
这里给出在java中特有的第二种解决方式:
-
使用Reader子类InputStreamReader,其构造方法如下:
InputStreamReader(InputStream in)
InputStreamReader(InputStream in,String charsetName)
更改现在的代码如下:
package Test;
//1.引入资源
import java.io.*;
//借助字符输入流FileReader读取文件
public class FileReaderDemoTest {
public static void main(String[] args) {
Reader fr = null;
//2.创建字符输入流FileReader对象
try {
//查看当前的文件的编码
System.out.println(System.getProperty("file.encoding"));
// fr = new FileReader("E:\\file\\code\\java\\day01\\src\\Test\\test.txt");
//创建字符输入流InputStreamReader对象
FileInputStream fis = new FileInputStream("E:\\file\\code\\java\\day01\\src\\Test\\test.txt");
fr = new InputStreamReader(fis, "UTF-8");
//3.调用FileReader对象的read()方法读取文件
StringBuffer s = new StringBuffer();
char[] ch = new char[1024];
int len = -1;
while ((len = fr.read(ch)) != -1) {
s.append(ch);
}
System.out.println(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭字符输入流
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
BufferedReader类
为了提高字符流读取文本文件的效率,可以使用BufferedReader类:
BufferedReader类是Reader类的子类
BufferedReader类带有缓冲区
按行读取内容的readLine()方法,这是BufferedReader特有的方法
- BufferedReader常用的构造方法
BufferedReader(Reader in)
- BufferedReader类读取文本文件的步骤:
1.引入相关的类
2.构造BufferedReader对象和FileReader对象
3.调用readLine()方法读取数据
4.关闭文件流对象
需要注意的是BufferedReader读取包含中文的文本文件时,可能包含乱码,这种情况下要使用InputStreamReader并设置编码格式。
package Test;
//1.引入资源
import java.io.*;
//借助字符输入流FileReader读取文件
public class BufferedReaderDemoTest {
public static void main(String[] args) {
Reader fr = null;
BufferedReader br = null;
FileInputStream fis = null;
//2.创建字符输入流FileReader对象
try {
//查看当前的文件的编码
System.out.println(System.getProperty("file.encoding"));
// fr = new FileReader("E:\\file\\code\\java\\day01\\src\\Test\\test.txt");
//创建带有缓冲区的字符输入流BufferedReader对象
fis = new FileInputStream("E:\\file\\code\\java\\day01\\src\\Test\\test.txt");
fr = new InputStreamReader(fis, "UTF-8");
br = new BufferedReader(fr);
//3.调用BufferedReader对象的readLine()方法读取文件
String s = null;
while ((s = br.readLine()) != null) {
System.out.println(s);
}
// StringBuffer s = new StringBuffer();
// char[] ch = new char[1024];
// int len = -1;
// while ((len = fr.read(ch)) != -1) {
// s.append(ch);
// }
// System.out.println(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭字符输入流
try {
br.close();
fr.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Writer及其子类
- Writer类的常用方法
write(String str)
write(String str,int off,int len)
void close()
void flush()
- FileWriter类是Writer的孙子类
FileWriter(File file)
FileWriter(String pathname)
带boolean类型的参数构造方法
package Test;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class FileWriterDemoTest {
public static void main(String[] args) {
Writer fw = null;
try {
System.out.println(System.getProperty("file.encoding"));
fw = new FileWriter("E:\\file\\code\\java\\day01\\src\\Test\\test.txt", true);
String s = "hello writer,字符输出流";
fw.write(s);
//指定字符串的特定内容写入文件
// fw.write(s,0,3);
fw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FileWriter类只可以按照本地的字符编码格式进行写数据,用户不可以指定其他的字符编码类型,这样就导致了可能出现乱码。
- 在Writer子类OutputStreamWriter常用的构造方法:
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out,String charsetname)
可以看到在Writer的子类OutputStreamWriter中可以指定编码格式。
修改后的代码:
package Test;
import java.io.*;
//借助字符输出流Writer-OutputStreamWriter往文件中写入内容,解决中文乱码的问题
public class OutputStreamWriterDemoTest {
public static void main(String[] args) {
Writer fw = null;
FileOutputStream fos = null;
OutputStreamWriter osw = null;
System.out.println(System.getProperty("file.encoding"));
try {
fos = new FileOutputStream("E:\\file\\code\\java\\day01\\src\\Test\\test.txt");
//字符输出流,把一个字节输出流做包装,包装的同时指定字符编码格式
osw = new OutputStreamWriter(fos, "GBK");
String s = "hello writer,字符输出流";
osw.write(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
osw.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
BufferedWriter类
BufferedWriter类是Writer类的子类,是带有缓冲区的,可以提高字符流写文本文件的效率。
- BufferedWriter类的常用的构造方法:
BufferedWriter(Writer out)
- BufferedWriter类写文件的步骤
1.引入相关的类
2.构造BufferedWriter对象和FileWriter对象
3.调用write()方法写数据
4.流对象的清空和关闭
package Test;
import java.io.*;
public class BufferedWriterDemoTest {
//借助字符输出流BufferedWriterDemoTest往文件中写入内容,是带有缓冲区的,提高效率
public static void main(String[] args) {
Writer fw = null;
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try {
System.out.println(System.getProperty("file.encoding"));
fos = new FileOutputStream("E:\\file\\code\\java\\day01\\src\\Test\\test.txt", true);
//字符输出流:把一个字节输出流做包装,包装的同事指定字符编码格式
osw = new OutputStreamWriter(fos, "GBK");
//带有缓冲区的字符输出流
bw = new BufferedWriter(osw);
bw.write("第一行内容");
bw.newLine();
bw.write("第二行内容");
bw.newLine();
bw.write("第三行内容");
bw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
osw.close();
fos.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符输入流和输出流的综合练习
- 需求读取模板文件pet.template的格式内容(保存宠物的数据),将模板文件中的{name} {type}{master}替换为具体的宠物信息,将替换后的内容重新写在pet.txt中。
pet.template的内容如下:
您好,我的名字是{name},我是一只{type},我的主人是{master}
package Test;
import java.io.*;
//读取模板文件pet.template的模板格式内容(保存宠物数据)
//把{name} {type} {master}替换为具体的宠物信息
//将替换后的内容重新写入到pet.txt中
public class ReaderAndWriterDemoTest {
public static void main(String[] args) {
//使用带有缓冲区的字符输入流读取文件pet.template
InputStreamReader isr = null;
BufferedReader br = null;
// 使用带缓冲区的字符输出流将替换后的内容重新写入到pet.txt中
BufferedWriter bw = null;
OutputStreamWriter osw = null;
try {
isr = new InputStreamReader(new FileInputStream("E:\\file\\code\\java\\day01\\src\\Test\\pet.template"), "UTF-8");
br = new BufferedReader(isr);
//读取的内容
StringBuffer sbf = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
sbf.append(line);
}
System.out.println("替换前: " + sbf);
String newStr = sbf.toString();
newStr = newStr.replace("{name}", "欧欧");
newStr = newStr.replace("{type}", "狗狗");
newStr = newStr.replace("{master}", "张三");
System.out.println("替换后: " + newStr);
//将新内容写入到pet.txt文件中
osw = new OutputStreamWriter(new FileOutputStream("E:\\file\\code\\java\\day01\\src\\Test\\pet.txt"), "UTF-8");
bw = new BufferedWriter(osw);
bw.write(newStr);
bw.flush();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
isr.close();
bw.close();
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
读写二进制文件
之前实现的都是文本文件的读取和写入的操作,但是文件还包括了图片 音频 视频 等等,那么怎样去读取和写入他们呢?
DataInputStream类
DataInputStream是FileInputStream的子类,和FileInputStream类结合使用读取二进制文件
DataOutputStream类
DataOutputStream是FileOutputStream的子类,和FileOutputStream类结合使用写入二进制文件
- 需求:在"C:\Users\root\Downloads\2018110709261249256.png"有一个png格式的图片,将它复制到项目当前路径下"E:\file\code\java\day01\src\Test"
package Test;
import java.io.*;
//借助Data
public class CopyPicture {
public static void main(String[] args) {
//读取图片文件"C:\Users\root\Downloads\2018110709261249256.png"
DataInputStream dis = null;
FileInputStream fis = null;
//将图片文件写入到E:\file\code\java\day01\src\Test\mycoder.png
DataOutputStream dos = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("C:\\Users\\root\\Downloads\\2018110709261249256.png");
dis = new DataInputStream(fis);
fos = new FileOutputStream("E:\\file\\code\\java\\day01\\src\\Test\\mycoder.png");
dos = new DataOutputStream(fos);
int temp;
while ((temp = dis.read()) != -1) {
dos.write(temp);
}
System.out.println("图片已经复制");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dos.close();
fos.close();
dis.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
序列化和反序列化
序列化
序列化就是将内存中的java对象写入到特定的流的过程。
序列化的操作就用到了对象输出流ObjectOutputStream,ObjectOutputStream可以结合FileOutputStream()使用可以实现序列化。
- 序列化的步骤
实现Serializable接口
创建对象输出流
调用writeObject()方法将对象写入文件
关闭对象输出流
使用集合保存对象那个,可以将集合中的所有对象序列化。
需要我们注意的是如果想要对象序列化或者是反序列化就必须遵守java.io.Serializable接口.
反序列化
反序列化就是从特定的流中获取数据重新构建对象的过程。反序列化用到了对象输入流ObjectInputStream,结合FileInputStream使用,实现对象的反序列化,可以使用Object readObject()方法读取对象。
- 反序列化的步骤
实现Serializable接口
创建对象输入流
调用readObject()方法读取对象那个
关闭对象输入流
package Kind;
import java.io.Serializable;
public class Student implements Serializable {
private int age;
private String name;
private String sex;
//避免密码被序列化和反序列化
private transient String password;
public Student() {
}
public Student(int age, String name, String sex, String password) {
this.age = age;
this.name = name;
this.sex = sex;
this.password = password;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", password='" + password + '\'' +
'}';
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
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;
}
}
package Serialize;
import Kind.Student;
import java.io.*;
//序列化和反序列化学员对象
public class SeriaStu {
public static void main(String[] args) {
Student student = new Student(18, "张三", "男", "1263456");
//对象输出流
ObjectOutputStream oos = null;
FileOutputStream fos = null;
//对象输入流
ObjectInputStream ois = null;
FileInputStream fis = null;
try {
//构建对象输出流,为序列化做准备
fos = new FileOutputStream("E:\\file\\code\\java\\day01\\src\\Test\\student.txt");
oos = new ObjectOutputStream(fos);
//构建对象输入流,为反序列化做准备
fis = new FileInputStream("E:\\file\\code\\java\\day01\\src\\Test\\student.txt");
ois = new ObjectInputStream(fis);
//实现对象序列化
oos.writeObject(student);
//实现对象的反序列化
Student student1 = (Student) ois.readObject();
System.out.println("反序列化出来的学生信息:" + student1.getName() + "-" + student1.getAge() + "-" + student1.getSex() + "-" + student1.getPassword());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
fis.close();
oos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
上一篇: 增加数组的长度
推荐阅读