一、概念
流:流动、流向,从一端移动到另一端,源头到目的地
程序 与 数据源(文|数组|网络连接|数据库),以程序为中心
二、IO流分类
1.流向:输入流与输出流 (以程序为中心)
2.数据:字节流:二进制,可以处理一切文件,包括纯文本、doc、音频、视频等等
字符流:文本文件,只能处理纯文本
3.功能:节点流,包裹源头(离源头最近)
处理流,增强功能,提供性能
三 字符流与字节流(重点)
1.字节流
输入流:InputStream(抽象类)
FileInputStream()
输出流: OutputStream (抽象类)
FileOutputStream()
2.字符流
输入流:Reader(抽象类)
FileReader()
输出流: Writer(抽象类)
FileWriter()
四、操作
1.举例:搬家 ----------------------->读取文件
(1)关联房子 ----------------->建立与文件的联系--->File对象
(2)选择搬家 ------------------>选取对应流
(3)搬家 ---------------->读取|写出
(a)卡车大小 -------------->数组大小
(b)运输 ----------------->读取、写出
(4)打发over -------------->释放资源
五、字节流的读取与写出
FileInputStream构造器
public class Demo01 { public static void main(String[] args) { //建立联系 File对象 File src = new File("/home/deepin/Desktop/test/aa.txt"); //选择流 //InputStream is = new FileInputStream("/home/deepin/Desktop/test/aa.txt"); InputStream is = null; try { is = new FileInputStream(src); //操作 不断读取缓冲数组 byte[] car = new byte[10]; int len =0; //接收实际读取大小 //循环读取 while (-1 != (len = is.read(car))) { //字节数组转成字符串 String info = new String(car, 0, len); System.out.println(info); } } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("文件不存在"); } catch (IOException e) { e.printStackTrace(); System.out.println("读取文件失败"); }finally { if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("关闭文件输入流失败"); } } } } }
FileOnputStream构造器
public class Demo02 { public static void main(String[] args) { //建立联系 File对象 File dest = new File("/home/deepin/Desktop/test/aa.txt"); //选择流 OutputStream os = null; try { //以追加的形式 os = new FileOutputStream(dest,true); //操作 String str = "heyuying\n"; //字符串转字节数组 byte[] data = str.getBytes(); os.write(data,0,data.length); //强制刷新出去,由于有管道,只有管道满时,才会写到文件 os.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("文件未找到"); } catch (IOException e) { e.printStackTrace(); System.out.println("文件写出失败"); }finally { try { if (null != os) { os.close(); } } catch (IOException e) { e.printStackTrace(); System.out.println("关闭输出流失败"); } } } }
文件与文件夹的拷贝
public class FileUtil { //文件的拷贝 public static void copyFile(String srcPath, String destPath) throws IOException { //1.建立联系 源(存在且为文件)+ 目的地(文件可不存在) copyFile(new File(srcPath),new File(destPath)); } public static void copyFile(File src,File dest) throws IOException { if (!src.isFile()) { //System.out.println("只能拷贝文件"); throw new IOException("只能拷贝文件"); } //dest为已经存在的文件夹,不能建立与文件夹同名的文件 if (dest.isDirectory()) { System.out.println(dest.getAbsolutePath()+"不能建立与文件夹同名的文件"); throw new IOException(dest.getAbsolutePath()+"不能建立与文件夹同名的文件"); } //2.选择流 InputStream is = new FileInputStream(src); OutputStream os = new FileOutputStream(dest); //文件的拷贝 循环读取+写出 byte[] flush = new byte[1024]; int len = 0; while (-1 != (len = is.read(flush))) { os.write(flush, 0, len); } os.flush(); //关闭流 os.close(); is.close(); } //拷贝文件夹 public static void copyDir(String srcPath, String destPath) throws IOException { File src = new File(srcPath); File dest = new File(destPath); copyDir(src,dest); }
//拷贝文件夹 public static void copyDir(File src, File dest) throws IOException { if (src.isDirectory()) { //文件夹 dest = new File(dest, src.getName()); } if (dest.getAbsolutePath().contains(src.getAbsolutePath())) { System.out.println("不能将父目录拷贝到子目录中"); return; } copyDirDetail(src, dest); } //拷贝文件夹的细节 public static void copyDirDetail(File src, File dest)throws IOException { if (src.isFile()) { try { FileUtil.copyFile(src, dest); } catch (IOException e) { e.printStackTrace(); throw e; } } else if (src.isDirectory()) { //文件夹 //确保目标文件夹存在 dest.mkdirs(); //获取下一级目录|文件 for (File sub : src.listFiles()) { copyDirDetail(sub,new File(dest,sub.getName())); } } } }
六、字符流
字符流:文本文件,只能处理纯文本,全部为可见字符 .txt .html
节点流 Reader FileReader
Writer FileWriter
1.纯文本读取
1)建立联系
2)选择流 Reader FileReader
3)读取 char[] flush = nwe char[1024];
4)关闭
//字符流的读取 public class CharReader { public static void main(String[] args) { //建立源 File src = new File("/home/deepin/Desktop/test/test.txt"); //选择流 Reader reader = null; try { reader = new FileReader(src); //读取操作 char[] flush = new char[10]; int len = 0; while (-1 != (len = reader.read(flush))) { //字符数组转成字符串 String str = new String(flush, 0, len); System.out.println(str); } } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("源文件不存在"); } catch (IOException e) { e.printStackTrace(); System.out.println("读取文件失败"); }finally { if (null != reader) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("关闭失败"); } } } } }
2.纯文本写出
1)建立联系
2)选择流 Writer FileWriter
3)写出 write(字符数组,0,长度)+flush()
4)关闭
//字符流的写出 public class CharWriter { public static void main(String[] args) { //建立源 File dest = new File("/home/deepin/Desktop/test/test.txt"); //选择流 Writer wr = null; try { //追加文件,而不是覆盖文件true wr = new FileWriter(dest,true); //写出 String msg = "......当希望不再有,你还会坚持吗?"; wr.write(msg); wr.append("加油"); wr.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if (null != wr) { try { wr.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("关闭流失败"); } } } } }
3.纯文件的拷贝
//字符流的拷贝 public class CharCopyFile { public static void main(String[] args) { //建立源 仅限于纯文本 File src = new File("/home/deepin/Desktop/test/test.txt"); File dest = new File("/home/deepin/Desktop/test/aa.txt"); //选择流 Reader reader = null; Writer wr = null; try { reader = new FileReader(src); wr = new FileWriter(dest); //读取操作 char[] flush = new char[1024]; int len = 0; while (-1 != (len = reader.read(flush))) { wr.write(flush, 0, len); } wr.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("源文件不存在"); } catch (IOException e) { e.printStackTrace(); System.out.println("读取文件失败"); }finally { try { if (null != wr) { wr.close(); } }catch (IOException e) { e.printStackTrace(); } try { if (null != reader) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
七、处理流 增强功能,提供性能,在节点流之上
1.节点流与处理流的关系
节点流处于io操作的第一线,所有操作必须通过它们进行;处理流可以对其他流进行处理(提高效率或操作灵活性)
2.缓冲流
1)字节缓冲流
BufferedInputStream
BufferedOutputStream
//字节流文件拷贝+缓冲流 提高性能 public class BufferedByteDemo { public static void copyFile(String srcPath, String destPath) throws IOException { File src = new File(srcPath); File dest = new File(destPath); if (!src.isFile()) { //System.out.println("只能拷贝文件"); throw new IOException("只能拷贝文件"); } //2.选择流 InputStream is = new BufferedInputStream(new FileInputStream(src)); OutputStream os = new BufferedOutputStream(new FileOutputStream(dest)); //文件的拷贝 循环读取+写出 byte[] flush = new byte[1024]; int len = 0; while (-1 != (len = is.read(flush))) { os.write(flush, 0, len); } os.flush(); //关闭流 os.close(); is.close(); } }
2)字符缓冲流
BufferedReader readLine()
BufferedWriter newLine()
//字符缓冲流+新增方法(不能发生多态) public class BufferedCharDemo { public static void main(String[] args) { //建立源 仅限于纯文本 File src = new File("/home/deepin/Desktop/test/test.txt"); File dest = new File("/home/deepin/Desktop/test/aa.txt"); //选择流 BufferedReader reader = null; BufferedWriter wr = null; try { reader = new BufferedReader(new FileReader(src)); wr = new BufferedWriter(new FileWriter(dest)); /* char[] flush = new char[1024]; int len = 0; while (-1 != (len = reader.read(flush))) { wr.write(flush, 0, len); }*/ //读取操作 一行一行读取 String line = null; while (null!=(line=reader.readLine())) { wr.write(line); wr.newLine(); //换行符 } wr.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("源文件不存在"); } catch (IOException e) { e.printStackTrace(); System.out.println("读取文件失败"); } finally { try { if (null != wr) { wr.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (null != reader) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
3.转换流:字节流 转换为字符流 处理乱码(编码集、解码集)
1)编码与解码概念
编码:字符 --编码字符集--> 二进制
解码:二进制 --解码字符集-->字符
2)乱码
<1>编码与解码的字符集不统一
//编码与解码字符集必须相同,否则乱码 public static void test1() throws UnsupportedEncodingException { //解码byte--->char utf-8 String str = "中国"; //编码 char-->byte utf-8 byte[] data = str.getBytes(); //编码与解码字符集统一 System.out.println(new String(data)); //设定编码字符集 utf-8 data = str.getBytes("utf-8"); System.out.println(new String(data)); //编码 byte[] data2 = "中国".getBytes("utf-8"); //解码 str = new String(data, "utf-8"); System.out.println(str); }
可以通过此方法设置解码字符集
<2>字节缺少,长度丢失
String str = "中国"; byte[] data = str.getBytes(); //字节数不完整 System.out.println(new String(data, 0, 2));
转换流:字节流转换为字符流
1.输出流:OutputStreamWriter 编码
2.输入流:InputStreamReader 解码
public class ConverDemo02 { public static void main(String[] args) throws IOException { //指定解码字符集 BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream( new File("/home/deepin/Desktop/test/test.txt") ),"UTF-8" ) ); //写出文件 BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( new File("/home/deepin/Desktop/test/aa.txt") ),"Utf-8" ) ); String info = null; while (null != (info = br.readLine())) { System.out.println(info); bw.write(info); bw.newLine(); } bw.flush(); bw.close(); br.close(); } }
IO流总结
八、其他流
1.节点流
1)字节数组
输入流:ByteArrayInputStream read(byte[] b, int off, int len)
输出流:ByteArrayOutputStream write(byte[] b, int off, int len)
+ toByteArray() 不要使用多态
/* * 输入流 操作与文件输入流操作一致 * 读取字节数组 * */ public static void read(byte[] src) throws IOException { //数据源 //String msg = "操作与文件输入流操作一致"; //byte[] src = msg.getBytes(); //选择流 InputStream is = new BufferedInputStream( new ByteArrayInputStream( src ) ); //操作 byte[] flush = new byte[1024]; int len = 0; while (-1 != (len = is.read(flush))) { System.out.println(new String(flush, 0, len)); } //释放资源 is.close(); }
/* * 输出流 操作与文件输入流操作有些不同,有新增方法,不是使用多态 * * */ public static byte[] write() throws IOException { //目的地 byte[] dest; //选择流 ByteArrayOutputStream bos = new ByteArrayOutputStream(); //写出 String msg = "操作与文件输入流操作一致"; byte[] info = msg.getBytes(); bos.write(info,0,info.length); //获取数据 dest = bos.toByteArray(); bos.close(); return dest; }
文件流与字节数组流对接完成文件的拷贝(之前是:文件--程序-->文件)
1.文件--程序-->字节数组
2.字节数组--程序-->文件
/* *1.文件--程序-->字节数组 * 文件输入流 * 字节数组输出流 * 2.字节数组--程序-->文件 * 字节数组输入流 * 文件输出流 * */ public class ByteArrayDemo02 { public static void main(String[] args) throws IOException { byte[] data = getBytesFromFile("/home/deepin/Desktop/test/test.txt"); System.out.println(new String(data)); toFileFromByteArray(data,"/home/deepin/Desktop/test/test1.txt"); } //2.字节数组--程序-->文件 public static void toFileFromByteArray(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 (-1 != (len = is.read(flush))) { //写出到文件中 os.write(flush, 0, len); } os.flush(); //释放资源 os.close(); is.close(); } //1.文件--程序-->字节数组 public static byte[] getBytesFromFile(String srcPath) throws IOException { //创建文件源 File src = new File(srcPath); //创建字节数组目的地 byte[] dest = null; //选择流 //文件输入流 InputStream is = new BufferedInputStream(new FileInputStream(src)); //字节数组输出流 不能使用多态 ByteArrayOutputStream bos = new ByteArrayOutputStream(); //操作 不断地读取文件写出到字符数组流中 byte[] flush = new byte[1024]; int len = 0; while (-1 != (len = is.read(flush))) { //写出到字节数组流中 bos.write(flush, 0, len); } bos.flush(); //获取数据 dest = bos.toByteArray(); //释放资源 bos.close(); is.close(); return dest; } }
2)字符数组
输入流:CharArrayReader
输出流:CharArrayWriter
2.处理流
1)基本类型+String 保留数据+类型
输入流 : DataInputStream readXX
输出流:DataOutputStream writeXX
1>向文件写数据+类型和从文件读取数据+类型
/* * 数据类型(基本数据类型+String)处理流 * 1.输入流 DataInputStream * 2.输出流 DataOutputStream * 新增方法不能用多态 * java.io.EOFException 没有读取到相关内容 * */ public class DataDemo01 { public static void main(String[] args) throws IOException { write("/home/deepin/Desktop/test/aa.txt"); //read("/home/deepin/Desktop/test/test.txt"); //文件存在,但为非法内容 read("/home/deepin/Desktop/test/aa.txt"); } /* * 从文件读取数据+类型 * */ public static void read(String destPath) throws IOException { File src = new File(destPath); DataInputStream dis = new DataInputStream( new BufferedInputStream(new FileInputStream(src)) ); //操作 读取顺序与写出一致,若读取顺序不一致,则数据会有问题 double num1 = dis.readDouble(); long num2 = dis.readLong(); String str2 = dis.readUTF(); dis.close(); System.out.println(num1+"-->"+num2+"-->"+str2); } /* * 数据+类型输出到文件 * */
public static void write(String destPath) throws IOException { double point = 2.5; long num = 100l; String str = "数据类型"; //创建源 File dest = new File(destPath); DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dest)) ); //操作 写出的顺序为读取准备 dos.writeDouble(point); dos.writeLong(num); dos.writeUTF(str); dos.flush(); dos.close(); } }
2>向字节数组写数据+类型和从字节数组读取数据+类型
public class DataDemo02 { public static void main(String[] args) { try { byte[] data = write(); System.out.println(data.length); read(data); } catch (IOException e) { e.printStackTrace(); } } /* * 从字节数组中读取数据+类型 * */ public static void read(byte[] src) throws IOException { DataInputStream dis = new DataInputStream( new BufferedInputStream(new ByteArrayInputStream(src)) ); //操作 读取顺序与写出一致,若读取顺序不一致,则数据会有问题 double num1 = dis.readDouble(); long num2 = dis.readLong(); String str2 = dis.readUTF(); dis.close(); System.out.println(num1+"-->"+num2+"-->"+str2); } /* * 数据+类型输出到字节数组中 * */ public static byte[] write() throws IOException { //目标数组 byte[] dest; double point = 2.5; long num = 100l; String str = "数据类型"; ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(bos) ); //操作 写出的顺序为读取准备 dos.writeDouble(point); dos.writeLong(num); dos.writeUTF(str); dos.flush(); dest = bos.toByteArray(); dos.close(); return dest; } }
2)引用(对象)保留数据+类型
反序列化 输入流 ObjectInputStream readObject()
序列化 输出流 ObjectOutputStream writeObject()
注意:
1>先序列化再反序列化
2>不是所有对象都可以序列化,要实现java.io.Serializable接口的类的对象可序列化
3>不是所有的属性都需要序列化,不需要序列化的属性用transient修饰
public class ObjectDemo01 { public static void main(String[] args) throws IOException, ClassNotFoundException { seri("/home/deepin/Desktop/test/aa.txt"); read("/home/deepin/Desktop/test/aa.txt"); } //反序列化 public static void read(String destPath) throws IOException, ClassNotFoundException { File src = new File(destPath); ObjectInputStream ois = new ObjectInputStream( new BufferedInputStream(new FileInputStream(src)) ); //操作 Object obj = ois.readObject(); if (obj instanceof Employee) { Employee emp = (Employee) obj; System.out.println(emp.getName()); System.out.println(emp.getSalary()); } obj = ois.readObject(); int[] arr = (int[]) obj; System.out.println(Arrays.toString(arr)); ois.close(); } //序列化 public static void seri(String destPath) throws IOException { Employee emp = new Employee("bjsxt", 10000); int[] arr = {1, 2, 3, 4}; //创建源 File dest = new File(destPath); ObjectOutputStream oos = new ObjectOutputStream( new BufferedOutputStream(new FileOutputStream(dest)) ); oos.writeObject(emp); oos.writeObject(arr); oos.flush(); oos.close(); } }3.编写工具类,实现关闭功能
public class FileCloseUtil { /* * 工具类关闭流 * 可变参数...只能形参最后一个位置,处理方式与数组一致 * */ public static void close(Closeable... io) { for (Closeable temp : io) { if ( null != temp) { try { temp.close(); } catch (IOException e) { e.printStackTrace(); } } } }
public static <T extends Closeable> void closeAll(T... io) { for (Closeable temp : io) { if ( null != temp) { try { temp.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
4.打印流
1)输出到控制台-->文件
/* * PrintStream打印流---->处理流 * * */ public class PrintStreamDemo01 { public static void main(String[] args) throws FileNotFoundException { System.out.println("test"); PrintStream ps = System.out; //输出到控制台 ps.println(false); //输出到文件 File src = new File("/home/deepin/Desktop/test/print.txt"); ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(src))); ps.println("io is so easy..."); ps.close(); } }
2)从控制台输入到从文件读取
/* * 三个常量 * 1.System.in --->InputStream对象, 输入流 键盘输入 * 2.System.out --->OutputStream对象 输出流 控制台输出 * 3.System.err---->OutputStream对象 * */ public class SystemDemo01 { public static void main(String[] args) throws FileNotFoundException { //test1(); InputStream is = System.in; //键盘输入 Scanner sc = new Scanner(is); System.out.println("请输入:"); System.out.println(sc.nextLine()); is = new BufferedInputStream(new FileInputStream("/home/deepin/Desktop/test/test.txt")); Scanner scanner = new Scanner(is); //从文件中使用Scanner System.out.println(scanner.nextLine()); /*重定向 setIn() setOut() setErr() FileDescriptor.in 输入控制台 FileDescriptor.out 输出控制台 FileDescriptor.err * */ System.setOut(new PrintStream( new BufferedOutputStream( new FileOutputStream("/home/deepin/Desktop/test/print.txt") ) ,true) ); System.out.println("a"); //控制台-->文件 //回控制台 System.setOut(new PrintStream( new BufferedOutputStream( new FileOutputStream(FileDescriptor.out) ) ,true) ); System.out.println("back...."); } public static void test1() { System.out.println("test"); System.err.println("err"); //打印一个错误信息 } }
3)用BufferedReader代替Scanner
public class BufferedIn { public static void main(String[] args) throws IOException { InputStream is = System.in; BufferedReader br = new BufferedReader(new InputStreamReader(is)); System.out.println("请输入。。。。"); String msg = br.readLine(); System.out.println(msg); } }
5. IO -- 装饰设计模式
例子:对声音进行放大,用扩音器装饰
public class Voice { private int voice = 10; public Voice() { } public Voice(int voice) { this.voice = voice; } public int getVoice() { return voice; } public void setVoice(int voice) { this.voice = voice; } public void say() { } }
/*类与类之间的关系 * 1.依赖:类作为方法的形参或局部变量 * 2.关联:属性(类用来声明属性) * 聚合:属性 整体与部分 不一致的生命周期 * 组合:属性 整体与部分 一致的生命周期 * 3.继承:父子类的关系 * 4.实现:接口与实现类的关系 * */ public class Amplifier { private Voice voice; public Amplifier() { } public Amplifier(Voice voice) { this.voice = voice; } public void say() { System.out.println(voice.getVoice() * 1000); } }
public class App { public static void main(String[] args) { Voice v = new Voice(); v.say(); Amplifier am = new Amplifier(v); am.say(); } }
6.文件的分割与合并
分割:RandomAccessFile
public class RndDemo01 { public static void main(String[] args) throws IOException { RandomAccessFile rnd = new RandomAccessFile(new File("/home/deepin/Desktop/test/test.txt"), "r"); rnd.seek(0);//从第几个字节开始读 byte[] flush = new byte[1024]; int len = 0; while (-1 != (len = rnd.read(flush))) { if (len >= 73) { //如果大于73,就读取73 System.out.println(new String(flush, 0, 73)); break; } else {//小于73,则读取全部 System.out.println(new String(flush, 0, len)); } } rnd.close(); } }
合并:SequenceInputStream
/*文件分割思路: * 1.分割的块数 size n块 * 2.每一块的大小 blockSize * 最后一块:总的文件大小-(n-1)*blockSize * */
public class SplitFile { //文件的路径 private String filePath; //文件名 private String fileName; //文件的大小 private long fileLength; //块数 private int size; //每块的大小 private long blockSize; //分割后的存放目录 private String destBlockPath; //每块的名称 private List<String> blockPath; public SplitFile() { blockPath = new ArrayList<>(); } public SplitFile(String filePath,String destBlockPath) { this(filePath, destBlockPath,1024); } public SplitFile(String filePath, String destBlockPath,long blockSize ) { this(); this.filePath = filePath; this.destBlockPath = destBlockPath; this.blockSize = blockSize; init(); } //初始化操作,计算块数、确定文件名 public void init() { File src = null; if (null == filePath || !((src = new File(filePath)).exists())) { return; } if (src.isDirectory()) { return; } //文件名 this.fileName = src.getName(); //计算块数 文件实际大小 与每块大小 this.fileLength = src.length(); if (this.blockSize > this.fileLength) { this.blockSize = this.fileLength; } //确定块数 size = (int) Math.ceil(this.fileLength * 1.0 / this.blockSize); //确定文件的路径 initPathName(); } private void initPathName() { for (int i = 0; i < size; i++) { this.blockPath.add(destBlockPath + "/" + this.fileName + ".part" + i); } } //文件的分割 public void split() { long beginPos = 0; //起始点 long actualBlockSize = this.blockSize; //计算所有块的大小、位置、索引 for (int i = 0; i < size; i++) { if (i == size - 1) { //最后一块 actualBlockSize = fileLength - beginPos; } splitDetail(i, beginPos, actualBlockSize); beginPos += actualBlockSize; //本次的终点,下一次的起点 } } private void splitDetail(int idx, long beginPos, long actualBlockSize) { //1.创建源 File src = new File(this.filePath); File dest = new File(this.blockPath.get(idx)); //2.选择流 RandomAccessFile raf = null; //输入流 BufferedOutputStream bos = null; //输出流 try { raf = new RandomAccessFile(src, "r"); bos = new BufferedOutputStream(new FileOutputStream(dest)); //读取文件 raf.seek(beginPos); byte[] flush = new byte[1024]; int len = 0; while (-1 != (len = raf.read(flush))) { if (actualBlockSize - len >= 0) { //查看是否足够 //写出 bos.write(flush, 0, len); actualBlockSize -= len; //剩余量 } else { //写出最后一次的剩余量 bos.write(flush, 0, (int) actualBlockSize); break; } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { bos.close(); raf.close(); } catch (IOException e) { e.printStackTrace(); } } } /*合并文件 * */ public void mergeFile(String destPath) { //创建源 File dest = new File(destPath); //选择流 BufferedOutputStream bos = null;//输出流 try { bos = new BufferedOutputStream(new FileOutputStream(dest, true));//追加文件 BufferedInputStream bis = null; for (int i = 0; i < this.blockPath.size(); i++) { bis = new BufferedInputStream(new FileInputStream(new File(this.blockPath.get(i)))); byte[] flush = new byte[1024]; int len = 0; while (-1 != (len = bis.read(flush))) { bos.write(flush,0,len); } bos.flush(); bis.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } /*合并文件 * */ public void merge(String destPath) { //创建源 File dest = new File(destPath); //选择流 BufferedOutputStream bos = null; //输出流 SequenceInputStream sis =null;//输入流 //创建一个容器 Vector<InputStream> v = new Vector<>(); try { for (int i = 0; i < this.blockPath.size(); i++) { v.add(new BufferedInputStream(new FileInputStream(new File(this.blockPath.get(i))))); } bos = new BufferedOutputStream(new FileOutputStream(dest, true));//追加文件 sis = new SequenceInputStream(v.elements()); byte[] flush = new byte[1024]; int len = 0; while (-1 != (len = sis.read(flush))) { bos.write(flush,0,len); } bos.flush(); sis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { SplitFile file = new SplitFile("/home/deepin/Desktop/test/print.txt","/home/deepin/Desktop/test" ,50); //System.out.println(file.size); //file.split(); file.merge("/home/deepin/Desktop/test/merge2"); } }
7.IO总结
一、步骤:创建源 选择流 操作(读取|写出)释放
二、流
三、重点
四、操作
0.打印文件|目录
1.文件拷贝
2.关闭流方法
3.文件分割与合并