- 流的概念:
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
- 字符流和字节流的区别:
(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的;而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件,我们将在下面验证这一点。
结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。
- IO流类图结构
- 字符流
处理字符类型文件(用记事本可以直接打开,正常显示)
字符输入|输出流
Reader 输入流
BufferReader 带缓冲区的输入流
Buffered 凡是带Buffered的都是带缓冲区,实现原理利用数组实现。
实现
方法:
readLine(); 按行读取
Writer 输出流
PrintWriter 输出流
方法:
println("打雷啦!下雨啦!回家收衣服啦!");
writer("\n\r"); 换行
- InputStreamReader 字节流与字符流转换
构造器:
Reader=InputStreamReader(InputStream is);
- 无论何种情况,外部资源流必须都关闭
Ctrl+T 查找该类所拥有子类
- 字节流
InputStream 是所有的输入字节流的父类,它是一个抽象类。
ByteArrayInputStream、
StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte
数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数 - 将一个文件夹里的文件复制到另一个文件夹
/** * @param oldFile * 被拷贝的文件夹 * @param copyFile * 拷贝文件存放的文件夹 */ public void copyFile(String oldString, String copyString) { File oldFile = new File(oldString); File copyFile = new File(copyString); BufferedReader br = null; // 用bufferWriter只能复制一个文件? File[] dirFile = oldFile.listFiles(); PrintWriter bw = null; for (int i = 0; i < dirFile.length; i++) { try { br = new BufferedReader(new FileReader(dirFile[i])); bw = new PrintWriter(new FileWriter(copyString + "/" + dirFile[i].getName())); String str = null; while ((str = br.readLine()) != null) { // 中文乱码: bw.println(str); bw.flush(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if(bw!=null) bw.close(); if(br!=null) br.close(); } catch (IOException e) { e.printStackTrace(); } } } }
9.读取属性文件
/** * 读取属性文件 */ public void getPropertiesFile(){ Properties prop=new Properties(); File file=new File("user.properties"); InputStream is; try { is=new FileInputStream(file); prop.load(is); String username=prop.getProperty("username"); System.out.println(username); } catch (IOException e) { e.printStackTrace(); } }
10.写属性文件
/** * 写属性文件 */ public void setProperties(){ Properties prop=new Properties(); try { FileOutputStream fos=new FileOutputStream("test.properties"); prop.setProperty("001", "第一名"); prop.setProperty("002", "第二名"); prop.setProperty("003", "第三名"); prop.store(fos, "我是注释,请注意!以#开头!"); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
11.实现对属性文件的增、改操作
package com.mig.jbs.io; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.Properties; import java.util.Scanner; public class PropertiesFileCRUD { static Properties prop = new Properties(); static Scanner sc = new Scanner(System.in); static File file = new File("test.properties"); static String username; static String password; static boolean b; //循环判断属性文件是否存在相同的键 public boolean loopCompare(){ FileInputStream fis; b=false; try { fis=new FileInputStream(file); prop.load(fis); @SuppressWarnings("unchecked") //返回属性列表中所有键的枚举 Enumeration enu=prop.propertyNames(); //测试此枚举中是否包含更多的元素,如果 while(enu.hasMoreElements()){ String name=(String) enu.nextElement(); //判断属性列表中是否已经包含了此键 if(username.equals(name)){ b=true; System.out.println(password); } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return b; } //分割用户输入数据,得到属性文件数据 public String[] propertiesSplit(String input){ System.out.println(input); String[] str=input.split("="); username=str[0]; password=str[1]; return str; } // 创建新的属性文件数据 public void doCreate() { try { FileOutputStream fos=new FileOutputStream(file); prop.setProperty(username, password); prop.store(fos, null); fos.close(); System.out.println("用户添加成功!"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // 更新属性表 public void doUpdate() { try { FileOutputStream fos=new FileOutputStream(file); prop.setProperty(username, password); prop.store(fos, null); fos.close(); System.out.println("用户信息更新成功!"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //输入属性文件数据 public void init() { String input=sc.nextLine(); if(input.equals(-1)){ System.exit(0); }else{ propertiesSplit(input); loopCompare(); if(b){ doUpdate(); }else{ doCreate(); } init(); } } public static void main(String[] args) { System.out.println("如果你要退出程序请输入-1"); System.out.println("如果你需要添加或修改用户信息请按格式XXXX=XXXXX"); System.out.println("请输入你要输入的信息"); PropertiesFileCRUD pfc=new PropertiesFileCRUD(); pfc.init(); } }
12.将文件分割成指定份数,并将分割后的文件合并
public class SplitFileDemo { /** * @param oldFile 要分割的文件 * @param per 要分割的份数 * @param newFile 分割后的文件 */ public void splitFile(File oldFile,int per,File newFile){ try { FileInputStream fis=new FileInputStream(oldFile); System.out.println(newFile.toString()); //被分割文件的长度 long totalSize=oldFile.length(); //分割的每一份长度 long splitSize=totalSize/per; String suffix=suffixFile(oldFile); byte[] buff=new byte[1024]; int len,sum; for (int i = 1; i <=per; i++) { sum=0; FileOutputStream fos=new FileOutputStream(newFile.toString()+i+"."+suffix); if(i==per){ splitSize=totalSize-splitSize*(i-1); } while((len=fis.read(buff))!=-1){ sum=len+sum; fos.write(buff, 0, len); if(sum>=splitSize){ break; } } } //文件合并 FileInputStream fis2 = null; FileOutputStream fos2 = new FileOutputStream("c:/"+oldFile.getName()); for (int i = 1; i <=per; i++) { fis2 = new FileInputStream(newFile.toString()+i+"."+suffix); while ((len = fis2.read(buff)) != -1) { fos2.write(buff, 0, len); } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * @param file 获取文件的后缀名 */ public String suffixFile(File file){ String filename=file.getName(); int index=filename.lastIndexOf("."); String suffix=filename.substring(index+1); return suffix; }