一、File类的使用
1、File类简介
1.1、File类的作用
- File类是Java提供的针对磁盘中的文件或目录转换对象的包装类。一个File对象可以代表一个文件或目录,File对象可以实现获取文件和目录属性等功能,可以实现对文件和目录的创建、删除等功能!
1.2、File类操作目录与文件的常用方法
1.2.1、针对文件操作方法
方法 | 作用 |
---|---|
createNewFile() | 创建新文件。 |
delete() | 直接从磁盘上删除。 |
exists() | 查询磁盘中的文件是否存在。 |
getAbsolutePath() | 获取绝对路径。 |
getPath() | 获取相对路径。 |
getName() | 获取文件名,相当于调用了一个toString方法。 |
isFile() | 判断是否为文件。 |
length() | 查看文件中的字节数。 |
isHidden() | 测试文件是否被这个抽象路径名是一个隐藏文件 |
- 使用代码演示:
package com.IOStream.FileClass;
import java.io.File;
//针对文件操作方法
public class FileDemo01 {
public static void main(String[] args) throws Exception{ //主动抛出异常
//创建File对象
File file = new File("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\aa.txt");
//1、使用CreateNewFile方法创建新文件
System.out.println("1、使用CreateNewFile方法创建新文件:"+file.createNewFile());
//2、使用delete方法删除文件
//System.out.println("2、使用delete方法删除文件:"+file.delete());
//3、使用exists方法查询磁盘中是否存在该文件
System.out.println("3、使用exists方法查询磁盘中是否存在该文件:"+file.exists());
//4、使用getAbsolutePath方法获取绝对路径
System.out.println("4、使用getAbsolutePath方法获取绝对路径:"+file.getAbsolutePath());
//5、使用getPath方法获取相对路径
System.out.println("5、使用getPath方法获取相对路径:"+file.getPath());
//6、使用getName方法获取文件名,相当于调用了一个toString方法
System.out.println("6、使用getName方法获取文件名:"+file.getName());
//7、使用isFile方法判断是否为文件
System.out.println("7、使用isFile方法判断是否为文件:"+file.isFile());
//8、使用isHidden方法测试文件是否为一个隐藏文件
System.out.println("8、使用isHidden方法测试文件是否为一个隐藏文件:"+file.isHidden());
//9、使用length方法查看文件中的字节数
System.out.println("9、使用length方法查看文件中的字节数:"+file.length());
}
}
- 结果图
总结:需要注意的是在创建File对象时,需要给对象一个实际的文件路径包括文件名,这个文件名在使用CreateNewFile方法后才会存在,否则不会出现在目录中,后面的操作将会返回false
1.2.2、针对目录操作的方法
方法 | 作用 |
---|---|
exists () | 查询目录是否存在。 |
isDirectory() | 判断当前路径是否为目录。 |
mkdir() | 创建目录。 |
getParentFile() | 获取当前目录的父级目录 。 |
list() | 返回一个字符串数组,包含目录中的文件和目录的路径名。 |
listFiles() | 返回一个File数组,表示用此抽象路径名表示的目录中的文件。 |
- 使用代码演示
package com.IOStream.FileClass;
import java.io.File;
//针对目录操作的方法
public class FileDirectoryDemo02 {
public static void main(String[] args) {
//创建File对象
File file2 = new File("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\a");
//1、mkdir()创建目录。
System.out.println("1、mkdir()创建目录:"+file2.mkdir());
//2、isDirectory()判断当前路径是否为目录。
System.out.println("2、isDirectory()判断当前路径是否为目录:"+file2.isDirectory());
//3、exists()查询目录是否存在。
System.out.println("3、exists()查询目录是否存在:"+file2.exists());
//4、getParentFile()获取当前目录的父级目录 。
System.out.println("4、getParentFile()获取当前目录的父级目录 :"+file2.getParentFile());
//5、list()返回一个字符串数组,包含目录中的文件和目录的路径名。
//重新创建一个目录,方便调用list方法。
File file = new File("D:\\IDEA\\JavaSE\\基础语法\\src\\com");
//创建一个String类型的数组,将file指定的目录内的文件名赋值给arr数组!
String[] arr = file.list();
for (String tmpe:arr //这里是遍历这个数组
) {
System.out.println(tmpe); //打印数组
}
//6、listFiles返回一个File数组,表示用此抽象路径名表示的目录中的文件。
//创建一个File类型的数组,用来接收file指定目录内的文件名以及抽象路径名!
File[] arr2 = file.listFiles();
for (File temp2:arr2) //使用增强for遍历arr2这个数组
{
System.out.println(temp2);
}
}
}
- 结果图
总结:在使用File类对目录进行操作时,需要注意的是List以及ListFiles的区别,List返回字符串数组,然后该数组返回的是当前指定目录下的所有文件,而ListFiles方法List数组,返回的是当前指定目录的所有文件名以及文件路径。
二、常用流对象
1、文件字节流
1.1、文件字节输入流
- FileInputStream通过字节的方式读取文件,适合读取所有类型的文件(图像、视频、文本文件等)。java也提供了FileReader专门读取文本文件!
package com.IOStream.FileInputStream;
//测试字节文件,读取gif视频文件
import java.io.FileInputStream;
public class FileInputStreamOne {
public static void main(String[] args) {
//引用FileInputStream类
FileInputStream fis = null;
try{
//创建文件字节输入流对象
fis = new FileInputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\kedaya.gif");
int temp = 0; //创建存放数据的int类型变量
long strat = System.currentTimeMillis(); //获取开始执行的时间
while ((temp=fis.read())!=-1){ //read为读取一个字节,然后返回给temp。直到等于-1,也就是读取完毕!
System.out.println(temp);
}
long end = System.currentTimeMillis(); //获取执行完毕的时间
System.out.println("总共耗时(毫秒):"+(end-strat));
}catch(Exception e){
e.printStackTrace();
}finally{
try {
if (fis!=null){
fis.close(); //关闭流
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 结果图:
1.2、文件字节输出流
- FileOutputStream通过字节的方式写数据到文件中,适合所有类型的文件。java也提供了FileWriter专门写入文本文件!
package com.IOStream.FileInputStream;
//测试字节文件,读取gif视频文件
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class FileInputStreamOne {
public static void main(String[] args) {
//引用FileInputStream类
FileInputStream fis = null;
FileOutputStream fos = null;
try{
//创建文件字节输入流对象
fis = new FileInputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\kedaya.gif");
//创建文件字节输出流对象
fos = new FileOutputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\可达鸭莫林辉大傻逼.gif");
int temp = 0;//创建存放数据的int类型变量
long strat = System.currentTimeMillis(); //获取开始执行的时间
while ((temp=fis.read())!=-1){ //read为读取一个字节,然后返回给temp。直到等于-1,也就是读取完毕!
fos.write(temp); //读取到的数据写出到目录文件中。
}
fos.flush(); //将数据从内存中写入到磁盘
long end = System.currentTimeMillis(); //获取执行完毕的时间
System.out.println("总共耗时(毫秒):"+(end-strat));
}catch(Exception e){
e.printStackTrace();
}finally{
try {
if (fis!=null){
fis.close(); //关闭流
}
if (fos!=null){
fos.close(); //关闭流
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
综上,可以看到gif文件已经被写出到指定的文件夹中了,而输出的时候需要注意的是,在输出时,需要使用flush方法将数据从内存写入到磁盘中!总耗时大概是3秒左右!
1.3 通过缓冲区提高读写效率
1.3.1 方式一
- 通过创建一个指定长度的字节数组作为缓冲区,以此来提高IO流的读写效率。该方式适用于读取较大图片时的缓冲区定义,注意:缓冲区的长度一定是2的整数幂。一般情况下1024长度较为合适。
package com.IOStream.FileInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
//测试字节文件,读取并写入gif文件,使用包装类的方法。
public class FileInputStreamtow {
public static void main(String[] args) {
//引用FileInputStream类
FileInputStream fis = null;
FileOutputStream fos = null;
try{
//创建文件字节输入流对象
fis = new FileInputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\kedaya.gif");
//创建文件字节输出流对象
fos = new FileOutputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\包装后的可达鸭莫林辉大傻逼.gif");
//创建一个缓冲区,提高读写效率!
byte[] buff = new byte[1024];
int temp = 0;
long strat = System.currentTimeMillis(); //获取开始执行的时间
// while ((temp=fis.read(buff))!=-1){
// fos.write(buff,0,temp); //读取到的数据写出到目录文件中。
// }
for (int i = 0; i != -1; i++) {
temp = fis.read(buff); //将数据读取到buff数组中!
if (temp==-1){ //如果temp等于-1,则停止循环!
break;
}
fos.write(buff,0,temp); //将数据从buff数组中,0号下标开始,长度为temp的长度!
}
fos.flush(); //将数据从内存中写入到磁盘
long end = System.currentTimeMillis(); //获取执行完毕的时间
System.out.println("总共耗时(毫秒):"+(end-strat));
}catch(Exception e){
e.printStackTrace();
}finally{
try {
if (fis!=null){
fis.close();
}
if (fos!=null){
fos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
总结: 可以看出来,当使用了缓冲区数组来进行读取之后,效率比之前快了很多!用时5毫秒左右!
1.3.2 方式二
- 通过创建一个字节数组作为缓冲区,数组长度是通过输入流对象的available()返回当前文件的预估长度来定义的。在读写文件时,是在一次读写操作中完成文件读写操作的。注意:如果文件过大,那么对内存的占用也是比较大的。所以大文件不建议使用该方法。
package com.IOStream.FileInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
//测试字节文件,读取并写入gif文件,使用自定义包装流的方法。
public class FileInputStreamthere {
public static void main(String[] args) {
//引用FileInputStream类
FileInputStream fis = null;
FileOutputStream fos = null;
try{
//创建文件字节输入流对象
fis = new FileInputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\kedaya.gif");
//创建文件字节输出流对象
fos = new FileOutputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\包装流2后的可达鸭莫林辉大傻逼.gif");
//创建一个缓冲区,提高读写效率!
byte[] buff = new byte[fis.available()]; //定义长度为预估长度!
int temp = 0;
long strat = System.currentTimeMillis(); //获取开始执行的时间
// while ((temp=fis.read(buff))!=-1){
// fos.write(buff,0,temp); //读取到的数据写出到目录文件中。
// }
for (int i = 0; i != -1; i++) {
temp = fis.read(buff); //将数据读取到buff数组中!
if (temp==-1){ //如果temp等于-1,则停止循环!
break;
}
fos.write(buff,0,temp); //将数据从buff数组中,0号下标开始,长度为temp的长度!
}
fos.flush(); //将数据从内存中写入到磁盘
long end = System.currentTimeMillis(); //获取执行完毕的时间
System.out.println("总共耗时(毫秒):"+(end-strat));
}catch(Exception e){
e.printStackTrace();
}finally{
try {
if (fis!=null){
fis.close();
}
if (fos!=null){
fos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
总结:综上,可以看到,在定义byte数组时,定义的长度为fis.available的长度,效率会更佳,因为这个是字节的预估长度,一次性执行完成,不需要太多的循环!
1.4 通过字节缓冲流提高读写效率
- 缓冲流本身不具有读取与写入功能,只是在别的流(节点流或其他处理流)中加上缓冲功能提高效率。就像是把别的流包装起来一样,因此缓冲流是一种处理流(包装流)。
- 当文件或其他数据源进行频繁的读写操作时,效率较低,这时如果使用缓冲流就能够高效的读写信息。因为缓冲流是先将数据缓存起来,然后当缓存区存满后或者手动刷新时,一次性读取到程序或写入目的地。
- BufferedInputStream和BufferedOutputStream这两个是缓冲字节流,通过内部缓存数组来提高操作流的效率。
package com.IOStream.FileInputStream;
//使用缓冲流来优化其他流
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class BufferedInputStreamDemo01 {
public static void main(String[] args) {
FileInputStream fis = null; //引用输入流
BufferedInputStream buis = null; //引用输入流的缓冲流
FileOutputStream fos = null; //引用输出流
BufferedOutputStream buos = null; //引用输出流的缓冲流
try{
//创建输入流对象
fis = new FileInputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\kedaya.gif");
//创建输入流缓冲流对象
buis = new BufferedInputStream(fis);
//创建输出流对象
fos = new FileOutputStream("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\使用buff输出流后的可达鸭莫林辉大傻逼.gif");
//创建输出流缓冲流对象
buos = new BufferedOutputStream(fos);
//缓冲流中的byte数组长度默认是8192!
int temp = 0; //创建一个变量来存放字节
long strat = System.currentTimeMillis(); //开始时间
while((temp = buis.read())!=-1){ //将读取出来的字节一个一个传递给temp
buos.write(temp); //将temp内的字节写出到目的地
}
buos.flush(); //将数据从内存中写入磁盘。
long end = System.currentTimeMillis(); //结束时间
System.out.println("总共耗时(毫秒):"+(end-strat));
}catch (Exception e){
e.printStackTrace();
}finally{
try {
if (buis !=null){
buis.close();
}
if (fis !=null){
fis.close();
}
if (buos!=null){
buos.close();
}
if (fos!=null){
fos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
总结:可以看出,花费的总时长是27毫秒,因为输入流跟输出流都使用了缓冲流,而缓冲流中使用的也是byte数组,而这个数组的默认长度是8192,也同样是2的正幂次方。
1.5 定义文件拷贝工具类
package com.IOStream.FileInputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
//拷贝路径
public class FileCopyTools {
public static void main(String[] args) {
copy("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\kedaya.gif","D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\copy后的可达鸭.gif");
}
public static void copy(String str,String des){
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try{
bis = new BufferedInputStream(new FileInputStream(str));
bos = new BufferedOutputStream(new FileOutputStream(des));
int temp = 0;
while ((temp = bis.read())!=-1){ //这里是将数据读取到temp中
bos.write(temp); //将temp数据写入到内存中
}
bos.flush(); //将数据从内存读取到磁盘中
}catch(Exception e){
e.printStackTrace();
}finally{
try {
if (bis !=null){
bis.close();
}
if (fis !=null){
fis.close();
}
if (bos!=null){
bos.close();
}
if (fos!=null){
fos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
综上,使用以上的方法便可以直接调用这个文件copy,只需要输入原路径以及目标路径即可!
2、文件字符流
- 前面介绍的文件字节流可以处理所有的文件,如果我们处理的是文本文件,也可以使用文件字符流,他以字符为单位进行操作!
2.1、文件字符输入流
package com.IOStream.FileReader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
//字符输入流
public class FileReaderDemo01 {
public static void main(String[] args) {
//创建字符输出流
FileReader fr = null;
//创建字符包装流
BufferedReader fr2 = null;
try{
fr = new FileReader("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\测试输入.txt");
fr2 = new BufferedReader(fr); //实例化包装流对象
int temp = 0;
while((temp = fr2.read())!=-1){
System.out.println((char)temp); //输出在控制台中
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if (fr!=null){
fr.close();
}
if (fr2!=null){
fr2.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
结果图:
2.1、文件字符输入流
package com.IOStream.FileWriter;
import java.io.FileWriter;
//文件字符输出流
public class FileWriterDemo01 {
public static void main(String[] args) {
//创建字符输出流
FileWriter fw = null;
FileWriter fw2 = null;
try{
fw = new FileWriter("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\测试输入.txt");
fw.write("我是你爹爹呀!");
fw.write("你好呀!");
fw.flush(); //将数据从内存读取到磁盘中,大致意思就是清空缓冲区。
fw2 = new FileWriter("D:\\IDEA\\JavaSE\\基础语法\\src\\com\\IOStream\\测试输入.txt",true);
fw2.write("何以解忧\r\n唯有哈哈哈哈");
fw2.flush();//将数据从内存读取到磁盘中,大致意思就是清空缓冲区。
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if (fw!=null){
fw.close();
}
if (fw2!=null){
fw2.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
3、字符缓冲流
- BufferedReader/BufferedWriter增加了缓存机制,大大提高了读写文本的效率!
3.1、字符输入缓冲流
- BufferedReader 是针对字符输入流的缓冲流对象,提供了更方便的按行读取的方法:
readLine(); 在使用字符流读取文本文件时,我们可以使用该方法以行为单位进行读取。
package com.copyFile;
import java.io.BufferedReader;
import java.io.FileReader;
public class BufferedReaderDemo {
public static void main(String[] args) {
FileReader fr = null;
BufferedReader br = null;
try{
fr = new FileReader("F:/IO测试/lxt.txt");
br = new BufferedReader(fr);
String temp = "";
while((temp = br.readLine()) != null){
System.out.println(temp);
}
}catch(Exception e){
e.printStackTrace();
}finally {
try{
if(br != null){
br.close();
}
if(fr != null){
fr.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
3.2 字符输出缓冲流
- BufferedWriter 是针对字符输出流的缓冲流对象,在字符输出缓冲流中可以使用
- newLine();方法实现换行处理。
package com.copyFile;
import java.io.BufferedWriter;
import java.io.FileWriter;
public class BufferedWriterDemo {
public static void main(String[] args) {
FileWriter fw = null;
BufferedWriter bw = null;
try{
fw = new FileWriter("F:/IO测试/lxt.txt");
bw = new BufferedWriter(fw);
bw.write("你好呀小明");
bw.write("你好Oldlu");
bw.newLine();
bw.write("何以解忧");
bw.newLine();
bw.write("唯有哈哈哈");
bw.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(bw != null){
bw.close();
}
if(fw != null){
fw.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
3.3、通过字符缓冲流实现文本文件的拷贝
package com.copyFile;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class FileCopyTools3 {
public static void main(String[] args) {
copyFile("F:/IO测试/lxt.txt","F:/IO测试/lxtReadercopy.txt");
}
/**
* 基于字符流缓冲流实现文件拷贝
*/
public static void copyFile(String src,String des){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new FileReader(src));
bw = new BufferedWriter(new FileWriter(des));
String temp = "";
while((temp = br.readLine()) != null){
bw.write(temp); //将temp得到的字符写出到目的地中
bw.newLine(); //换行操作
}
bw.flush();
}catch(Exception e){
e.printStackTrace();
}finally {
try{
if(br != null){
br.close();
}
if(bw != null){
bw.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
3.4、通过字符缓冲流为文件中的内容添加行号
package com.copyFile;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class LineNumberDemo {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new FileReader("F:/IO测试/lxt.txt"));
bw = new BufferedWriter(new FileWriter("F:/IO测试/带行号的lxt.txt"));
String temp = "";
int i = 1;
while((temp = br.readLine()) != null){ //readLine 读取一整行内容
bw.write(i+","+temp);
bw.newLine();
i++;
}
bw.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(br != null){
br.close();
}
if(bw != null){
bw.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
总结 :本小结需要注意的就是添加行号,在内容写出的时候,需要在输出内容的前面加上一个变量i,初始值为1,循环下去!还有readLine方法是读取整行的内容!
4、转换流
- InputStreamReader/OutputStreamWriter用来实现将字节流转化成字符流。比如,如下场景:
System.in 是字节流对象,代表键盘的输入,如果我们想按行接收用户的输入时,就必须用到缓冲字符流 BufferedReader 特有的方法 readLine(),但是经过观察会发现在创建BufferedReader 的构造方法的参数必须是一个 Reader 对象,这时候我们的转换流InputStreamReader 就派上用场了。而System.out也是字节流对象,代表输出到显示器,按行读取用户的输入后,并且要将读取的一行字符串直接显示到控制台,就需要用到字符流的write(Stringstr)方法,所以我们要使用OutputStreamWriter 将字节流转化为字符流。
4.1、通过转换流实现键盘输入屏幕输出
package com.copyFile;
import jdk.internal.util.xml.impl.Input;
import java.io.*;
public class ConvertStream {
public static void main(String[] args) {
//引用字符包装流(读取)
BufferedReader br = null;
//引用字符包装流(写出)
BufferedWriter bw = null;
try{
//实例化字符处理流 其中再实例化一个字节转换字符流对象 值为用户输入的值
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
while(true){
bw.write("请输入:");
bw.flush();
String input = br.readLine();
if("exit".equals(input)){
break;
}
bw.write("你输入的是:"+input);
bw.newLine();
bw.flush();
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(bw != null){
bw.close();
}
if(br != null){
br.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
结果图:
4.2、通过字节流读取文本文件并添加行号
package com.copyFile;
import java.io.*;
public class LineNumberDemo2 {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new InputStreamReader(new FileInputStream("F:/IO测试/lxt.txt")));
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("F:/IO测试/通过字节流读取文本文件并添加行号 lxt.txt")));
String temp = "";
int i = 1;
while((temp = br.readLine()) != null){
bw.write(i+","+temp);
bw.newLine();
i++;
}
bw.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(br != null){
br.close();
}
if(bw != null ){
bw.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
5、字符输出流
- 在 Java的 IO 流中专门提供了用于字符输出的流对象PrintWriter。该对象具有自动行刷新缓冲字符输出流,特点是可以按行写出字符串,并且可通过println();方法实现自动换行。
package com.copyFile;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class LineNumberDemo3 {
public static void main(String[] args) {
BufferedReader br = null;
PrintWriter pw = null;
try{
br = new BufferedReader(new InputStreamReader(new FileInputStream("F:/IO测试/lxt.txt")));
pw = new PrintWriter("F:/IO测试/字符输出的流对象PrintWriter-lxt.txt");
String temp ="";
int i = 1;
while((temp = br.readLine()) != null){
pw.println(i+","+temp);
i++;
}
}catch(Exception e){
e.printStackTrace();
}finally {
try{
if(br != null){
br.close();
}
if(pw != null){
pw.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
6、字节数组流
- ByteArrayInputStream 和 ByteArrayOutputStream 经常用在需要流和数组之间转化的情况
6.1、字节数组输入流
- 说白了,FileInputStream 是把文件当做数据源。ByteArrayInputStream 则是把内存中的字节数组对象”当做数据源
package com.copyFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class ByteArrayInputDemo {
public static void main(String[] args) {
byte[] arr = "abcdefg".getBytes();
ByteArrayInputStream bis = null;
StringBuilder sb = new StringBuilder();
try{
//该构造方法的参数是一个字节数组,这个字节数组就是数据源
bis = new ByteArrayInputStream(arr);
int temp = 0;
while ((temp = bis.read()) != -1){
sb.append((char)temp);
}
System.out.println(sb.toString());
}finally{
try{
bis.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
结果图
6.2、字节数组输出流
- ByteArrayOutputStream 流对象是将流中的数据写入到字节数组中。
package com.copyFile;
import java.io.ByteArrayOutputStream;
public class ByteArrayOutputDemo {
public static void main(String[] args) {
ByteArrayOutputStream bos = null;
try{
StringBuilder sb = new StringBuilder();
bos = new ByteArrayOutputStream();
bos.write('a');
bos.write('b');
bos.write('c');
byte[] arr = bos.toByteArray();
for(int i=0;i<arr.length;i++){
sb.append((char)arr[i]);
}
System.out.println(sb.toString());
}finally {
try{
if(bos != null){
bos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
结果图
7、数据流
- 数据流将“基本数据类型与字符串类型”作为数据源,从而允许程序以与机器无关的方式从底层输入输出流中操作Java基本数据类型与字符串类型。
- DataInputStream 和DataOutputStream 提供了可以存取与机器无关的所有Java基础类型数据(如:int、double、String 等)的方法
7.1、数据输出流
package com.copyFile;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
public class DataOutputDemo {
public static void main(String[] args) {
DataOutputStream dos = null;
try{
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("F:/IO测试/lxt.txt")));
dos.writeChar('a');
dos.writeInt(10);
dos.writeDouble(Math.random());
dos.writeBoolean(true);
dos.writeUTF("你好baby");
dos.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(dos != null){
dos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
7.2、数据输入流
package com.copyFile;
import java.io.BufferedInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.FileInputStream;
public class DataInputDemo {
public static void main(String[] args) {
DataInputStream dis = null;
try{
dis = new DataInputStream(new BufferedInputStream(new FileInputStream("F:/IO测试/lxt.txt")));
//直接读取数据,注意:读取的顺序要与写入的顺序一致,否则不能正确读取数据。
System.out.println("char: "+dis.readChar());
System.out.println("int: "+dis.readInt());
System.out.println("double: "+dis.readDouble());
System.out.println("boolean: "+dis.readBoolean());
System.out.println("String: "+dis.readUTF());
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(dis != null ){
dis.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
小结:直接读取数据,注意:读取的顺序要与写入的顺序一致,否则不能正确读取数据
8、对象流
- 对象的本质是用来组织和存储数据的,对象本身也是数据。那么,能不能将对象存储到硬盘上的文件中呢?能不能将对象通过网络传输到另一个电脑呢?我们可以通过序列化和反序列化来实现这些需求
8.1、java对象的序列化和反序列化
8.1.1、序列化和反序列化是什么
- 当两个进程远程通信时,彼此可以发送各种类型的数据。 无论是何种类型的数据,都会以二进制序列的形式在网络上传送。比如,我们可以通过 http 协议发送字符串信息;我们也可以在网络上直接发送Java 对象。发送方需要把这个Java 对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为 Java对象才能正常读取。
- 把 Java对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为 Java对象的过程称为对象的反序列化。
- 对象序列化的作用有如下两种:
- 持久化: 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中。
- 网络通信:在网络上传送对象的字节序列。比如:服务器之间的数据通信、对象传
递。
8.1.2、序列化设计的类和接口
- ObjectOutputStream 代表对象输出流,它的writeObject(Objectobj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
- ObjectInputStream 代表对象输入流,它的 readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
- 只有实现了Serializable 接口的类的对象才能被序列化。Serializable 接口是一个空接口,只起到标记作用。
8.2、操作基本数据类型
- 我们前边学到的数据流只能实现对基本数据类型和字符串类型的读写,并不能对 Java对象进行读写操作(字符串除外),但是在对象流中除了能实现对基本数据类型进行读写操作以外,还可以对 Java对象进行读写操作。
8.2.1、写出基本数据类型数据
package com.copyFile;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamBasicTypeDemo {
public static void main(String[] args) {
ObjectOutputStream oos = null;
try{
oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("F:/IO测试/写出基本数据类型数据lxt.txt")));
oos.writeInt(10);
oos.writeDouble(Math.random());
oos.writeChar('a');
oos.writeBoolean(true);
oos.writeUTF("你好Oldlu");
oos.flush();
}catch(Exception e){
e.printStackTrace();
}finally {
try{
if(oos != null){
oos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
结果图
8.2.2、读取基本数据类型数据
package com.copyFile;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class ObjectInputStreamBasicTypeDemo {
public static void main(String[] args) {
ObjectInputStream ois = null;
try{
ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("F:/IO测试/写出基本数据类型数据lxt.txt")));
//必须要按照写入的顺序读取数据
System.out.println("int: "+ois.readInt());
System.out.println("double: "+ois.readDouble());
System.out.println("char: "+ois.readChar());
System.out.println("boolean: "+ois.readBoolean());
System.out.println("String: "+ois.readUTF());
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(ois != null){
ois.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
结果图
小结:必须要按照写入的顺序读取数据
8.3、操作对象
8.3.1、将对象序列化到文件
- ObjectOutputStream 可以将一个内存中的 Java 对象通过序列化的方式写入到磁盘的文件中。被序列化的对象必须要实现Serializable 序列化接口,否则会抛出异常。
8.3.1.1、创建对象
package com.copyFile;
import java.io.Serializable;
public class Users implements Serializable {
private int userid;
private String username;
private String userage;
public Users(int userid, String username, String userage) {
this.userid = userid;
this.username = username;
this.userage = userage;
}
public Users() {
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserage() {
return userage;
}
public void setUserage(String userage) {
this.userage = userage;
}
}
8.3.1.2、序列化对象
package com.copyFile;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamObjectTypeDemo {
public static void main(String[] args) {
ObjectOutputStream oos = null;
try{
oos = new ObjectOutputStream(new FileOutputStream("F:/IO测试/序列化对象.txt"));
Users users = new Users(1,"Oldlu","18");
oos.writeObject(users);
oos.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(oos != null){
oos.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
8.3.2 将对象反序列化到内存中
package com.copyFile;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class ObjectInputStreamObjectTypeDemo {
public static void main(String[] args) {
ObjectInputStream ois = null;
try{
ois = new ObjectInputStream(new FileInputStream("F:/IO测试/序列化对象.txt"));
Users users = (Users)ois.readObject();
System.out.println(users.getUserid()+"\t"+users.getUsername()+"\t"+users.getUserage());
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(ois != null){
ois.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
结果图
9、随机访问流
- RandomAccessFile 可以实现两个作用:
- 实现对一个文件做读和写的操作。
- 可以访问文件的任意位置。不像其他流只能按照先后顺序读取。
- 在开发某些客户端软件时,经常用到这个功能强大的可以”任意操作文件内容”的类。比如,软件的使用次数和使用日期,可以通过本类访问文件中保存次数和日期的地方进行比对
和修改。 Java很少开发客户端软件,所以在Java开发中这个类用的相对较少。
学习这个流我们需掌握三个核心方法:
- RandomAccessFile(String name, String mode) name 用来确定文件; mode 取r(读)或 rw(可读写),通过mode 可以确定流对文件的访问权限。
- seek(long a) 用来定位流对象读写文件的位置,a确定读写位置距离文件开头的字节个数。
- getFilePointer() 获得流的当前读写位置。
package com.copyFile;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
public static void main(String[] args) {
RandomAccessFile raf = null;
try{
raf = new RandomAccessFile("F:/IO测试/RandomAccessFile.txt","rw");
//将若干数据写入到文件中
int[] arr = new int[]{10,20,30,40,50,60,70,80,90,100};
for(int i=0;i<arr.length;i++){
raf.writeInt(arr[i]);
}
raf.seek(4);
System.out.println(raf.readInt());
//隔一个读一个数据
for(int i=0;i<10; i+=2){
raf.seek(i*4);
System.out.print(raf.readInt()+"\t");
}
System.out.println();
//在第8个字节位置插入一个新的数据45,替换之前的数据30
raf.seek(8);
raf.writeInt(45);
for(int i=0;i<10; i+=2){
raf.seek(i*4);
System.out.print(raf.readInt()+"\t");
}
}catch(Exception e){
e.printStackTrace();
}finally {
try{
if(raf != null){
raf.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
- 结果图
10、File类在IO中的作用
- 当以文件作为数据源或目标时,除了可以使用字符串作为文件以及位置的指定以外,我们也可以使用 File类指定。
package com.copyFile;
import java.io.*;
public class FileInIODemo {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new FileReader(new File("F:/IO测试/lxt.txt")));
bw = new BufferedWriter(new FileWriter(new File("F:/IO测试/lxt3.txt")));
String temp = "";
int i =1;
while((temp = br.readLine()) != null){
bw.write(i+","+temp);
bw.newLine();
i++;
}
bw.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(br != null){
br.close();
}
if(bw != null){
bw.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
总结:以上就是File类的使用以及常用流对象的一些小案例了,在实验过程中,需要注意的还是要合理的运用缓冲流(包装流)去实现包装,使得程序在运行中能跟高效!
注:文章仅做个人学习日记,不做学习建议,学习来源:老翔扯IT