Java流的分类:
1.按方向分为输入流和输出流(相对于计算机的内存来说,而不是相对于目标或源来说)
输入流: InputStream/Reader
输出流:OutputStream/Writer
2.按读写单位分为字节流(8位)和字符串流(16位)
字节流(字节输入流:InputStream和字节输出流OutputStream)
字符流(字符输入流:Reader和字符输出流Writer)
3.按功能分节点流和处理流
节点流:可以直接从数据源或目的地读写数据
处理流:(包装流):不直接连接到数据源或目的地,是其他流进行封装。目的主要是简化操作和提高性能。
* InputStream/OutputStream都是抽象类,不能实例化。
* java.io.FileInputStream类继承了java.io.InputStream
* 常用的构造方法:
* FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream
* 其中有一个检查异常需要捕获:FileNotFoundException
* 常用方法:
* read():从此输入流中读取一个数据字节。 如果已到达文件末尾,则返回 -1 ,其中有一个检查异常需要捕获:IOException
* close():其中有一个检查异常需要捕获:IOException
*
* 利用FileInputStream读取中文文本时出现乱码?
* 原因:中文汉字占用1个字符(2个字节),FileInputStream每次读取1个字节,利用字符输入流解决
*/
public class TestFileInputStream {
//读取D:/aa.txt的文件内容
public static void main(String[] args) {
FileInputStream fis=null;
try {
fis = new FileInputStream("D:/aa.txt");
int len;
//read():从输入流读取一个字节,如果已到达文件末尾,则返回 -1
while((len=fis.read())!=-1){
char c=(char)len;
System.out.print(c);
}
// fis.close(); //关闭流应该放在try...catch..finally中的finally内,可以确保流被关闭
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
//关闭流:捕获IOException
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* FileOutputStream类继承了OutputStream(抽象类)
* 构造函数:
* FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。
* FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。
* FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。。
* FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流
* 常用的方法:
* write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
* write(int b) 将指定字节写入此文件输出流
* close() 关闭流
*/
public class TestFileOutStream {
public static void main(String[] args) {
File file = new File("D:/bb.txt");
FileOutputStream fos=null;
try {
//如果文件不存在,创建文件
if(!file.exists()){
file.createNewFile();//创建D:/bb.txt
}
//创建FileOutputStream对象
// fos = new FileOutputStream(file);
fos = new FileOutputStream(file,true);//true:是否追加
// fos.write('s');
// fos.write('x');
// fos.write('t');
// String str="zzsxt,is very good!";
// byte[] bs = str.getBytes();//将字符串转换为字节的数组
// fos.write(bs);
String str2="zzsxt,is very good!";
byte[] bs2 = str2.getBytes();//将字符串转换为字节的数组
fos.write(bs2);
System.out.println("写入完毕!");
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
* 字符串的构造函数
* String(byte[] bytes)通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
* String(byte[] bytes, int offset, int length)通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
* 构造函数:
* FileInputStream(File file)
* 常用方法:
* read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
*/
//1.创建FileInputStream对象:将文件转换成文件字节输入流
fis=new FileInputStream(file);//建立"管道"
byte[] bs = new byte[1024];//缓冲区
//2.使用read方法读取内容
int len = fis.read(bs);//从此输入流中将最多 b.length 个字节的数据读入一个 byte数组中
// for (byte b : bs) {
// System.out.print((char)b);
**
* String(char[] value):分配一个新的 String,使其表示字符数组参数中当前包含的字符序列
* String(char[] value, int offset, int count) 分配一个新的 String,它包含取自字符数组参数一个子数组的字符。
*字符流:以字符为单位进行读取
*使用场景:如果读取文本内容时推荐使用字符流进行读取(一个汉字占用的两个字节(一个字符))
*两个抽象基类
* Reader:用于读取字符流的抽象类。
* FileReader:是Reader的子类
* FileReader的构造函数
* FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
* FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader。
* 注意:在创建FileReader对象时需要捕获一个检查异常:FileNotFoundException
* 常用方法:
* int read():读取单个字符。 有一个检查异常需要捕获IOException
* int read(char[] cbuf, int offset,int length):将字符读入数组中的某一部分。
close() 关闭该流并释放与之关联的所有资源。 有一个检查异常需要捕获IOException
//1.将文件转成文件字符输入流
fileReader = new FileReader("D:/aa.txt");
int len;
//2.使用read方法循环读取文件内容
while((len=fileReader.read())!=-1){
char c = (char)len;
System.out.print(c);
/**
* 捕获异常的快捷键:alt+shift+z
*BufferedReader类:继承了Reader类,带缓冲区的输入流,提高读的效率
*按功能划分属于处理流,必须结合节点流进行使用,不能单独使用
*构造函数:
*BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
*BufferedReader(Reader in, int size) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。
*常用方法:
* readLine() 读取一个文本行。
* close() 关闭该流并释放与之关联的所有资源
*/
fr = new FileReader("D:/aa.txt");
//2.创建字符输入缓冲流BufferedReader
br = new BufferedReader(fr);
//3.读取数据
String str;
while((str=br.readLine())!=null){
System.out.println(str);
**
*统计某个文件夹下(包含子文件和文件)的所有代码的行数
* 实现思路:
* 1.获取该文件夹和子文件下的所有文件(递归)
* 2.使用BufferedReader中的readLine()读取行数据
* 技能点:
* File类的常用方法: listFiles(),isDirectory(),exist()
* 递归调用
* FileReader
* BufferedReader: readLine()
*/
public class CodeCounter {
static long count=0;
/**
* 统计指定文件下的代码行数
* @param file
* @throws IOException
*/
public static void calcCode(File file) throws IOException{
//判断文件目录是否存在
if(file.exists()){
//获取该目录下所有的子文件或子目录
File[] fs = file.listFiles();
for (File f : fs) {
//判断是否为目录
if(f.isDirectory()){
calcCode(f);//递归调用
}else{
String fileName = f.getName();
//判断文件是否为java源文件(java源文件的后缀名为.java)
if(fileName.endsWith(".java")){
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
while(br.readLine()!=null){
count++;
}
br.close();
fr.close();
}
}
}
}else{
System.out.println("你要统计的目录不存在!");
}
}
public static void main(String[] args) {
// File file = new File("D:/javacode");
File file = new File("F:/workspaces");
try {
CodeCounter.calcCode(file);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("代码总行数:"+CodeCounter.count);
}
}
**
*BufferedWriter:继承了Writer类,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
*按功能划分属于处理流,必须结合Writer(节点流)进行使用
*构造函数:
*BufferedWriter(Writer out):创建一个使用默认大小输出缓冲区的缓冲字符输出流。
*BufferedWriter(Writer out, int sz): 创建一个使用给定大小输出缓冲区的新缓冲字符输出流
*常用的方法:
*write(int c) : 写入单个字符
*write(String str) : 写入字符串
*flush():刷新该流的缓冲。
*close():关闭此流,但要先刷新它。
*...
*/
public class TestBufferedWriter {
public static void main(String[] args) {
File file = new File("D:/test2.txt");
FileWriter fw=null;
BufferedWriter bw=null;
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write("hello");
bw.newLine();//写入一个行分隔符(换行)
bw.write("hello again!");
bw.newLine();
bw.write("你好!");
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
bw.close();
fw.close();//关闭流时会调用flush()方法刷新缓冲流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
**
* Writer:写入字符流的抽象类
* FileWriter类:Writer的子类,用法与FileOutputStream(读写单位为字节)类似 ,读写单位为字符
* 构造函数:
* FileWriter(File file)根据给定的 File 对象构造一个 FileWriter 对象。
* FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。
* append代表是否追加内容,如果值为false将发生覆盖,否则追加内容。
* FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
* FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
* 常用方法:
* write(int c):写入单个字符。
* write(String str):写入字符串。
* write(char[] cbuf, int off,int len):写入字符数组的某一部分。
write(String str,int off,int len):写入字符串的某一部分。
flush():刷新该流的缓冲。
close():关闭此流,但要先刷新它