目录
字符流FileReader
字符流是什么?
字符流是可以直接读写字符的IO流
字符流读取字符,就要先读取到字节数据,然后转为字符,如果要写出字符,需要把字符转为字节再写出
FileReader类的read()方法可以按照字符大小读取
import java.io.FileReader;
import java.io.IOException;
public class demo1 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("xxx.txt");
int c ;
while((c = fr.read())!=-1){ //通过项目默认的码表一次读取一个字符
System.out.print((char)c);
}
fr.close();
}
}
FileWriter
import java.io.FileWriter;
import java.io.IOException;
public class demo2 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("yyy.txt");
fw.write("大家好。");
fw.close();
}
}
字符流的拷贝
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class demo3 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("xxx.txt");
FileWriter fw = new FileWriter("yyy.txt");
int c;
while((c=fr.read())!=-1) {
fw.write(c);
}
fr.close();
fw.close(); //writer类中有一个2k的小缓冲区,如果不关流就会将
//内容写到缓冲区里
}
}
什么情况下使用字符流
字符流也可以拷贝文本文件,但是不推荐使用,因为读取时会把字节转为字符,写出时还要把字符转回字节
程序需要读取一段文本,或者需要写出一段文本的时候可以使用字符流
读取的时候是按照字符的大小读取的不会出现半个中文,写出的时候可以直接将字符串写出不用转换为字节数组
字符流是否可以拷贝纯文本文件
不可以拷贝纯文本文件
因为再读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字节,就会用?代替,写出的时候会将字符转换成字节写出去,如果是?,直接写出之后的文件就乱了看不了了
自定义字符流数组
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class demo4 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("xxx.txt");
FileWriter fw = new FileWriter("yyy.txt");
int len;
char[] arr = new char[1024];
while((len=fr.read(arr)) != -1){
fw.write(arr,0,len);
}
fw.close();
fr.close();
}
}
带缓冲的字符流
import java.io.*;
public class demo5 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("yyy.txt"));
int c;
while((c=br.read())!=-1) {
bw.write(c);
}
br.close();
bw.close();
}
}
readLine()和newLine()
BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
BufferedWrite的newLine()方法可以输出一个跨平台的换行符号"\r\n"
import java.io.*;
public class demo6 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("yyy.txt"));
String line;
while((line = br.readLine()) != null){
bw.write(line);
//bw.write("\r\n"); //只支持windows
bw.newLine(); //跨平台
}
br.close();
bw.close();
}
}
将文本反转
将一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换
import java.io.*;
import java.util.ArrayList;
public class test {
public static void main(String[] args) throws IOException {
//创建临时存储集合并将读到数据存储进去
ArrayList<String> al = new ArrayList<>();
String line;
BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
while((line = br.readLine())!=null){
al.add(line);
}
br.close();
BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
//将存储在集合中的临时数据倒叙写到文件上
for(int i = al.size()-1;i>=0;i--){
bw.write(al.get(i));
bw.newLine();
}
bw.close();
}
}
注意事项:流对象尽量晚开早关
LineNumberReader
LineNumberReader是BufferedReader的子类,具有相同的功能,并且可以统计行号
调用getLineNumber()方法获取当前行号
调用setLineNumber()方法设置当前行号
装饰设计模式
public class demo7{
public static void main(String[] args) {
ketang ket = new ketang(new Student());
ket.code();
}
}
interface Coder {
public void code();
}
class Student implements Coder {
@Override
public void code() {
System.out.println("java");
}
}
class ketang implements Coder {
//1.获取被装饰类的引用
private Student s; //获取学生引用
//2.在构造方法中传入被装饰类的对象
public ketang(Student s) {
this.s = s;
}
//3.对原有的功能进行升级
@Override
public void code() {
s.code();
System.out.println("安卓");
System.out.println("...");
}
}
降低耦合性,被装饰的类的变化与装饰类的变化无关
使用指定码表读写字符
FileReader是使用默认码表读取文件,如果需要使用指定码表读取,那么可以使用InputStreamReader(字节流,编码表)
FileWriter是使用默认码表读取文件,如果需要使用指定码表写出,那么可以使用InputStreamWrite(字节流,编码表)
import java.io.*;
public class demo8 {
public static void main(String[] args) throws IOException {
//高效用指定码表读
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("UTF_8.txt"),"UTF-8"));
//高效用指定码表写
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"),"GBK"));
int ch;
while((ch = br.read()) != -1){
bw.write(ch);
}
bw.close();
br.close();
}
}
图解:由于字符流相当于内置了一个编码表,因此这里用字节流
获取文本上字符出现的次数
import java.io.*;
import java.util.TreeMap;
public class test3 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
TreeMap<Character,Integer> tm = new TreeMap<>();
int ch;
while((ch = br.read())!=-1){
char c = (char)ch; //向下强转
// if(!tm.containsKey(c)){
// tm.put(c,1);
// }else{
// tm.put(c,tm.get(c)+1);
// }
tm.put(c,!tm.containsKey(c) ? 1 : tm.get(c)+1);
}
br.close();
BufferedWriter bw = new BufferedWriter(new FileWriter("yyy.txt"));
for(Character k : tm.keySet()){
switch(k) {
case'\t':
bw.write("\\t"+ "=" + tm.get(k));
break;
case'\n':
bw.write("\\n"+ "=" + tm.get(k));
break;
case'\r':
bw.write("\\r" + "=" + tm.get(k));
break;
default:
bw.write(k + "=" + tm.get(k));
break;
}
bw.newLine();
}
bw.close();
}
}
试用版软件
当我们下载一个试用软件,没有购买正版时,每执行一次就会提醒我们还有多少次试用机会,模拟试用软件,当试用次数用完之后提示购买正版
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class test4 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("www.txt"));
String line = br.readLine();
int times = Integer.parseInt(line);
if(times>0){
System.out.println("您还有"+times--+"次试用机会");
FileWriter fw = new FileWriter("www.txt");
fw.write(times + "");
fw.close();
}else{
System.out.println("您试用次数已经完了,请购买正版");
}
br.close();
}
}
F递归
递归的弊端是不能调用次数过多,容易导致栈内存溢出
好处是不用知道循环次数,只要找到递归出口跟入口就好了
构造方法是否可以递归调用:不可以,没有递归出口,不断创建新对象,死循环了。
递归调用是否必须有返回值:不一定(可以有也可以没有)
典型递归问题:
5!=5*4*3*2*1
public static int fun(int num) {
if(num == 1){return num;
}else {
return num *fun(num-1);
File递归练习
从键盘输入接收一个文件夹路径,打印出该文件夹下所有的.java文件名
import java.io.File;
import java.util.Scanner;
public class teste {
public static void main(String[] args) {
File f = getdir();
digui(f);
}
public static File getdir() {
Scanner sc = new Scanner(System.in);
while (true) {
String s = sc.nextLine();
File f = new File(s);
if (f.isFile()) {
System.out.println("您输入的是文件,请重新输入");
} else if (!f.exists()) {
System.out.println("您输入的路径不存在,请重新输入");
} else {
return f;
}
}
}
public static void digui(File f) {
File[] subFiles = f.listFiles();
for(File s : subFiles) {
if(s.isFile()&&s.toPath().endsWith(".java")){
System.out.println(s);
} else if(s.isDirectory()){
digui(s);
}
}
}
}