在Java中,Everything is Object!所以在文件中,也不例外!在Java中,可以用 File类来表示一个与硬盘上文件联系!!!注意:
1、 File仅代表一个联系,可能文件存在,也可能不存在;
2、 这里的文件可以是文件,也可以是文件夹;
流即流动、流向,从一端流向另一端。如水流:从山里流向到人家;车流:从公司流动到家里;声音流:从发出者流动到对方的耳朵里。
文件流:从一端流动到另一端,即从java内存流动到存储介质中。存储介质包括:硬盘文件、数据库与网络等节点(数据源)。记住:一切以java内存为中心。
data source. 提供原始数据的原始媒介。常见的:数据库、文件、其他程序、内存、网络连接、IO设备。
数据源就像水箱,流就像水管中流着的水流,程序就是我们 终的用户。 流是一个抽象、动态的概念,是一连串连续动态的数据集合。
由此可见,IO流很庞大,从不同角度进行分类
按处理数据单位分为:字节流和字符流。处理数据是音频、视频、doc、文本等一切为字节流,仅能处理文本的为字符流。 字节流和字符流的用法几乎完全一致,区别在于它们所操作的数据单元不同,字节流(8 位)、字符流(16 位),字节流主要由 InputStream 和OutputStream作为基类,字符流主要由Reader 和 Writer作为基类。
输入流和输出流。从节点到 java 内存叫输入流,从 java 内存到节点叫输出流。Java 的输入流主要由InputStream 和Reader作为基类,输出流主要由OutputStream和Writer作为基类。
节点流和处理流。从/向一个特定的I/0设备(磁盘、网络等)读写数据的流称为节点流,也常被称为低级流。 处理流则对于一个已存在的节点流进行连接或封装,常被称为高级流(装饰器设计模式)。处理流为增强、提升性能的,本身不具备直接操作节点的能力。如扩音器,就是放大声音的。 节点流处于io操作的第一线,所有操作必须通过他们进行;处理流可以对其他流 进行处理(提高效率或操作灵活性).
处理流的功能主要体现在:
a、性能的提高:主要以增加缓冲的方式来提高输入/输出的效率 ;
b、 操作的便捷:提供了系列便捷的方法来一次输入/输出大批量内容
使用流抽象的概念,屏蔽了实际的 I/O设备中处理数据的细节。
核心步骤如下
1)、建立联系
2)、选择流
3)、操作:写出 读取
4)、释放资源(程序中打开的文件 IO 资源不属于内存中的资源,垃圾回收无法回收,需要显示关闭。)
字节流和字符流的操作方式几乎完全一样,只是操作的数据单元不同而已 。字节流可以操作所有文件,字符流仅操作纯文本。
InputStream和Reader是所有输入流的基类,它们是两个抽象类,是所有输入流的模版,其中定义的方法在所有输入流中都可以使用。
在InputStream里包含如下三个方法:
在Reader中包含如下三个方法:
对比InputStream和Reader 所提供的方法,可以看出这两个基类的功能基本相似。返回结果为-1 时表明到了输入流的结束点。 InputStream 和 Reade 都是抽象的,不能直接创建它们的实例,可以使用它们的子类。
FileInputStream 和 FileReader,它们都是节点流,直接和指定文件关联。 操作方式基本一致。
单个字节读取
以FileInputStream为例
public class SingleFileRead { public static void main(String[] args) { // 1、建立联系 File对象 File file = new File("f:/IO/test.txt"); // 2、选择流 InputStream in = null;// 提升作用域 try { in = new FileInputStream(file); // 3、操作 单个字节读取 long fileLength = file.length(); // 接收实际读取的字节数 // 计数器 System.out.println(fileLength); long num = 0; // 循环读取 while (num < fileLength) { char ch = (char) in.read(); System.out.println(ch); num++; } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("文件不存在,不能进行下一步操作"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("读取文件失败"); } finally { try { // 4、释放资料 if (in != null) { in.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("关闭文件输入流失败"); } } } }批量读取
public class ReadFile { public static void main(String[] args) { //1、字节读取:建立联系 File对象 File file=new File("f:/IO/test.txt"); //2、选择流 InputStream in=null;//提升作用域 try { in=new FileInputStream(file); //3、操作 不断读取 缓冲数组 byte[]car=new byte[1024]; int len=0; //接收实际读取的大小 //循环读取 while(-1!=(len=in.read(car))){ //输出,字节数组转成字符串 String info=new String(car,0,len); System.out.println(info); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("文件不存在"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("读取文件失败"); }finally{ try { //4、释放资料 if(in!=null){ in.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("关闭文件输入流失败"); } } } } //字符读取1、创建源 File src=new File("f:/char.txt"); //2、选择流 Reader reader=new FileReader(src); //3、读取操作 char[] flush=new char[1024]; int len=0; while(-1!=(len=reader.read(flush))){ //字符数组转换为字符串 String str=new String(flush,0,len); System.out.println(str); } //4、释放资源 reader.close();OutputStream和Writer也非常相似。
在OutputStream 里包含如下方法:
在 Writer 中, 因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来代替字符数组,即以String对象来作为参数。 包含如下方法:
FileOutputStream 和 FileWriter,它们都是节点流,直接和指定文件关联。
public class WriteFile { public static void main(String[] args) { //1、建立联系 File对象 源头 目的地 File dest=new File("c:/IO/print.txt"); //2、选择流 文件输出流 OutputStream FileOutputStream OutputStream out=null; //以追加形式写出文件 必须为true 否则会覆盖 try { out=new FileOutputStream(dest,true); //3、操作 String str="shsxt is very good \r\n good good good"; //字符串转成字节数组 byte[] data=str.getBytes(); out.write(data,0,data.length); out.flush();//强制刷新出去 } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("文件未找到"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("文件写出失败"); }finally{ try { if(out!=null){ out.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("关闭输出流失败"); } } } } //1、创建源 File dest=new File("f:/IO/char.txt"); //2、选择流 Writer wr=new FileWriter(dest,true); //3、写出 String str="锄禾日当午\r\n码农真辛苦\r\n一本小破书\r\n一读一上午"; wr.write(str); //追加内容 wr.append("我就是追加进去的"); wr.flush();//强制刷出 //4、关闭资源 wr.close();结合输入输出流,可以实现文件拷贝
public static void copyFile(String srcPath, String destPath) throws FileNotFoundException,IOException{ // 1、建立联系 源(存在且为文件) 目的地(文件可以不存在) File src = new File(srcPath); File dest = new File(destPath); if(!src.isFile()){//不是文件或者为null时抛出异常 System.out.println("只能拷贝文件"); throw new IOException("只能拷贝文件"); } // 2、选择流 InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest); // 3、操作 byte[] flush = new byte[1024]; int len = 0; // 读取 while (-1 != (len = in.read(flush))) { // 写出 out.write(flush, 0, len); } out.flush();// 强制刷出 // 关闭流 先打开的后关闭 out.close(); in.close(); }缓冲提高性能: 字节流直接套上即可;字符缓冲流 +新增方法(不能使用多态):
//1、创建源,建立联系 File src =new File("test.txt"); //2、选择缓冲流 InputStream is =new BufferedInputStream(new FileInputStream(src)); //3、操作 : 多个读取 byte[] car =new byte[2]; int len =0; while(-1!=(len=is.read(car))){ //获取数组的内容 字节数组转字符串 new String(字节数组,0,length) System.out.println(new String(car,0,len)); } //4、释放资源 is.close(); //创建源: File src =new File("test.txt"); //使用字符缓冲流 提高性能读取文件 +新增方法(不能使用多态) BufferedReader br =new BufferedReader(new FileReader(src)); //操作 行读取 String line=null; while(null!=(line=br.readLine())){ System.out.println(line); } //释放资源 br.close();转换流:将字节流转为字符流 处理乱码(编码集、解码集)。
//读取文件 File src =new File("test.txt"); //转换流 BufferedReader br =new BufferedReader( new InputStreamReader( new BufferedInputStream( new FileInputStream( src ) ),"utf-8" ) ); //行读取 String msg =null; while(null!=(msg =br.readLine())){ System.out.println(msg); } br.close();可以处理基本类型+String,保留数据的类型。前提是读取顺序与写出顺序一致,否则读取数据不正确
/** * 数据+类型 输出到文件 * @param destPath * @throws IOException */ public static void write(String destPath) throws IOException{ int point=2; long num=100L; String str="数据类型"; //创建源 File dest=new File(destPath); //选择流 DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dest))); //操作 写出的顺序 为读取作准备 dos.writeInt(point); dos.writeLong(num); dos.writeUTF(str); dos.flush(); //释放资源 dos.close(); }以前我们学过的流都只能读写字节,字符形式的数据,而java中非常重要并且常见的对象类型的数据,如果想要存 储到文件中应该怎么操作呢?这个时候就使用到了对象流。
序列化:是一个用于将对象状态转换为字节流的过程,可以将其保存到磁盘文件中或通过网络发送到任何其他程序
反序列化:从字节流创建对象的相反的过程称为反序列化
ObjectInputStream能够让你从输入流中读取Java对象,而不需要每次读取一个字节。你可以把InputStream包装 到ObjectInputStream中,然后就可以从中读取对象了
首先在使用ObjectInputStream和ObjectOutputStream的时候,放置在此IO中的对象,必须要实现Serializable 接口!序列化接口(实现了此接口,代表我们的对象支持序列化)
但是实现了Serializable接口之后,其中并没有实现任何方法,对于这种接口,我们称之为标记接口。
/** * 反序列化: * 1、先写入再读取 * 2、读取对象需要知道具体类型,依次读取 * 注意: * 1)不是所有的对象都可以序列化 Serializable * 2)不是所有的属性都需要序列化 transient */ public static void read(String srcPath) throws FileNotFoundException, IOException, ClassNotFoundException{ //创建源 File src=new File(srcPath); //选择流 OjbectInputStream ObjectInputStream dis=new ObjectInputStream( new BufferedInputStream( new FileInputStream(src) ) ); //操作 读取的顺序与写出的顺序一致 必须存在才能读取 Object obj=dis.readObject(); if(obj instanceof Employee){ Employee emp=(Employee)obj; System.out.println(emp.getName()); System.out.println(emp.getSalary()); } obj=dis.readObject(); int[]arr=(int[])obj; System.out.println(Arrays.toString(arr)); //释放资源 dis.close(); }注意: 要先序列化后反序列化
//创建源 File dest=new File(destPath); //选择流 OjbectOutputStream ObjectOutputStream dos=new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream(dest) ) ); //操作 读取的顺序与写出的顺序一致 必须存在才能读取 Employee obj=new Employee (“yinwei”,1500); dos.writeObject(obj); //刷出 dos.flush(); //释放资源 dos.close();commons-IO是apache的一个开源的工具包,封装了IO操作的相关类,使用Commons IO可以很方便的读写文件,url 源代码等。commons-IO 需要加入classpath 的第三方 jar 包内的 class 文件才能在项目中使用
从某个地方以合法合理的方式获取都行。
commons-io-2.4.jar 就是需要导入到项目中的 jar 包,里面存放的是class文件commons-io-2.4-sources.jar 工具类中原代码docs 是帮助文档build path
这个工具类是用来处理文件名(文件路径)的,可以轻松解决不同操作系统文件名称规范不同的问题,里面的方法 都是静态的,直接用类进行调用
常用方法:
getName():获取文件名 getExtension(String path):获取文件的扩展名 isExtension(String fileName,String ext):判断fileName是否是ext后缀名
提供文件操作,如移动文件、读取文件、检查文件是否存在等的方法
常用方法:
readFileToString(File file):读取文件内容,并返回一个String writeStringToFile(File file,String content):将内 容content写入到file中 copyDirectoryToDirectory(File srcDir,File destDir):文件夹复制 copyFile(File srcFile,File destFile):文件复制
