IO 流 对于文件内容的操作主要分为两大类
分别是:
一 字符流 (用于读取纯文本 使用 char处理)
其中,字符流有两个抽象类:Writer Reader
其对应子类FileWriter和FileReader可实现文件的读写操作
BufferedWriter和BufferedReader能够提供缓冲区功能,用以提高效率
二、字节流 (可以读取任何格式的文件 使用 byte处理 )
字节流也有两个抽象类:InputStream OutputStream
其对应子类有FileInputStream和FileOutputStream实现文件读写
BufferedInputStream和BufferedOutputStream提供缓冲区功能
/** * 文件copy * @param sourceFilePath 需要复制的源文件 * @param targetFilePath 目标文件 * @param isCoverWhentargetfileExists 当目标文件存在的时候是否覆盖目标文件 * */ public static void copyFile(String sourceFilePath, String targetFilePath, boolean
isCoverWhentargetfileExists) throws IOException{ //参数 if(null == sourceFilePath || null == targetFilePath ){ throw new NullPointerException("参数不能为空"); } //检查源文件是否存在 File sourceFile = new File(sourceFilePath); if(!sourceFile.exists()){ throw new FileNotFoundException("文件:" + sourceFilePath + "没有找到"); } //检查目标文件是否存在 File targetFile = new File(targetFilePath); if(targetFile.exists() && ! isCoverWhentargetfileExists){ //这里其实应该扩展IOException 自定义一个已经FileExistsException throw new IOException("目标文件已存在!"); } BufferedInputStream input =
new BufferedInputStream(new FileInputStream(sourceFile)); BufferedOutputStream output =
new BufferedOutputStream(new FileOutputStream(targetFile)); byte[]buff=new byte[1024]; //开始复制文件内容 int len=0; while((len=input.read(buff))!=-1){ output.write(buff,0,len); } //关闭流 input.close(); output.close(); }
三、转换流
将字节流转换为字符流 处理乱码(编码,解码)
相对于程序而言:
编码:字符——》二进制
解码:二进制———》字符
乱码的原因:
1.编码解码字符集不统一
2.字节丢失,长度不够
输出转换流:OutputStreamWriter 编码
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("E:/f")),"utf-8"));
输入转换流:InputStreamReader 解码
BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(new File("D:/f")),"utf-8"));
四、字节数组流
字节数组输入流 ByteArrayInputStream
从 内存中的字节数组中读取数据,因此它的数据源是一个字节数组 ;
ByteArrayInputStream类本身采用了适配器设计模式,它把字节数组类型转换为输入流类型,使得程序能够对字节数组进行读操作。
2.字节数组----》程序---》文件 private static void getFileFromBytw(byte[] src,String destPath) throws IOException{ //创建目的地 File dest=new File(destPath); //选择流 输入流 InputStream is=new BufferedInputStream(new ByteArrayInputStream(src)); //选择流 字节数组输出流 OutputStream os=new BufferedOutputStream(new FileOutputStream(dest)); //读操作 byte [] flush=new byte[1024]; int len=0; while((len=is.read(flush))!=-1){ os.write(flush, 0, len); } os.flush(); os.close(); is.close(); }
字节数组输出流 ByteArrayOutputStream
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。
可使用toByteArray()
和toString()
获取数据。关闭 ByteArrayOutputStream 无效
//文件到程序 输入流 字节数组输出流 private static byte[] getBytestFromFile(String srcPath) throws IOException{ //1 创建文件源 File file =new File(srcPath); //创建目的地 byte[]dest=null; //选择流 输入流 InputStream is=new BufferedInputStream(new FileInputStream(file)); //选择流 字节数组输出流 ByteArrayOutputStream baos=new ByteArrayOutputStream(); //读操作 byte [] flush=new byte[1024]; int len=0; while((len=is.read(flush))!=-1){ baos.write(flush, 0, len); } baos.flush(); //获取数据 dest=baos.toByteArray(); baos.close(); is.close(); System.out.println(new String(dest)); return dest; }
五、处理流
基本数据类型处理流
输入流 DataInputStream
private static void dataReadIo(String src) throws IOException{ //创建源 File file=new File(src); //选择流 DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream(file))); //操作 注意读出的顺序 double d=dis.readDouble(); int m=dis.readInt(); String str=dis.readUTF(); System.out.println(str); }
输出流:DataOutputStream
private static void dataWriteIo(String src) throws IOException{ double dou=1000d; int m=100; String str="AAAAAAAAAAA"; //创建 目标 File file=new File(src); //选择流 DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); //操作 注意写出的顺序 dos.writeDouble(dou); dos.writeInt(m); dos.writeUTF(str); dos.flush(); dos.close(); }
引用数据类型处理流
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、
对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
readObject
方法用于从流读取对象。应该使用 Java 的安全强制转换来获取所需的类型。在 Java 中,字符串和数组都是对象,
所以在序列化期间将其视为对象。读取时,需要将其强制转换为期望的类型。
反序列化:ObjectInputStream
private static void fSerIo(String src) throws FileNotFoundException, IOException, ClassNotFoundException{ //创建 源 File file=new File(src); //选择流 ObjectInputStream ois=new ObjectInputStream(new BufferedInputStream(new FileInputStream(file))); //操作 Object obj=ois.readObject(); if(obj instanceof Employee){ Employee emp=(Employee) obj; System.out.println(emp.getMoney()+"_______________"+emp.getName()); } }
序列化:ObjectOutputStream
//序列化 private static void serIo(String src) throws FileNotFoundException, IOException{ Employee emp=new Employee("张三", 10000.123); //创建 目的地 File file=new File(src); //选择流 ObjectOutputStream oos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); //操作 oos.writeObject(emp); oos.flush(); oos.close(); }
RandomAccessFile :
供了一种类似于文件指针的东西,他可以随着你对文件的读或者写操作来进行指针的移动,从而实现对文件的随机读取。具体的获取及相关操作就要用到接下来的几种
RandomAccessFile的常用方法
1:构造方法
RandomAccessFile 对象名称 = new RandomAccessFile(file,mode); 创建从中读取和向其中写入的随机访问文件流
◆file参数:进行具体操作所对应的文件
◆mode参数:指打开文件的具体访问模式,常用的有如下两种,其他可以参见帮助文档
“r”:以只读的方式打来文件(即对文件只能进行读操作)
"rw":以读和写的双重方式打开文件(即对文件可以进行读与写双重操作)
2:常用方法
(1)public long getFilePointer() throws IOException 获取当前文件指针相对于文件开头的偏移量
(2)public void seek(long pos) throws IOException 设置当前文件指针相对于文件开头的偏移量
(3)public long length() throws IOException 返回当前文件的长度
public static void main(String[] args) throws Exception { //创建操作的文件对象 File file = new File("d:"+File.separator+"a.txt"); //对指定的文件,以读写双重方式,创建随机文件访问流 RandomAccessFile raf = new RandomAccessFile(file,"rw"); //默认的文件指针指向文件开头位置 System.out.println("文件指针位置1:"+raf.getFilePointer()); String trs = "Abcdef"; byte[] str=trs.getBytes(); raf.write(str);//写入六个字符 //写入六个字符后,文件指针指向第七个位置6 System.out.println("文件指针位置2:"+raf.getFilePointer()); //1:绝对定位 raf.seek(0);//将光标强制的移动到文件的开始位置0 //2:相对定位 raf.skipBytes(5);//相对于当前位置跳过5个字节,如果为负值,不跳过任何字节 System.out.println("文件指针位置3:"+raf.getFilePointer()); //读操作进行之后,指针向后移 char i = (char)raf.read(); System.out.println("文件指针位置4:"+raf.getFilePointer()); System.out.println(i); }
流的关闭方法
/** * @param io * 可变参数 ... 只能在 参数最后 处理方式与数组相同 */ public static void closeIo(Closeable ...io){ for(Closeable cl:io){ try { if(cl!=null){ cl.close(); } } catch (IOException e) { e.printStackTrace(); } } }