I/O流(复习)
File类
File类可以操作文件和目录,它可以新建,删除,重命名文件,但是不能修改文件的内容,它可以使用文件路径来创建
文件过滤:通过File类中的list()方法可以接收一个FilenameFilter参数,通过该参数可以列出符合的文件
关于FilenameFilter,它是一个接口,只有一种方法accept(),所以要想使用这个类必须创建一个类来继承它,所创建的这个类还需要重写accept()方法
import java.io.File;
import java.io.FilenameFilter;
//java程序中的路径指的是java命令执行时所在路径。
public class T4 {
public static void main(String[] args) throws Exception {
File f = new File(".");//”.”或”.\”代表当前目录,这个目录也就是jvm启动路径.
//比如有个项目名为blog,其完整路径为:D:\work\IDE\workspace\blog.那么这个路径就是jvm的启动路径了.
MyFilter filter = new MyFilter(".java");
String[] files = f.list(filter);
for (String a : files) {
System.out.println(a);
}
}
static class MyFilter implements FilenameFilter {
private String type;
public MyFilter(String type) {
this.type = type;
}
public boolean accept(File dir, String name) {//必须重写accept(File file,String path)方法
return name.endsWith(type);
}
}
}
I/O流
java的所有流都是由InputStream(字节输入流),Reader(字符输入流),OutputStream(字节输出流),Writer(字符输入流)派生而来
字符流与字节流的用法几乎一样,只是他们的操作单位不一样,字节流的操作单位是8字节,字符流为16字节
字节流
FileInputStream示例:
import java.io.FileInputStream;
public class FileInputStreamTest {
public static void main(String[] args)throws Exception{
//创建字节输入流
FileInputStream fis=new FileInputStream("name");//输入路径
byte[] bbuf=new byte[1024];//创建一个数组,每次讲取出来的数据装到这里
//保存实际读取的字节
int hasRead=0;
while((hasRead=fis.read(bbuf))>0){
System.out.print(new String(bbuf,0,hasRead));//创建一个字符串,这是一个字符串构造器,将一个数组转为字符串
}
fis.close();
}
}
这样所写入的程序会覆盖原文件,原文件的信息会被删除,可以用如下方法来续写文件
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutPutStreamTest2 {
public static void main(String[] args)throws IOException {
File file=new File("C:\\Users\\xxx\\Desktop\\a.txt");
FileOutputStream fos=new FileOutputStream(file,true);//指定为需要续写的文件
String str="\r\n"+"efg";
fos.write(str.getBytes());
fos.close();
}
}
此处需要注意\r\n:
\r:回车的意思,光标回到本行行首
\n:换行的意思,光标向下移一行
\r\n合起来使用就是换行的意思
将文件输入输出流结合来使用,制作一个文件复制器,代码如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFileTest {
//利用字节流来复制文件
public static void main(String[] args) throws IOException{
File scr=new File("D:\\下载\\a.jpg");
File dest=new File("C:\\Users\\xxx\\Desktop\\ab.jgp");
//划分明确输入和输出流
FileInputStream fis=new FileInputStream(scr);
FileOutputStream fos=new FileOutputStream(dest);
//使用输入流的方法读取字节,并输出
int ch=0;
while((ch=fis.read())!=-1){
fos.write(ch);
}
//关闭资源
fis.close();
fos.close();
}
}
我们所使用的是字结流,这种复制速度过于缓慢,所以我们可以利用缓冲数组的方式,一次多读进去几个内容
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFIleByBufferTest {
public static void main(String[] args) throws IOException {
//继续先创建文件
File scr=new File("D:\\下载\\a.jpg");
File dest=new File("C:\\Users\\XXX\\Desktop\\ab.jgp");
//创建输入输出流
FileInputStream fis=new FileInputStream(scr);
FileOutputStream fos=new FileOutputStream(dest);
int len=0;
byte[] buf=new byte[1024];
while((len=fis.read(buf))!=-1){
fos.write(buf);
}
fos.close();
fis.close();
}
}
这样效率就提高了
以上所列举的都是字节流,如果我们所面对的中文字符,我们就需要考虑这个
字符流
如果我们继续使用字节流去读取中文文件的话,那我们所读取到的是一些奇怪的字符例如,我们使用文件字节输入流来读取文件中的“哈哈”两个字
所得到的就是这样的符号,这就要我们去通过编码翻译
通过字符流来FileReader来读取文件
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo {
//利用字符流来读取文件
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("C:name");
int ch=0;
while((ch=fr.read())!=-1){
System.out.print(ch);//输出对应的值
System.out.print((char)ch);//输出字符本身
}
}
}
通过字符流FileWirter来写文件
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
public static void main(String[] args) throws IOException {
FileWriter fw=new FileWriter("C:\\Users\\xxx\\Desktop\\a.txt");
fw.write("嘿嘿");//这些文字都写入了缓存区,需要边写边刷新
fw.flush();
fw.close();
}
}
此处要特别注意在写完需要刷新flush()
此处使用了flush()和close()
flush()是刷新流,刷新后流还可以继续使用
close()是直接关闭流,close()自带刷新
最后还是利用字符输入输出流来练习文件的复制
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyTextFileTest {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("D:\\下载\\a.jpg");
FileWriter fw=new FileWriter("C:\\Users\\王敏航\\Desktop\\ab.jpg");
char[] buf=new char[1024];
int len=0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
}
fr.close();
fw.close();
}
}
总结:在输入流方面,字节都是可以使用单个的int型数来接收的,字节输入流使用byte[]数组,而字符输入流则使用char[]
输出流方面,要特别注意字符输出流每次write完都要flush
上面我们所看到的字符流中有两个转换流,FileWriter和FileReader都是两个转换流的子类,FileWriter和FileReader使用的是默认编码表
转换流
转换流就是字符流与字节流之间的桥梁
OutputStreamWriter类,它是字符流转向字节流的桥梁,它的作用是指定特定的编码方式,再使用字节流以指定的编码方式写出去
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class writeCN {
public static void main(String[] args) throws IOException {
FileOutputStream fos=new FileOutputStream("name");
//创建可以把字符转为字节的转换流对象
OutputStreamWriter osw=new OutputStreamWriter(fos,"utf-8");
osw.write("abc");//调用转换流,写入缓存,注:这里是写入缓存,所以要刷新
osw.close();
}
}
注:使用该转换流写入后需要刷新
InputStreamReader:是字节流通向字符流的桥梁,字节流读取的数据通过它进行指定的编码,展示出来
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
public class InputStreamreaderDemo {
public static void main(String[] args) {
//创建字节流
FileOutputStream is=new FileInputStream("");
//创建转换流
InputStreamReader isr=new InputStreamReader(is,"utf-8");
int ch=0;
while((ch=isr.read())!=-1){
System.out.print((char)ch);
}
isr.close();
}
}
总结:
字节--->字符 : 看不懂的--->看的懂的 需要读 输入流 InputStreamReader
字符--->字节 : 看的懂的--->看不懂的 需要写 输出流 OutputStreamWriter
缓冲流
在之前的操作中,如果需要的数据多了,就会影响速度,所以就要用到缓冲流,缓冲流也分为字节缓冲流和字符缓冲流
l 字节缓冲输出流 BufferedOutputStream
l 字节缓冲输入流 BufferedInputStream
l 字符缓冲输入流 BufferedReader
l 字符缓冲输出流 BufferedWriter
使用缓冲流都是对基础的字符字节流进行封装
直接上代码来看
字节缓冲输入流BufferedOutputStream
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedOutputDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos=new FileOutputStream("name");//创建基础的字节输出流
BufferedOutputStream bos=new BufferedOutputStream(fos);//对字节输出流进行封装
bos.write("asd".getBytes());
bos.close();
}
}
字节缓冲输入流BufferedInputStream
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException {
//创建基础字节输入流
FileInputStream fis=new FileInputStream("name");
//进行封装
BufferedInputStream bis=new BufferedInputStream(fis);
int ch=-1;
while((ch=fis.read())!=-1){
System.out.print((char)ch);
}
fis.close();
}
}
字符缓冲输出流BufferedWriter
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
FileWriter fw=new FileWriter("name");
BufferedWriter bw=new BufferedWriter(fw);
for(int i=0;i<5;i++){
bw.write("ad");
bw.newLine();//换行
}
bw.close();
}
}
字符缓冲输入流BufferedReader
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
//1,创建流
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
//2,读数据
//一次一个字符
//一次一个字符数组
//一次读取文本中一行的字符串内容
String line = null;
while( (line = in.readLine()) != null ){
System.out.println(line);
}
//3,关闭流
in.close();
}
}
如果使用字符流会更加高效,下面使用字符流来完成复制功能
import java.io.*;
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//1,指定数据源, 是数据源中读数据,采用输入流
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
//2,指定目的地,是把数据写入目的地,采用输出流
BufferedWriter out = new BufferedWriter(new FileWriter("copyFile.txt"));
//3,读数据
String line = null;
while ( (line = in.readLine()) != null ) {
//4,写数据
out.write(line);
//写入换行符号
out.newLine();
}
//5,关闭流
out.close();
in.close();
}
}
Properties集合
它是唯一一个能和IO流交互的集合,是一个持久集合,它的值以键值的形式存储,下面通过个栗子来了解这个集合
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
public static void main(String[] args) {
//创建集合对象
Properties prop=new Properties();
//添加元素到集合中
prop.setProperty("王","haha");//调用 Hashtable 的方法 put
prop.setProperty("sad","asda");
prop.setProperty("sads","2we");
//遍历集合
Set<String> keys=prop.stringPropertyNames();//返回此序列中的键集
for(String key:keys){
String val=prop.getProperty(key);//通过键得到值得
System.out.print(key+" "+val);//输出
}
}
}
我们可以使用IO流将这个集合存到文件中,这里的核心方法是store()
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class PropertiesDemo2 {
public static void main(String[] args) throws IOException {
Properties prop=new Properties();
prop.setProperty("a","b");
prop.setProperty("c","d");
prop.setProperty("e","f");
FileWriter out=new FileWriter("prop.properties");//文件名
prop.store(out,"save data");
out.close();
}
}
也可以利用输入流将它读取,这里的核心方法是load()
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class PropertiesDemo3 {
public static void main(String[] args) throws IOException {
//创建集合
Properties prop=new Properties();
//创建流对象
FileInputStream fis=new FileInputStream("prop.properties");
prop.load(fis);
System.out.print(prop);
}
}
序列化和反序列化
序列化就是向流中写入对象
反序列化就是从流中读取对象
序列化ObjectOutputStream,首先,已经存在一个已知的类person,而且这个被序列化的类还必须实现Serializable接口
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException {
//明确存储对象的文件
FileOutputStream fos=new FileOutputStream("D:\\下载\\obj.object");
//对其进行封装
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(new Person("wang",19));
oos.close();
}
}
反序列化ObjectInputStream,刚刚已经序列化了一个对象,现在我们来反序列化,读取刚才所序列化的内容
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectStreamDemo2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis=new FileInputStream("D:\\下载\\obj.object");
ObjectInputStream ois=new ObjectInputStream(fis);
Person obj=(Person) ois.readObject();
System.out.print(obj.toString());
}
}
当一个对象被序列化,必须实现Serializable接口,这个借口给需要序列化的类提供了一个序列版本号。
如果不想序列化类中的某一变量,可以使用transient来修饰这个变量
打印流
打印流能方便的打印各种数据
字节打印流:PrintStream
字符打印流:PrintWriter
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriterDemo {
public static void main(String[] args)throws IOException {
//创建流
PrintWriter pw=new PrintWriter("p.txt");
//直接打印
for(int i=0;i<5;i++){
pw.println("abc");
}
pw.close();
}
}
public PrintWriter(OutputStream out, boolean autoFlush)
public PrintWriter(Writer out, boolean autoFlush)
可以开启自动刷新
总结一下:了解了File类,字节流和字符流(最基础的流),以及转换流和他们的子类(可以设置字符流,字节流的输入输出编码方式) 缓冲流(属于封装流,可以提升效率) Properties集合(唯一一个可以和IO流交互的集合,内容以键值对的形式存在) 序列化与反序列化(将一个类序列化后存起来) 打印流
上一篇: Java文件读写(一)
下一篇: PHP addslashes 的高级写法