java中File详解

#第六部分:IO流

##1. File类的作用
File类是Java.io包中唯一代表磁盘我呢见本身的对象。File类定义类一些与平台无关的方法
来操作文件,File类主要用来获取或处理与磁盘文件相关的信息,像文件名,文件路径,访问
权限和修改日期等,还可以浏览子目录层次结构
File类表示处理文件和文件系统的相关信息。也就是说:File类不具有从文件读取信息和向
文件写入信息的功能,它仅描述了文件本身的属性。

##2. File类中常用方法的使用介绍

  1. 使用File类操作文件和文件夹

    File类提供了如下三种构造方法:
    1.File(File parent,String child):根据parent抽象路径和child路径名来创建一个新的
    File实例
    2.File(String pathname):通过将给定路径名字符串转换成抽象路径名来创建下一个新File实例。
    如果给定字符串是空字符串,则结果是空的抽象路径名
    3.File(String parent,String child):根据parent路径名字符串和child路径名字符串来船舰一个新
    File实例
    使用任意一个构造方法都可以创建一个File对象,然后调用其提供的方法对象文件进行操作

方法名称 说明

boolean canRead()	测试应用程序是否能从指定的文件中进行读取
boolean canWrite()	测试应用程序是否能写当前文件
boolean delete()	删除当前对象指定的文件 .
boolean exists()	测试当前 File 是否存在
String getAbsolutePath()	返回由该对象表示的文件的绝对路径名
String getName()	返回表示当前对象的文件名
String getParent()	返回当前 File 对象路径名的父路径名,如果此名没有父路径则为 null
boolean isAbsolute()	测试当前 File 对象表示的文件是否为一个绝对路径名
boolean isDirectory()	测试当前 File 对象表示的文件是否为一个路径
boolean isFile()	测试当前 File 对象表示的文件是否为一个“普通”文件
long lastModified()	返回当前 File 对象表示的文件最后修改的时间
long length()	返回当前 File 对象表示的文件长度
String[] list()	返回当前 File 对象指定的路径文件列表
String[] list(FilenameFilter)	返回当前 File 对象指定的目录中满足指定过滤器的文件列表
boolean mkdir()	创建一个目录,它的路径名由当前 File 对象指定
boolean mkdirs()	创建一个目录,它的路径名由当前 File 对象指定
boolean renameTo(File)	将当前 File 对象指定的文件更名为给定参数 File 指定的路径名

#获取文件属性
在Java中获取文件属性信息的第一步就是先创建一个File类对象并指向一个已存在的文件长度,然后调用
表1中的方法进行操作
##例1:
public class Test02 {
public static void main(String[] args) {
String path=“C:/window/”;//指定文件所造的目录i
File f=new File(path,“notepad.exe”);
System.out.println(“文件信息图如下:”);
System.out.println("======================");
System.out.println(“文件长度”+f.length());
System.out.println(“文件或者目录:”+(f.isFile()?“使文件”:“不是文件”));
System.out.println(“文件或者目录:”+(f.isDirectory()?“使目录”:“不是目录”));
System.out.println(“是否可读:”+(f.canWrite()?“可写入”:“不可写入”));
System.out.println(“是否可写:”+(f.canRead()?“可读取”:“可写入”));
System.out.println(“是否隐藏:”+(f.isHidden()?“是隐藏文件”:“不是隐藏文件”));
System.out.println(“最后修改日期:”+new Date(f.lastModified()));
System.out.println(“文件名称:”+f.getName());
System.out.println(“文件路径:”+f.getPath());
System.out.println(“绝对路径:”+f.getAbsolutePath());

}
}

文件信息图如下:

======================

文件长度0

文件或者目录:不是文件

文件或者目录:不是目录

是否可读:不可写入

是否可写:可写入

是否隐藏:不是隐藏文件

最后修改日期:Thu Jan 01 08:00:00 CST 1970

文件名称:notepad.exe

文件路径:C:\window\notepad.exe

绝对路径:C:\window\notepad.exe

#创建和删除文件
file类不仅可以获取已知的文件的属性和信息,还可以在指定的路径创建文件,以及删除一个文件,
创建文件需要调用createNew()方法,删除文件需要调用delete方法。无论事创建还是删除文件通常先调用
exits()方法判断文件是否存在。
例2:

public class Test02 {
public static void main(String[] args) throws IOException {
   String path="C:/config/";//指定文件目录
    String filename="dbConfig.xml";//指定文件名称
    File f=new File(path,filename);//创建指向文件的File对象
    if(f.exists())//判断文件是否存在
    {
        f.delete();//存在则先删除
    }
    f.createNewFile();//在创建
}
}

#创建和删除目录
File类出列对文件的创建和删除外,还可以创建和删除目录。创建目录需要调用mkdir()方法,删除目录
需要调用delete()方法。无论是创建还是删除目录都可以调用exists()方法判断目录是否存在。

例3:

public class Test02 {
public static void main(String[] args) throws IOException {
   String path="c:/config/";//指定目录位置
   File f=new File("path");//创建file对象
   if(f.exists()){
       f.delete();
   }
   f.mkdir();//创建目录
}
}

#遍历目录
通过遍历目录可以在指定的文件中查找文件,或者显示所有文件列表。File类的list()方法提供了遍历目录的
功能,该方法有两种重载形式

1.String[] list()

该方法表示返回由File对象表示目录中所有文件和子目录名称组成的字符串,如果调用的File对象不是目录,
则返回null

提示:

list()方法返回的数组中仅包含文件名称,而不包含路径。但不保证所得数组中的相同字符串将以特定顺序
出现,特别是不保证他们按字母顺序出现。

#例四:
public class Test02 {
public static void main(String[] args) throws IOException {
File f=new File(“C:/”);//建立f变量,并设定由f变量引用
System.out.println(“文件名称\t\t文件类型\t\t文件大小 “);
System.out.println(”=======================”);
String fileList[]=f.list();//调用不带参数的list()方法
for (int i=0;i //遍历字符串数组
System.out.print(fileList[i]+"\t\t");
System.out.print((new File(“C:/”,fileList[i])).isFile()?“文件”+"\t\t":“文件夹”+"\t\t");
System.out.println((new File(“C:/”,fileList[i])).length()+“字节”);
}
}
}
#例五:
假设希望只列出目录下的某些文件,这就需要调用带过滤器参数的list()方法,首先需要创建文件过滤器,
该过滤器必须实现java.io.FilenameFilter接口,并在accept()方法中指定允许的文件类型
如:
public class ImageFilter implements FilenameFilter {
//实现FilenameFilter接口
public boolean accept(File dir,String name){
//指定允许的文件类型
return name.endsWith(".sys")||name.endsWith(".txt");
}

}

IO流的概念和工作原理

IO流

##IO流概述及其分类
io概念
IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式
Java用于操作流的类都在IO包中
按流向分为两种
输入流(读取数据)

输出流(写数据)

流按操作类型分为两种:
字节流:字节流可以操作任何数据,因为再计算机中任何数据都是以字节的形式存储的
字符流:字符流只能操作纯字符数据,比较方便
#常用的IO流类
##字节流的抽象父类
inputStream
OutptStream
字符流的抽象父类:
Reader
Writer
InputStream&FileInputStream文件输入流
InputStream是抽象类,表示字节输入流
直接已知子类
AudioInputStream
ByteArrayInputStream
FileInputStream
FilterInputStream
ObjectInputStream
PipedInputStream
SequenceInputStream
StringBufferInputStream
##FileInputStream文件输入流
###概述
FileInputStream从文件系统种的某个文件中获得输入字节。FileInputStream用于读取注入图像
数据之类的原始字节流。要读取字符流
构造方法
FileInputStream(File file)
FileInputStream(String name)
成员方法
int read()从此输入流中读取一个数据字节

案例:读取一个txt文件数据(方法一)

###知识点
1.FileInputStream用于读取文件数据,在构造方法中传入文件对象
2.构造方法,有可能抛出文件找不到的异常
3.read方法是每次读取一个字节的数据,把字节转成int返回
读取数据也会抛出异常,比如突然某个文件某部分数据损坏了
读取的数据是文件编码的表值
ascii是包含在GBK或者Unicode中的
如果读取数据到最后,会返回一个-1(代表读完数据了)
4.文件不用后,要关闭输入流,避免占用资源

    /*
	读取txt文件内容
1.通过FileInputStream来读取txt文件内容
2.读取内容通过read方法
read方法每次读取文件1个字节,把byte转成int返回
当读到最后的时候,返回-1,-1表示读取文件结束
3.当读完文件后,这个输入流要关闭,释放资源
 	*/
	public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建一个文件对象
File file=new File("a.txt");
//创建一个文件输入流【读取文件对象】
FileInputStream fis1=new FileInputStream(file);
//再创建一个文件输入流对象
FileInputStream fis2=new FileInputStream("b.txt");
//3.读取a.txt的数据

/*
1.read方法每次读文件1个字节,把byte转成int返回
2.当读到后的时候,返回-1,-1读取文件结果
 */
System.out.println(fis1.read());

//关闭流
fis1.close();
fis2.close();;
}
	}

例题:读取一个txt文件数据

public class Demo01 {
public static void main(String[] args) throws IOException {
    //1.创建一个文件对象
    File file = new File("abc.txt");
    System.out.println(file.getAbsolutePath());

//2.创建一个文件输入流
    FileInputStream inputStream = new FileInputStream(file);

    int b;
//while循环里,每次读取字节赋值给b
    while((b = inputStream.read()) != -1){
        System.out.println(b);
    }
}
}

###read()方法读取的是一个字节,为什么返回是int,而不是byte?
因为字节输入流可以操作任意类型文件,比如图片,音频等,这些文件底层都是以二进制形式的存储的
如果每次读取都返回byte,有可能在读到中间的时候遇到11111111那么这、11111111是byte类型的-1
我们的程序遇到-1就会停止下来不读了,而后面的程序就读不到了,所以在读取的时候用int类型接受,
如果读到11111111会在其前面补上24个0凑够四个字节,那么byte类型的-1就变成int型地55了,这样
可以保证数据读完
##OutputStream&FileOutputStream文件输出流
文件输出流是用于将数据写入File的输入流
FileOutputStream用于写入诸如图像数据之类的原始字节的流
查看文档的构造方法和成员方法
####案例
new FileOutputStream(file)这种构造方法,会把以前的内容都删除
new FileOutputStream(File,true);这种构造方法能追加内容
FileNotFoundException是IOEException的子类
write(int b)写数据
public class Demo01 {
public static void main(String[] args) throws IOException {
/*
构造方法
FileOutputStream(String name)
FileOutputStream(File file)
方法
write (int b);//每次写一个字节
write(byte[] b)//一次写多个字节
*/
//案例:往b.txt写个内容
//1.创建文件输入流对象
//FileOutputStream fos=new FileOutputStream(“b.txt”);
OutputStream fos=new FileOutputStream(“b.txt”);

    //2.写数据
    fos.write(97);
    fos.write(98);
    fos.write(99);

    //一次性写多个字节
    byte[] bytes={97,98,99,100,101};
    fos.write(bytes);
    //关闭流
    fos.close();
}
} 

##拷贝图片和音频
###原理,使用输入流读取数据,使用输出流写数据
原理和性能
每次读一次字节,太慢,效率太低
public class Demo01 {
public static void main(String[] args) throws IOException {
/**
* 目的:结合输入流和输出流使用
* 图片路径"C:\Users\liguoliang\Desktop\文档\jaca\22.jpg"
/
//1.先创建输入流对象和输出流对象
FileInputStream fis=new FileInputStream(“C:/Users/liguoliang/Desktop/文档/jaca/22.jpg”);
FileOutputStream fos=new FileOutputStream(“c.jpg”);
//2.通过输入流读取图片的数据
int b=0;
while ((b=fis.read())!=-1){
//3.通过输出流写入图片数据
fos.write(b);
}
//4.关闭流
fos.close();
fis.close();
System.out.println(“复制成功”);
}
}
##字节数组拷贝之available()方法
public class Demo01 {
public static void main(String[] args) throws IOException {
/

不建议在大文件下使用
前面拷贝图片问题:每次只读一个字节,写入的时候也是一个字节一个字节的写
如果有10W个字节,就要读10w次,写10w次
字节数组拷贝之available()方法
*/
//文件输入流
FileInputStream fis=new FileInputStream(“C:\Users\liguoliang\Desktop\文档\jaca\22.jpg”);
int size=fis.available();//是返回文件的长度【字节为单位】
System.out.println(“文件的大小:”+size);
//2.现在一次读取文件大小的字节
//定义一个字节数组
byte[] bytes=new byte[size];//相当于现在一个空杯子
//2.2把数据读到字节数组中
int r=fis.read(bytes);//这个方法的返回值读取到实际长度
System.out.println(“r:”+r);
//3.把字节数组一次性的写入文件
//输出流
FileOutputStream fos=new FileOutputStream(“d.jpg”);
//写数据
fos.write(bytes);
//关闭流
fis.close();
fos.close();
}
}

##例题:正确的拷贝文件的方法(被子思想,缓冲思想)

1.输入流读取数据的方法
read(byte[] b)读取指定字节数的数据
2.输出流写数据的方法
write(byte[] b)
write(byte[] b,int off,int len)写出有效的字节个数

/*
杯子思想,缓冲思想
 */
public class Demo01 {
public static void main(String[] args) throws IOException {
  //经常使用
  /*
  1.每次只读一个字节,又觉得太慢
  2.一次性读一个文件的所有数据,又怕内存装不下
  内存只有2G视频3G这样就会内存溢出
  3.最终解决方法:折中,定义每次读8kb
   */
//输入流
    FileInputStream fis=new FileInputStream("C:\\Users\\liguoliang\\Desktop\\文档\\jaca\\22.jpg");
    FileOutputStream fos=new FileOutputStream("f.jpg");
    //3.定义一个8kb字节数组,也称作缓冲流
    byte[] bytes=new byte[1024*8];
    int len=0;
    int i=0;
    while((len=fis.read(bytes))!=-1){
        i++;
        fos.write(bytes,0,len);
    }
    System.out.println("读取次数:"+i);
    //5关闭流
    fis.close();
    fos.close();
}
}

##BufferedInputStream和BufferOutputStream
这两个流是内置了缓冲区流,也就是说内部有一个字节数组
缓冲思想
字节流一次读写一个数组的速度明显比一次读写一个字节的所读快的多
java本身在设计的时候,加入了数组这样的缓冲区效果,也考虑到了这样的设计思想(装饰设计模式
所以提供了字节缓冲区流)
###BufferedInputStream
BufferedInputStream内置了一个缓冲区(数组)
从BufferedInputStream中读取一个字节时
BufferedInputStream会一次性从文件中读取8kb,存在缓冲区中,返回给程序,
程序再次读取时,就不用找文件了,直接从缓冲区获取直到缓冲区中所有的都被使用过,
才重新从文件中读取8kb个
###BufferedOutputStream
BufferedOutputStream也内置了一个缓冲区流(数组)程序向流中写出字节时,不会直接写到文件中
先写到缓冲区中直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里

例题:使用缓冲输入输出文件

public class Demo01 {
public static void main(String[] args) throws IOException {
    //创建文件输入流
    FileInputStream fis=new FileInputStream("C:\\Users\\liguoliang\\Desktop\\文档\\jaca\\23.jpg");
    //2.创建文件输出流
    FileOutputStream fos=new FileOutputStream("j.jpg");
    //3.输入流读取数据,输出流写数据
    int b=0;
    while((b=fis.read())!=-1){
        fos.write(b);
    }
    //4关流
    fis.close();
    fos.close();
    System.out.println("音频拷贝完成。。。");

}
private static void test1() throws IOException {
    /*
    BufferedInputStream和BufferedOutputStream
    这两个流是内置了缓冲区流,也就是说内部有一个字节数组
    这两个类没有前面写的好用,因为它内部每次读8kb字节
     */
    //1.创建缓冲流输入流
    FileInputStream fis=new FileInputStream("C:\\Users\\liguoliang\\Desktop\\文档\\jaca\\23.jpg");
    BufferedInputStream bis=new BufferedInputStream(fis);
    //2.创建缓冲流
    FileOutputStream fos=new FileOutputStream("g.jpg");
    BufferedOutputStream bos=new BufferedOutputStream(fos);
    //输入流读取数据,输出流写数据
    int b=0;
    //bis.read()方法,内部会读8kb数据
    while((b=bis.read())!=-1){
        bos.write(b);//内容会写8kb数据
    }
    //关流,只需要关缓冲流,文件流不用关
    bis.close();
    bos.close();
    System.out.println("拷贝完成");
}
}

带Buffered的流和自己写的数组缓冲对比

自己写的数组的读写和带Buffered 的读取哪个更快?
自己写数组会更好,因为读和写操作的是同一个数组,而Buffered操作的是两个数组

BufferOutputStream的flush和close方法的区别:

flush()方法
用来刷新缓冲区的,刷新后可以再次写出
close()方法
用来关闭流释放资源的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流
之前刷新缓冲区,关闭后不能再写出

例题:

public class Demo01 {
public static void main(String[] args) throws IOException {
   //BufferedOutputStream的flush和close方法的区别
    /*
    flush()方法
    1.用来刷新缓冲区的,刷新后可以再次写出close()方法
    2.用来关闭流释放资源的
    3.如果是带缓冲区的流对象的close()方法,不但会关闭流
    还会再关闭流之前刷新缓冲区,关闭后不能再写出
     */
    //输入流
    FileInputStream fis=new FileInputStream("a.txt");
    BufferedInputStream bis=new BufferedInputStream(fis);
    //2.输出流
    FileOutputStream fos=new FileOutputStream("h.txt");
    BufferedOutputStream bos=new BufferedOutputStream(fos);
    //读写操作
    int b=0;
    while((b=bis.read())!=-1){
        bos.write(b);
    }
    bos.flush();
    bos.write(97);
    //4.关闭流
    bis.close();
    bos.close();
}

}

字节流读写中文乱码问题

字节流读取中文:
字节流读取到中文的问题
字节流在读中文的时候会可能读到半个中文,造成乱码
public class Demo01 {
public static void main(String[] args) throws IOException {
    //字节流读写中文乱码问题
    //1.读取数据
    //创建文件输入流
    FileInputStream fis=new FileInputStream("a.txt");
    //读
    //定义字节数组
    /*
    在UTF-8编码表中,抑恶中文占用三个字节,一个英文占用一个字节
    在GBK中,一个中文占用2歌字节

     */
    byte buf[] =new byte[3];
    int len=0;
    while((len=fis.read(buf))!=-1){
        System.out.println("len"+len);
        //吧字节转成字符串
        String s=new String(buf,0,len);
        System.out.println("s:"+s);
    }
    //关闭
    fis.close();
}
}

字节流写入中文的问题

字节流直接操作的字节,所以写出中文必须将字符串转换成字节数数组

写出回车换行write("\r\n".getBytes())

public class Demo01 {
public static void main(String[] args) throws IOException {
   //1.输出流
    FileOutputStream fos=new FileOutputStream("a.txt");
    //2.写中文
    String s="你好,最近还好吗?" ;
    //把字符串转成字节数组
    //byte[] bytes=s.getBytes();
    /**
     * charsetName 字符编码 UTF-(Unicode),GBK,ASCII
     */
    byte[] bytes=s.getBytes("UTF-8");
    fos.write(bytes);
    //关流
    fos.close();
}

}

流的标准处理异常代码1.7以上版本

原理:在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}

(读写代码)执行后就会自动调用,流对象的close方法将流关掉

public class Demo01 {
public static void main(String[] args) throws Exception {
    //流的标准处理异常代码1.7版本
    /**
     * 1,把流对象的声明放在try()括号里面
     * 2.操作流【读写数据】的代码放在括号里
     * 3.这样写不用关闭流,Java自动关闭流
     * 4.在try的括号里的对象,必须是实现AutoCloseable的接口
     */
    try (
            FileInputStream fis = new FileInputStream("a.txt");
            FileOutputStream fos = new FileOutputStream("c.txt");
            //Person p=new Person();
            //声明一个自己输入流
            MyInputStream myis = new MyInputStream();
    ) {
        int b = 0;
        while ((b = fis.read()) != -1) {
            fos.write(b);
        }
    }
}
}
class Person{

}
class MyInputStream implements AutoCloseable{
@Override
public void close() throws Exception {
    System.out.println("我的输入流关闭了,我太难了");
}
}

练习:图片加密

public class Demo01 {
public static void main(String[] args) throws Exception {
    //图片加密
    //1.输入输出流
    FileInputStream fis=new FileInputStream("c.jpg");
    FileOutputStream fos=new FileOutputStream("j.jpg");
    //2.读写数据
    /**
     * 加密操作
     * 解密操作
     *
     * 一个数亦或2次,数据不变
     */
    int b=0;
    while ((b=fis.read())!=-1){
        fos.write(b^5);
    }
    //关流
    fis.close();
    fos.close();
    System.out.println("图片加密完成");
}

}

根据用户输入的文件拷贝文件到当前项目目录

public class Demo01 {
public static void main(String[] args) throws Exception {
    //1.获取用户输入的文件路径
    Scanner scanner = new Scanner(System.in);
    System.out.println("请输入一个文件的路径");
    String path = scanner.nextLine();
    //2.判断这个路径是否为文件
    File file = new File(path);
    if (file.isDirectory()) {
        System.out.println("您输入的路径不是一个文件");
        return;
    }
    //3.如果是文件就拷贝
    //输入流
    FileInputStream fis = new FileInputStream(path);
    //输出流
    FileOutputStream fos = new FileOutputStream(file.getName());
    //读写数据
    byte[] buf = new byte[8 * 1024];
    int len = 0;
    while ((len = fis.read()) != -1) {
        fos.write(buf, 0, len);
    }
    //关流
    fis.close();
    fos.close();
    System.out.println("文件拷贝完成。。。");
}
}

练习:录入数据拷贝到文件

public class Demo01 {
public static void main(String[] args) throws Exception {
    //练习:录入数据拷贝到文件
    //1.创建一个文件输出流
    FileOutputStream fos=new FileOutputStream("new.txt");
    //2.创建一个Scanner对象
    Scanner scanner=new Scanner(System.in);
    System.out.println("请输入要录取的内容。。。输入quit代表退出");
    //通过死循环来获取用户输入【当输入quit,代表不录入】
    while (true){
        //获取用户的输入
        String line=scanner.nextLine();
        //退出循环
        if(line.equals("quit")){
            break;
        }
        //写入文件
        fos.write(line.getBytes());
        //换行
        fos.write("\r\n".getBytes());
    }
    fos.close();
}
}

##字符流概念
字符流是什么?
1.字符流是可以直接读写字符的IO流
2.字符流读取字符,就要先读取到字节数据,然后转为字符
3.写入字符,需要把字符转为字节再写出
###字符流有Reader和Writer两大派,开发中使用他们的子类
FileReader读取字符流类
FileWriter写入字符流类
##FileReader读取字符流
查看API的方法
案例:使用FileReader读取一个文本数据

1.read方法是读取字符char
2.一个字符可能占用1个字节,2个字节,或者3个字节
3.占用字节个数根据码表决定(ASCII:1字节 GBK:2字节 Unicode:3个字节)
4.用int表示字节,假如读取到2个字节,int有四个字节,前两个字节可以补0
5.GBK,Unicode中,中文的字符的第一个字节都是负数,所以直到怎么去读取
6.读取的方式与与FileInputStream字节流差不多,会用FileInputStream,就会用FileReader
//以后读纯文本使用FileReader这个类,因为我们不用考虑乱码问题
public class Demo01 {
public static void main(String[] args) throws Exception {
    //读字节
    FileInputStream fis=new FileInputStream("a.txt");

    System.out.println((byte)fis.read());
    System.out.println((byte)fis.read());
    System.out.println((byte)fis.read());
    System.out.println((byte)fis.read());
    System.out.println((byte)fis.read());
    System.out.println((byte)fis.read());
    System.out.println((byte)fis.read());
}
public static void test1() throws Exception {
    //FileReader
    /*
    FileReader用于读取字符
     */
    //创建对象
    FileReader reader=new FileReader("a.txt");
    //读取数据
    /*
    reader.read();先读取到字节数据,然后转为字符
     */
    System.out.println((char)reader.read());
    System.out.println((char)reader.read());
    System.out.println((char)reader.read());
    System.out.println((char)reader.read());
    System.out.println((char)reader.read());
    System.out.println((char)reader.read());
    int c;
    while((c=reader.read())!=-1){
        System.out.println((char)c);
    }
    //3关闭流
    reader.close();
}
}

#FileWriter写入字符流
###查看API中FileWriter的方法

案例使用FileWriter写入数据

1.其实内部是通过一个字符数组缓冲区写入文件

2.内部方法,创建一个字符串长度的字符数组缓存区

/**
* FileWriter
 * 掌握:
 * 1.write方法使用
* 2.write方法内部实现,内部是通过一个字符数组缓冲区写入数据
*
 */

public class Demo01 {
public static void main(String[] args) throws Exception {
    //FileWriter文件写入流
    //使用FileWriter往一个文件a.txt写内容
    //1.创建writer对象
    FileWriter writer=new FileWriter("a.txt");
    //写内容
    writer.write("你好!");
    writer.write("\r\n");
    writer.write("你好!");
    writer.write("\r\n");
    writer.write("你好!");
    writer.write("\r\n");
    writer.write("你好!");
    //关闭
    writer.close();
}
}

##案例:字符流的拷贝
//案例:字符流的拷贝
//思路:用FileReader读字符,用FileWriter写字符
public class Demo01 {
public static void main(String[] args) throws Exception {
//创建“读取流”对象
FileReader reader=new FileReader(“a.txt”);
//创建“写入流”对象
FileWriter writer=new FileWriter(“b.txt”);
//3.读取和写入【缓冲思想】
char[] buf=new char[8*1024];
int len=0;
while ((len=reader.read(buf))!=-1){
writer.write(buf,0,len);
}
//关闭流
reader.close();
writer.close();
}
public static void test1() throws Exception {
//1.创建“读取流”对象
FileReader reader=new FileReader(“a.txt”);
//2.创建“写入流”对象
FileWriter writer=new FileWriter(“b.txt”);
//3.读取和写入
int c=0;
while((c=reader.read())!=-1){
writer.write©;
}
//关闭流
reader.close();
writer.close();
}
}
使用字符流场景

	public class Demo01 {
public static void main(String[] args) throws Exception {
//使用字符流的场景
/**
 * 1.使用FileReader读取字符
 *  原理:先读字符,把字节转成字符(byte->char)
 *  2.使用FileWriter写入字符
 *  原理:writer(String str),str转成字符数组再转成字节写入文件
 *  (String->char[] ->char->byte)
 *  如果是读取文本文件,使用FileReader比较好,不考虑乱码问题
 *  如果是写入文本文件,不建议使用FileWriter,直接使用FileOutputStream好一点
 */
}
}

##带缓冲的字符流BufferedReader/BufferedWriter
1.BufferedReader

1.read()方法读取字符时会一次读取若干字符到缓冲区,然后逐个返
回给程序,降低读取文件的次数,提高效率

2.BufferedWriter

1.write()方法写出字符时会先写到缓冲区,缓冲区写满时才会写到
文件,降低写文件的次数,提高效率
2.查看源码:字符缓冲区的大小是8192
public class Demo01 {
public static void main(String[] args) throws Exception {
    /**
     * 带缓冲的字符流BufferedReader/BufferedWriter
     * 1.这两个类,内部都一个缓冲区,字符数组
     * 2.br.read()方法,内部会读8192(8*1024)个字符
     * 3.bw.write(),内部会写8192(8*1024)个字符
     *
     * 带缓冲的字节流,BufferedInputStream/BufferedOutputStream
     * 1.这两个类,内部都一个缓冲区,字节数组
     */
    //拷贝文件,a.txt->b.txt
    //创建Reader
    FileReader fr=new FileReader("a.txt");
    BufferedReader br=new BufferedReader(fr);
    //2.创建Writer
    FileWriter fw=new FileWriter("b.txt");
    BufferedWriter bw=new BufferedWriter(fw);
    //3.读写
    int c=0;
    while((c=br.read())!=-1){
        bw.write(c);
    }
    //关流
    br.close();//内部关闭FileReader
    bw.close();//内部关闭FileWriter
}
}

###BufferedReader的readLine()&BufferedWriter的newLine()方法
public class Demo01 {
public static void main(String[] args) throws Exception {
/**
* 1.readLine(),每次读取一行数据
/
//1.创建Reader
FileReader fr=new FileReader(“a.txt”);
BufferedReader br=new BufferedReader(fr);
//2.读一行数据
/

System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
*/
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
//3.关流
br.close();
}
}
###BufferedWriter的newLine()方法
public class Demo01 {
public static void main(String[] args) throws Exception {
//BufferedWriter的newLine()方法
//newLine()换行
//往b.txt写a.txt文件的内容
//1.创建Reader
FileReader fr=new FileReader(“a.txt”);
BufferedReader br=new BufferedReader(fr);
//2.创建writer
FileWriter fw=new FileWriter(“b.txt”);
BufferedWriter bw=new BufferedWriter(fw);

    //3.读一行写一行
    String line=null;
    while((line=br.readLine())!=null){
        bw.write(line);
        /**
         * 当使用readLine读取一行数据时,不会读回车换行“\r\n”
         */
        //bw.write("\r\n");
        bw.newLine();
    }
    //4.关流
    br.close();
    bw.close();

}
}

####案例:使用带缓冲的字符流拷贝文件
BufferedReader的readLine()&BufferedWriter的newLine()
1.BufferedReader的readLine()方法可以读取一行字符(不包括换行)
2.BufferedWriter的newLine()可以输出一个跨平台的换行符“\r\n”
###将文本反转
一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换
/*
for循环的倒序遍历
/
public class Demo01 {
public static void main(String[] args) throws Exception {
//把文本每一行内容读取出来存在List集合
//集合对象
List list=new ArrayList();
//一行行的读取文本
BufferedReader br=new BufferedReader(new FileReader(“c.txt”));
String line=null;
while((line=br.readLine())!=null){
list.add(line);
}
System.out.println(list);
//当我们写入文件时,倒叙保存List集合中的文本内容
BufferedWriter bw=new BufferedWriter(new FileWriter(“b.txt”));
for (int i=list.size()-1;i>=0;i–){
bw.write(list.get(i));
bw.newLine();//换行
}
//关闭流
br.close();
bw.close();
System.out.println(“完成!”);
}
}
#装饰设计模式
##装饰设计模式的概念
动态的给一个对象添加一些额外的功能,就增加功能来说,装饰模式比
生成子类更为灵活。再不必改变源文件和继承的情况下,动态的扩展一个对象的功能。
它是再创建一个包装对象,也就是使用装饰来包裹真实对象
###适应性
1.需要扩展一个类的功能,或给一个类添加附加职责
2.当不能采用生成子类来实现,比如final类
###装饰模式的实现方式
1.装饰对象和真实的对象有相同的接口
2.装饰对象包含一个真实对象的引用(reference)
3.装饰对象的所有方法,内部实现都是通过真实对象的引用来调用,然后实现自己的功能
####案例:
public class Demo01 {
public static void main(String[] args) throws Exception {
//
/
*
* 设计模式怕【一种固定的代码风格】
* 常用的设计模式:装饰模式,单例模式,模板模式
* 适配器模式,代理模式,工厂模式
* 装饰设计模式
* 1.装饰模式的概念
* 装饰模式是动态的给一个对象添加一些额外的功能,就
* 增加功能来说,双十模式比生成子类更为灵活。装饰模式
* 实在不必改变原类文件和使用继承的情况下,动态的扩展一个
* 对象的功能。装饰模式是创建一个包装对象,也就是使用装饰
* 来包裹真实的对象
*
* 2.装饰设计模式的实现方式
*
* 1.装饰对象和真实对象有相同的接口/抽象类
* 2.装饰对象包含一个真实对象的引用(reference)
* 3.装饰对象的所有方法,内部实现都是通过真实对象的引用来
* 调用,然后实现自己的功能
*
* 3.适用性
* 1.需要扩展一个类的功能,或给一个类添加附职责
* 2.当不能采用生成子类来实现
*
*/
/BufferedInputStream bis=new BufferedInputStream(new FileInputStream(“a.txt”));
BufferedOutputStream bos;
BufferedReader br;
BufferedWriter bw;
GYFStudent stu=new GYFStudent();
stu.code();
/
GYFStudent stu=new GYFStudent(new UniversityStudent());
stu.code();

}
}
//1.接口
interface Person {
public void code();
}
//接口实现类
final class UniversityStudent implements Person{
public void code(){
    System.out.println("我对Java一点也不懂。。。");
}
}
/*class GYFStudent extends UniversityStudent{
@Override
public void code() {
    //
    System.out.println("学也学不会");
}
}*/
class GYFStudent implements Person{
private  UniversityStudent us;
public GYFStudent(UniversityStudent us){
    this.us=us;
}
//装饰对象的所有方法,内部实现都是通过真实对象的引用来
//调用,然后实现自己的功能

@Override
public void code() {
    us.code();
    System.out.println("那我该怎么办?");
}
}

###例题:
public class Demo01 {
public static void main(String[] args) {
GYFStudent stu=new GYFStudent();
stu.coding();
}
}

interface Person{
//人可以具备编码的功能
public void coding();
}
//大学生
class UniversityStudent implements Person{
@Override
public void coding() {
    System.out.println("我会一点点编程");
}
public void piano(){
    System.out.println("我还会点钢琴");
}
}
//第一种继承类的写法
class GYFStudent extends UniversityStudent{
@Override
public void coding() {
    super.coding();
    System.out.println("我已经会Java基础了");
}
}
/*class GYFStudent implements Person{
private UniversityStudent uStu;
public GYFStudent(UniversityStudent uStu){
    super();
    this.uStu=uStu;
}

@Override
public void coding() {
    uStu.coding();
    System.out.println("我会Java基础编程了");
}
}*/

##InputStreamReader&OutputStreamWriter
这两个类用于适用指定的码表读写字符
FileReader是使用默认码表读取文件,如果需要使用指定的码表读取请使用InputStreamReader(字符流,编码表)
FileWriter是使用默认码表写出文件,如果需要使用指定码表写入请使用OutputStreamWriter(字符流,编码表)
public class Demo01 {
public static void main(String[] args) throws Exception {
/*
InputStreamReader&OutputStreamWriter
1.这两个类用于使用指定的码表读写字符
使用指定“码表UTF-8GBK”读取字符
charsetName:字符编码的名称
/
FileInputStream fis=new FileInputStream(“a.txt”);
InputStreamReader isr=new InputStreamReader(fis,“UTF-8”);
//读一个字符
/
System.out.println(isr.read());
System.out.println(isr.read());/
//读一行
BufferedReader br=new BufferedReader(isr);
System.out.println(br.readLine());
br.close();
}
}
public class Demo01 {
public static void main(String[] args) throws Exception {
/

InputStreamReader&OutputStreamWriter
1.这两个类用于使用指定的码表读写字符
使用指定“码表UTF-8GBK”读取字符
charsetName:字符编码的名称
/
FileInputStream fis=new FileInputStream(“a.txt”);
InputStreamReader isr=new InputStreamReader(fis,“UTF-8”);
//读一个字符
/
System.out.println(isr.read());
System.out.println(isr.read());*/
//读一行
BufferedReader br=new BufferedReader(isr);
System.out.println(br.readLine());
br.close();
}
}

###案例2:
public class Demo01 {
/**
* 掌握:
* 1.当读取文件内容,还有写入文件,可以指定编码格式
* 2.使用InputStreamReader&OutputStream这个类
*
* 使用指定的编码方式写文件
/
public static void main(String[] args) throws Exception {
//创建writer
FileOutputStream fos=new FileOutputStream(“c.tct”);
OutputStreamWriter osw=new OutputStreamWriter(fos,“GBK”);
BufferedWriter bw=new BufferedWriter(osw);
//写
bw.write(“你好,IO,你真难写”);
bw.newLine();
bw.write(“你好,我不会”);
bw.newLine();
//关流
bw.close();
}
}
###练习:获取文本上字符出现的次数
public class Demo01 {
/
*
* 掌握:当键盘敲enter键,两个字符\r\n:回车换行
/
public static void main(String[] args) throws Exception {
//练习:获取文本上字符出现的次数,把数据写入文件
/

思路:
1.遍历文本每一个字符
2.字符出现的次数存在Map中
Mapmap=new HashMap();
map.put(‘a’,18);
map.put(‘你’,2);
3.把Map中的数据写入文件
/
//创建Map集合
Map map=new HashMap();
System.out.println(map.get(‘a’));
//2.遍历每一个字符,每一个字符穿线的次数放到map中
FileReader reader=new FileReader(“a.txt”);
int c=0;
while ((c=reader.read())!=-1){
//int还原char
char ch=(char)c;
//判断char是否在Map中第一次出现
if(map.get(ch)null){
map.put(ch,1);
}else {
map.put(ch,map.get(ch)+1);
}
}
//把map中数据存在文件count.txt
//创建writer
BufferedWriter bw=new BufferedWriter(new FileWriter(“count.txt”));
//遍历map,再写入数据
for (Map.Entry entry:map.entrySet()){
switch (entry.getKey()){
case ’ ':
bw.write(“空格=”+entry.getValue());
break;
case ‘\t’:
bw.write(“tab键=”+entry.getValue());
break;
case ‘\r’:
bw.write(“回车=”+entry.getValue());
break;
case ‘\n’:
bw.write(“换行=”+entry.getValue());
break;
default:
bw.write(entry.getKey()+"="+entry.getValue());
break;
}
bw.newLine();
}
//关流
reader.close();
bw.close();
}
}
#递归(5!)
递归作为一种算法,在程序设计语言中广泛应用
递归:就方法内部调用自己
递归的弊端:不能调用次数过多,容易导致栈溢出
递归的好处:不用直到循环的次数
构造方法是否可以递归调用
构造方法不能使用递归调用
递归调用是否必须有返回值?
不一定(可以有,也可以没有)
public class Demo01 {
public static void main(String[] args) {
/
*
* 递归作为一种算法
* 递归:就方法内部调用自己
*/
//使用递归来写阶乘
int r=jiecheng(116);
System.out.println(“r=”+r);
}
public static int jiecheng(int i){
if(i1){
return 1;
}else{
return i*jiecheng(i-1);
}
}
/**
* 使用for循环来写阶乘
/
public static void test1(){
int r=1;
for(int i=1;i<=5;i++){
r=r
i;
}
System.out.println(“r=”+r);
}
}

###递归:文件目录
public class Demo01 {
/**
* 计算一个文件夹大小:累加文件大小
/
public static void main(String[] args) {
//递归文件目录
/

打印出a目录所有文件名称,包括文件加的文件
*/
//创建目录对象
File dir=new File(“C:\Users\liguoliang\Desktop\eclipse-jee-oxygen-R-win32-x86_64”);
//打印目录的子目录
printSubFile(dir);
}
public static void printSubFile(File dir){
//打印目录的子文件
File[] subfiles=dir.listFiles();
for(File f:subfiles){
if(f.isDirectory()) {
printSubFile(f);
}else {
System.out.println(f.getAbsolutePath());
}
}
}
}
####从键盘输入接受一个文件加路径,打印出该文件夹下所有的.jpg文件名

public class Demo01 {
public static void main(String[] args) {
    //1.获取文件路径
    Scanner scanner=new Scanner(System.in);
    System.out.println("请输入一个文件夹路径");
    String path=scanner.nextLine();
    //2.把路径封装成File对象
    File file=new File(path);
    if(!file.exists()){
        System.out.println("此路径对应的文件不存在");
        return;
    }
    if(!file.isDirectory()){
        System.out.println("请输入文件夹路径,而不是文件路径");
        return;
    }
    //3.遍历文件夹下的子目录
    printSubFile(file);
}
public static  void printSubFile(File dir){
    //打印文件夹下的子文件
    File[] subfiles=dir.listFiles();
    for (File f:subfiles
         ) {
        if(f.isDirectory()){
            printSubFile(f);
        }else {
			if(f.getName().endsWith(".jpg"))
            System.out.println(f.getAbsolutePath());
        }
    }
}
}

##SequenceInputStream序列流
###什么是序列流?
序列流可以把多个字节输入流整合成一个,从序列流中读取数据时,将从被整合的第一个流开始读、
读完一个之后继续读第二个
####案例:使用字节流把两个文件数据写到另一个文件
public class Demo01 {
/**
* SequenceInputStream序列流
* InputStream输入流
* Sequence序列 连续
*
/
public static void main(String[] args) throws Exception {
test2();
}
public static void test2() throws Exception {
//创建序列流
FileInputStream fis1=new FileInputStream(“a.txt”);
FileInputStream fis2=new FileInputStream(“b.txt”);
SequenceInputStream sis=new SequenceInputStream(fis1,fis2);
//创建序列流
FileOutputStream fos=new FileOutputStream(“c.txt”);
//读写
int b=0;
while ((b=sis.read())!=-1){
fos.write(b);
}
fis2.close();
sis.close();
fos.close();
}
}
####序列流整合多个字节流
public class Demo01 {
public static void main(String[] args) throws Exception {
//Vector是集合
Vector vector=new Vector();
vector.add(new FileInputStream(“a.txt”));
vector.add(new FileInputStream(“b.txt”));
vector.add(new FileInputStream(“c.txt”));
//2.Enumeration枚举
Enumeration e=vector.elements();
//序列流
SequenceInputStream sis=new SequenceInputStream(e);
//4.创建输出流
FileOutputStream fos=new FileOutputStream(“d.txt”);
//读写
int b=0;
while ((b=sis.read())!=-1){
fos.write(b);
}
sis.close();
fos.close();
}
}
###ByteArrayOutputStream字节数组输出流
此类实现了一个输出流,其中的数据被写入一个byte数组,缓冲区会随着数据的不断写入
而自动增长,可以使用toByteArray()和toString()获取数据
public class Demo01 {
/
*
* ByteArrayOutStream不需要关联文件
* 此类实现了一个输出流,其中的数据被写入一个
* byte数组,缓冲区会随着数据的不断写入而自动增长
* 可使用toByteArray()和toString()获取数据
*/
public static void main(String[] args) throws Exception {
//1.创建字节数组输出流对象
ByteArrayOutputStream baos=new ByteArrayOutputStream();
//输入流
FileInputStream fis=new FileInputStream(“a.txt”);
//写入输出流
int b=0;
while((b=fis.read())!=-1){
baos.write(b);
}
System.out.println(baos.toString());
System.out.println(baos.toString(“UTF-8”));
//获取文件数据
byte[] bytes=baos.toByteArray();
System.out.println(new String(bytes));
System.out.println(new String(bytes,“UTF-8”));
//关流
fis.close();
}

}

#对象ObjectOutputStream&ObjectInputStream
###什么是对象操作流
该流可以将一个对象写出,或者读取一个对象到程序中,也就是执行了序列化和反序列化的操作
归档(序列化):将对象存在一个文件
解归档=反序列化:把一个文件解析出对象
ObjectOutputStream对象输出流,把一个对象存储起来,存储的对象必须实现serializable接口
ObjectInputStream对象输入流,把存的数据还原成一个对象
public class Demo01 {
/**
* 对象操作流ObjectOutputStream&ObjectInputStream
* ObjectOutputStream将一个对象写入文件
* 1.如果使用这个类写入对象,这个对象需要序列化
* 2.序列化就是让这个对象实现一个Serializable接口
* 3.如果没实现Serializable接口,会抛异常NotSerializableException
* 二、ObjectInputStream从文件中读一个对象
*
/
public static void main(String[] args) throws Exception {
//1.创建一个对象输入流
FileInputStream fis=new FileInputStream(“gf.data”);
ObjectInputStream ois=new ObjectInputStream(fis);
//读数据
GirlFriend gf1=(GirlFriend)ois.readObject();
System.out.println(gf1);
GirlFriend gf2=(GirlFriend)ois.readObject();
System.out.println(gf2);
/

如果没有数据可读,强制读的时候报错
*/
System.out.println(ois.readObject());
}
public static void test1() throws Exception {
//创建女友对象
GirlFriend gf1=new GirlFriend(“宋海英”,1.78);
GirlFriend gf2=new GirlFriend(“二蛋”,1.68);
//创建对象输出流
FileOutputStream fos=new FileOutputStream(“gf.data”);
ObjectOutputStream oos=new ObjectOutputStream(fos);
//3.往文件存入对象
oos.writeObject(gf1);
oos.writeObject(gf2);
//关流
oos.close();
}

}

class GirlFriend implements Serializable{
String name;
double height;
public GirlFriend(String name,double height){
    super();
    this.name=name;
    this.height=height;
}

@Override
public String toString() {
    return "GirlFriend [name="+name+",height="+height+"]";
}
}

###对象操作流优化
为了方便读取多个对象
建立把对象存储在集合中,然后将集合对象存入取出
public class Demo01 {
public static void main(String[] args) throws IOException {
//对象操作流优化思路,存多个对象时,把对象存在list里面
//把女朋友对象存在List中,再把List写入文件【序列化/归档】
//1.创建集合
List list = new ArrayList();
//2.添加女朋友
list.add(new GirlFriend(“宋海英”, 1.78));
list.add(new GirlFriend(“二蛋”, 1.68));
list.add(new GirlFriend(“狗蛋”, 1.58));
//3.把list存入文件
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“list.data”));
oos.writeObject(list);
//关流
oos.close();
}
}
class GirlFriend implements Serializable {
String name;
double height;

public GirlFriend(String name, double height) {
    super();
    this.name = name;
    this.height = height;
}

@Override
public String toString() {
    return "GirlFriend [name=" + name + ", height=" + height + "]";
}
}

public class Demo01 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
  //创建对象输入流
   ObjectInputStream ois=new ObjectInputStream(new FileInputStream("list.data"));
   //读取list对象
    Object obj=ois.readObject();
    //把obj转list
    @SuppressWarnings("unchecked")
    List list=(List)obj;
    System.out.println(obj.getClass());
    //遍历
    for (GirlFriend gf :list){
        System.out.println(gf);
    }
    ois.close();
}
}
class GirlFriend implements  Serializable {
String name;
double height;

public GirlFriend(String name, double height) {
    super();
    this.name = name;
    this.height = height;
}

@Override
public String toString() {
    return "GirlFriend [name=" + name + ", height=" + height + "]";
}
}

##Serializable接口的ID
归档或者序列化的对象必须实现Serializable接口才内被序列化
serializable中有个id,但是ID不是一定有加的
SerialVersionUid,简而言之,其目的是序列化对象版本控制,有关各个版本反序列化是否
兼容。如果修改较小,比如仅仅增加了一个属性,我们希望向下兼容,老版本的数据都能保留
那就不用修改
如果我们删除了一个属性,或者更改了类的继承关系,必然不兼容旧数据,这就应该手动更新版本号
即SerialVersionUid
public class Demo01 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
/* Serializable接口的ID
1.要归档或者序列化的对象必须实现Serializable接口才能被序列化
2.Serializable 中有个id,但ID不是一定要加的
3.SerialVersionUid,简言之,其目的是以序列化对象进行版本控制,有关各版本
反序列化时是否兼容。
4.如果在新版本中这个值修改了,新版本就不兼容旧版本,反序列化时会抛出InvalidClassException异常。
5.如果修改较小,比如仅仅是增加了一个属性,我们希望向下兼容,老版本
的数据都能保留,那就不用修改;
6.如果我们删除了一个属性,或者更改了类的继承关系,必然不兼容旧数据,
这时就应该手动更新版本号,即SerialVersionUid。
7.一般不会添加ID,就算添加了ID,版本号最好不要修改
*/
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(“stu.data”));
Student stu=(Student)ois.readObject();
System.out.println(stu);

}
public static void save() throws IOException {
    //创建学生对象
    Student stu=new Student("宋海英");
    //2.把学生存入文件
    ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("stu.data"));
    /**
     * 存的学生的版本号是1
     */
    oos.writeObject(stu);
    //关流
    oos.close();
}
}
class Student implements Serializable{
/**
 * 序列化版本ID
 */
private static final long serialVersionUID=1L;
private String name;
private String hometown;
public Student(String name){
    super();
    this.name=name;
}
public String toString(){
    return "Student [name="+name+"]";
}

##打印流的概述和特点
什么是打印流?
该流可以很方便的将对象的toString()结果输出,并且自动加上换行,而且可以使用自动刷出
的模式System.out就是一个PrintStream,其默认向控制台输出信息
PrintStream和PrintWriter分别是打印的字节流和字符流
public class Demo01 {
//打印流的概述和特点
/*
什么是打印流
什么是打印流?
该流可以很方便的将对象的toString()结果输出,并且自动加上换行,而且可以使用自动刷出
的模式System.out就是一个PrintStream,其默认向控制台输出信息
PrintStream和PrintWriter分别是打印的字节流和字符流
/
//1.打印的字节流【打印到控制台】
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps=System.out;
ps.println(“你好,元宵节”);
ps.println(19.6);
//打印字符流
/
*
* 1.printWrite调用打印方法,控制台是内有内容,它是把内容写到文件中
* 如果打印了内容,没有调用flush或者close,内容在文件中也不存在
/
PrintWriter pw=new PrintWriter(“test.txt”);
pw.println(“吃汤圆了”);
pw.print(“超市一包汤圆10几块钱”);
pw.print(13.01);
pw.flush();
pw.close();
}
}
##标准输入输出流概述和输出语句
System.in和InputStream,标准输入流,默认可以从键盘
读取字节数据
System.out是PrintStream,标准输出流,默认可以向Console中输出字符和字节数据
public class Demo01 {
public static void main(String[] args) {
InputStream is=System.in;//标准输入流
PrintStream ps=System.out;//标准输出流
}
}
##随机访问流概述和读写数据
随机访问流概述
RandomAccessFile概述
RandomAccessFile类不属于流,是Object类的子类,但
它融合了InputStream和OutputStream的功能
支持对随机访问文件按的读取和写入
public class Demo01 {
public static void main(String[] args) throws IOException {
//随机访问流概述
/
*
* 构造方法两个参数
* name:文件名称,路径
* mode:模式,r=read只读,w=write
/
//创建一个随机访问流对象,以读写的方式打开文件
RandomAccessFile raf=new RandomAccessFile(“a.txt”,“rw”);
//2.读字符
/
*
* 使用RandomAccessFile的readchar/readLine方法读文件有乱码问题
*
/
/
System.out.println(raf.readChar());
System.out.println(raf.readChar());
System.out.println(raf.readChar());
System.out.println(raf.readLine());*/
//使用字节数组来读比较好
byte[] buf=new byte[1024];
int len;
while((len=raf.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
//写数据
raf.writeChars(“abc”);
raf.writeChars(“abc”);
raf.seek(4);//指定位置
raf.write(97);
raf.write(98);
raf.write(99);
}
}
#DataOutputStream&DataInputStream
##什么是数据输入输出流
DataInputStream,DataOutputStream可以按照基本数据
类型大小读写数据
例如:
按long大小写出一个数字,写出时该数据占8字节,读取的
时候也可以按照Long类型读取,一次读取8个字节
public class Demo01 {
//DataOutputStream&DataInputStream数据输入输出流
public static void main(String[] args) throws Exception {
//读3个long数据
DataInputStream dis=new DataInputStream(new FileInputStream(“a.txt”));
System.out.println(dis.readLong());//读8个字节
System.out.println(dis.readLong());//读8个字节
System.out.println(dis.readLong());//读8个字节
}
public static void test1() throws IOException {
long a=997;
long b=998;
long c=999;
//使用FileOutputStream没法写入long类型数据
FileOutputStream fos=new FileOutputStream(“a.txt”);
fos.write(997);
fos.write(998);
fos.write(999);
DataOutputStream dos=new DataOutputStream(fos);
dos.writeLong(a);
dos.writeLong(b);
dos.writeLong©;
dos.close();
}
}
#Properties的概述
Properties的概述
Properties可保存在流中或从流中加载
Properties类表示了一个持久的属性集
属性列表中每个键及其对应值都是一个字符串
###方法
Properties的load()和store()
public Object setProperty(String key,String value)
public String getProperty(String key)
public Enumeration stringPropertyNames()

public class Demo01 {
public static void main(String[] args) throws Exception {
    //1.创建属性对象
    Properties p=new Properties();
    //2.关联文件
    p.load(new FileInputStream("Info.properties"));
    //遍历一
    Set keys=p.keySet();
    for (Object key:keys){
        System.out.println(key+"="+p.get(key));
    }
    //System.out.println(keys);
    //4.遍历二
    System.out.println("===================");
    //p.entrySet();
    for (Map.Entry entry:p.entrySet()
         ) {
        System.out.println(entry.getKey()+"="+entry.getValue());
    }
}
public static void test2() throws Exception {
    //使用Properties读取数据
    //创建属性对象
    Properties p=new Properties();
    //2.关联文件
    p.load(new FileInputStream("info.properties"));
    //通过key读取数据
    String name=p.getProperty("name");
    String city=p.getProperty("city");
    String hometown=p.getProperty("hometown");
    System.out.println(name);
    System.out.println(city);
    System.out.println(hometown);
}
/**
 * 使用Properties来存储数据
 */
public static void test1() throws IOException {
    //创建属性对象
    Properties p=new Properties();
    //存数据
    p.setProperty("name","gyf");
    p.setProperty("city","广州");
    p.setProperty("hometown","梅州");
    //3.关联文件
    /**
     * 当properties把key和value存入文件,把中文转成unicode编码
     * 
     */
    p.store(new FileOutputStream("info.properties"),null);
}

}
 
  

#总结
##一、IO流-输入输出流
I:input
O:out
IO流 操作文件,读取文件内容,往文件写内容
##字节流

InputStream

  • -FileInputStream 文件输入流,读的单位是字节
  • -BufferedInputStream 缓冲输入流,内部有个byte[]字节数组
  • -SequenceInputStream 序列流,把多个字节流整合成一个流
  • -ObjectInputStream 对象输入流,直接从文件中读取一个对象,这个对象要实现serilazable接口
  • -Sytem.in 标准输入流-指键盘
  • -DataInputStream 数据输入流,按基本数据类型的大小(long)
    ###>InputStream
    -FileOutputStream 文件输出流,写的单位是字节 * -BufferedOutputStream 缓冲输出流,内部有个byte[]字节数组
    -ByteArrayOutputStream 字节数组输出流,把数据读取到内存中,这个类不需要关联文件
    -ObjectOutputStream 对象输出流,直接把一个对象存入文件,
    -PrintStream 打印流,把内容打印到控制台
    -System.out 标准输出流-指控制台
    -DataOutputStream 数据输出流,按基本数据类型的大小(long) 写入文件
    三、字符流
    #Reader
 -FileReader 文件读取流,读取的单位是字符 
-BufferedReader 缓冲读取流,内部有个char[] 字符数组 
 -InputStreamReader 指定字符编码读取文件

#Writer
-FileWriter 文件写入流,写入的单位是字符
-BufferedWriter,缓冲写入流,内部有个char[] 字符数组
-OutputStreamWriter 指定字符编码写入文件
-PrintWriter 打印流,把内容打印一个文件

RandomAccessFile 随机访问流,特点:读和写都在一个类中


Properties 相当于Map一样使用,这个类把数据存在一个后缀名为.properties文件

你可能感兴趣的:(java中File详解)