五、 Java IO
1. IO
1. java.io 包中几乎包含了所有操作输入、输出所需要的类 2. 一个流可以理解为一个数据的序列 3. 输入流表示从一个源读取数据,输出流表示向一个目标写数据 4. 字节流和字符流: 1)字节流:二进制,可处理一切文件(纯文本、音频、视频等) 2)字符流:纯文本,只能处理纯文本
5. 字节流、字符流与文件 1)字节流: 输入流:InputStream is = new FileInputStream(File file);
is.read(byte[] bt);// 从源中读取 bt.length 长度的字节并赋给数组 bt;返回读取的字节数;如果是文件结尾则返回 -1 输出流:OutputStream os = new FileOutputStream(File file, boolean append);
os.write(byte[] bt);// 将 bt 数组中 bt.length 长度的字节写入到目标中
2)字符流: 输入流:Reader reader = new FileReader(File file);
reader.read(char[] ch); // 从源中读取 ch.length 长度的字符并赋给数组 ch;返回读取的字符数;如果是文件结尾则返回 -1
输出流:Writer writer = new FileWriter(File file, boolean append);
writer.write(char[] ch);// 将 ch 数组中 ch.length 长度的字符写入到目标中
writer.append(CharSequence csq);// 追加字符序列,底层实现:writer.write(csq.toString());返回 Writer 6. 缓冲流:增加缓冲功能,避免频繁读写硬盘,提高性能 1)字节缓冲流 输入流:new BufferedInputStream(InputStream in); 输出流:new BufferedOutputStream(OutputStream out); 2)字符缓冲流 输入流:BufferedReader br = new BufferedReader(Reader in);
子类新增方法:br.readLine();// 无参数,行读取,返回 String 类型,如果是文件结尾则返回 null;不能发生多态
输出流:BufferedWriter bw = new BufferedWriter(Writer out);
子类新增方法:br.newLine();// 无参数,相当于一个换行符,无返回类型;不能发生多态
7. 转换流:字节流转为字符流 1)编码与解码概念 编码:字符 --编码字符集--> 二进制 解码:二进制 --解码字符集--> 字符
byte[] data = "中国".getBytes("gbk");// 编码 char-->byte
String str = new String(data, "gbk");// 解码 byte-->char,与编码字符集统一,否则出现乱码 2)乱码 a.编码与解码的字符集不统一 b.字节缺少,长度丢失 3)转换流 a.输出流(写入),编码 OutputStreamWriter(OutputStream out, String charsetName); b.输入流(读取),解码 InputStreamReader(InputStream in, String charsetName);
8. 使用 1)创建 src 或 dest 2)选择流 3)操作流 4)释放资源 close();
9. 控制台
1)键盘输入
Scanner sc = new Scanner(System.in);
2)文件输入
InputStream is = new BufferedInputStream(new FileInputStream(src)); Scanner sc = new Scanner(is);
3)输出到控制台
System.out.println("hello, world");
4)输出到指定文件
PrintStream ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(dest))); ps.println("hello, world");
5)错误样式输出
System.err.println();
6)重定向
System.setIn(InputStream in);
System.setOut(PrintStream out);
System.setOut(new PrintStream(OutputStream out, boolean autoFlush)); System.out.println("控制台-->文件");
System.setErr(PrintStream err);
7)回到控制台:FileDescriptor.out
System.setOut(new PrintStream(FileDescriptor.out, boolean autoFlush)); System.out.println("控制台")
public class CopyDirectory { //拷贝文件夹 public static void copyDir(File src, File dest){ if(src.isDirectory()){ //父类文件夹不能拷贝到子类中 if(dest.getAbsolutePath().contains(src.getAbsolutePath())){ return; } } copyFileDetail(src, dest); } //拷贝细节 private static void copyFileDetail(File src, File dest) { if(src.isFile()){//文件 copyFile(src, dest); }else if(src.isDirectory()){//文件夹 dest.mkdirs(); //获取下一级文件|目录 for(File sub : src.listFiles()){ copyFileDetail(sub, new File(dest, sub.getName())); } } } private static void copyFile(File src, File dest) { //2.选择流 InputStream is = null; OutputStream os = null; try { is = new BufferedInputStream(new FileInputStream(src)); os = new BufferedOutputStream(new FileOutputStream(dest)); //3.文件拷贝 循环+读取+写出 byte[] bt = new byte[1024]; int len = 0; while(-1!=(len=is.read(bt))){ os.write(bt, 0, len); } os.flush(); } 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("文件关闭失败"); } } if(null!=os){ try { os.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("文件关闭失败"); } } } } }
public class Convert { public static void main(String[] args) throws IOException { //编码 BufferedWriter or = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( new File("E:/test/a.txt")), "gbk" ) ); String off = "转换流:字节流转为字符流"; or.write(off); or.flush(); //解码 BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream( new File("E:/test/a.txt")), "gbk" ) ); String info = null; while(null!=(info=br.readLine())){ System.out.println(info); } } }
public class SplitFile { //文件名 private String fileName; //文件路径 private String filePath; //文件大小 private long length; //块数 private int size; //每一块的大小 private long blockSize; //每块的名称 private ListblockPath; public SplitFile(){ this.blockPath = new ArrayList (); } public SplitFile(String filePath){ this(filePath, 1024); } public SplitFile(String filePath,long blockSize){ this(); this.filePath = filePath; this.blockSize = blockSize; init(); } private void init() { File src = null; src=new File(filePath); //健壮性 if(null==filePath || !src.exists()){ return; } if(src.isDirectory()){ return; } //文件名 this.fileName = src.getName(); //计算块数,是实际大小,每块大小 this.length = src.length(); //修正最后一块大小 if(this.blockSize>length){ this.blockSize=length; } //确定块数 this.size = (int)Math.ceil(length*1.0/this.blockSize); } private void initPathName(String destPath){ for(int i=0;i<this.size;i++){ String original = this.fileName.substring(0, this.fileName.lastIndexOf(".")); String tail = this.fileName.substring(this.fileName.lastIndexOf(".")); this.blockPath.add(destPath+"/"+original+"_Part"+i+tail); } } /** * 文件分割 * @param destPath 分割文件的存放 目录 */ public void split(String destPath){ //确定文件路径 initPathName(destPath); long beginPos = 0;//起始点 long actualBlockSize = this.blockSize;//实际大小 //计算所有块的大小,位置,索引 for(int i=0; i<this.size; i++){ if(i==size-1){//最后一块 actualBlockSize = this.length - beginPos; } splitDetail(i, beginPos, actualBlockSize); beginPos += actualBlockSize; } } public void splitDetail(int index, long beginPos, long actualBlockSize){ //文件的拷贝 //1.创建源 File src = new File(this.filePath);//源文件 File dest = new File(this.blockPath.get(index));//目标文件 //2.选择流 RandomAccessFile raf = null; BufferedOutputStream bos = null; try { raf = new RandomAccessFile(src, "r"); bos = new BufferedOutputStream(new FileOutputStream(dest)); //3.从指定位置开始读取文件 raf.seek(beginPos); //缓冲区 byte[] bt = new byte[1024]; //接收长度 int len = 0; while(-1!=(len=raf.read(bt))){ if(actualBlockSize-len>0){//如果每块的实际大小大于 1024 个字节数,则继续循环 bos.write(bt, 0, len); actualBlockSize -= len;//剩余量 }else{//写出最后一次的剩余量 bos.write(bt, 0, (int)actualBlockSize); break; } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ if(null!=raf && null!=bos){ try { raf.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 文件合并 */ public void mergeFile(String destPath){ //创建源 File dest = new File(destPath); //选择流 BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bos = new BufferedOutputStream(new FileOutputStream(dest,false)); for(int i=0;i<this.blockPath.size();i++){ bis = new BufferedInputStream( new FileInputStream(new File(this.blockPath.get(i))) ); //缓冲区 byte[] bt = new byte[1024]; //接收长度 int len = 0; while(-1!=(len=bis.read(bt))){ bos.write(bt,0,len); } bos.flush(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ if(null!=bis && null!=bos){ try { bis.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 合并02 */ public void mergeFile02(String destPath){ //1.创建源 File dest = new File(destPath); //选择流 SequenceInputStream sis = null;//输入流 BufferedOutputStream bos = null;//输出流 //创建容器 Vector vi = new Vector (); try { bos = new BufferedOutputStream(new FileOutputStream(dest,false)); for(int i=0;i<this.blockPath.size();i++){ vi.add(new BufferedInputStream( new FileInputStream(new File(this.blockPath.get(i))) )); } sis = new SequenceInputStream(vi.elements()); //缓冲区 byte[] bt = new byte[1024]; //接收长度 int len = 0; while(-1!=(len=sis.read(bt))){ bos.write(bt,0,len); } bos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ if(null!=sis && null!=bos){ try { sis.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * main */ public static void main(String[] args) { SplitFile file = new SplitFile("E:/test/k.txt", 50); System.out.println(file.size); file.split("E:/test"); file.mergeFile("E:/test/k02.txt"); file.mergeFile02("E:/test/k03.txt"); } }
public class CloseUtil { /** * 工具类关闭流 * 可变参数: ... 只能在形参最后一个位置,处理方式和数组一致 * @param io */ public static void close(Closeable ...io){ for(Closeable temp:io){ if(null!=temp){ try { temp.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 泛型方法的关闭流 * @param io */ public staticextends Closeable> void closeAll(T ...io){ for(Closeable temp:io){ if(null!=temp){ try { temp.close(); } catch (IOException e) { e.printStackTrace(); } } } } }