IO流:
01.File
创建文件
//创建文件夹 private static void mkdirs() { System.out.println("请您输入创建的文件夹名称:(默认是E:/)"); String fileName = input.next(); //创建File对象 File file=new File("E:/"+fileName); if (file.mkdirs()){ System.out.println("创建成功"); }else{ System.out.println("创建失败"); } }
//创建文件
private static void createNewFile() { System.out.println("请您输入文件的名称:(默认是E:/)"); String fileName = input.next(); //创建File对象 File file=new File("E:/"+fileName); if (file.exists()){ //文件已经存在 System.out.println("该文件已经存在!"); }else{ try { boolean flag= file.createNewFile(); if (flag){ System.out.println("文件创建成功!"); }else{ System.out.println("文件创建失败!"); } } catch (IOException e) { e.printStackTrace(); } } }
删除文件
//修改文件
private static void updateFile() { System.out.println("请您输入需要修改文件的名称:(默认是E:/)"); String oldFileName = input.next(); System.out.println("请您输入文件的新名称:(默认是E:/)"); String newFileName = input.next(); //创建File对象 File oldFile=new File("E:/"+oldFileName); File newFile=new File("E:/"+newFileName); if(oldFile.renameTo(newFile)){ System.out.println("修改成功"); }else{ System.out.println("修改失败"); } }
修改文件
//修改文件 private static void updateFile() { System.out.println("请您输入需要修改文件的名称:(默认是E:/)"); String oldFileName = input.next(); System.out.println("请您输入文件的新名称:(默认是E:/)"); String newFileName = input.next(); //创建File对象 File oldFile=new File("E:/"+oldFileName); File newFile=new File("E:/"+newFileName); if(oldFile.renameTo(newFile)){ System.out.println("修改成功"); }else{ System.out.println("修改失败"); } }
显示文件信息
// 查询文件夹下所有的文件列表 private static void findFileList() { System.out.println("请您输入查询的文件夹名称:(默认是E:/)"); String fileName = input.next(); //创建File对象 File file=new File("E:/"+fileName); File[] files = file.listFiles(); int dirNums=0; int fileNums=0; //遍历集合 for (File f:files){ if (f.isDirectory()){ dirNums++; } if (f.isFile()){ fileNums++; System.out.println(f.getName()); } } System.out.println("有多少个文件夹?"+dirNums); System.out.println("有多少个文件?"+fileNums); }
02.字节流
InputStream(输入) OutputStream(输出) 基类 都不能实例化 public static void main(String[] args) { //创建输入流和输出流对象 InputStream inputStream=null; OutputStream outputStream=null; try { inputStream=new FileInputStream("e:/a.txt"); // true 代表是否向文件中拼接,不删除之前的内容 outputStream=new FileOutputStream("e:/a.txt",true); //先向文件写入内容 outputStream.write("54321".getBytes()); //outputStream.flush(); 自己没有实现 // read 方法将返回0-255之间的数字 如果流读到了最后,将返回-1 int num=0; while ((num=inputStream.read())!=-1){ System.out.println((char)num); } } catch (Exception e) { e.printStackTrace(); }finally { try { inputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } }
03.字符流
Reader Writer
public static void main(String[] args) { //创建输入和输出流 Reader reader=null; Writer writer=null; try { reader=new FileReader("e:/a.txt"); writer=new FileWriter("e:/a.txt",true); writer.write("大家辛苦了1111!"); writer.flush(); // 清空缓冲区 writer.write("大家辛苦了4444!"); writer.close(); //读取 // 创建一次性读取多少个字符 char [] data=new char[1024]; int num=0; StringBuffer sb=new StringBuffer(); while((num=reader.read(data))!=-1) { sb.append(data); } System.out.println(sb.toString()); } catch (Exception e) { e.printStackTrace(); }finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } }
04.缓冲流
BufferReader BufferWriter 不单独使用
一般和Reader Writer 联用 在debug的情况下能看清楚Flush的作用
public static void main(String[] args) { //创建输入和输出流 Reader reader=null; Writer writer=null; BufferedReader br=null; BufferedWriter bw=null; try { writer=new FileWriter("e:/a.txt",true); bw=new BufferedWriter(writer); //封装 bw.write("大家辛苦了!"); bw.newLine(); //换行 bw.write("大家别眨眼!"); bw.flush(); bw.write("大家别眨眼22!"); bw.write("大家别眨眼33!"); bw.close(); writer.close(); //如果不关闭 后续两句话没法获取 //读取 reader=new FileReader("e:/a.txt"); br=new BufferedReader(reader);//封装 String line=null; StringBuffer sb=new StringBuffer(); while ((line=br.readLine())!=null){ sb.append(line); } System.out.println(sb.toString()); } catch (Exception e) { e.printStackTrace(); }finally { try { br.close(); reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
05.二进制流
DataInputStream DataOutputStream
不单独使用 一般需要与 InputStream OutputStream 联用
public static void main(String[] args) { //创建输入流和输出流对象 InputStream inputStream=null; OutputStream outputStream=null; DataInputStream dis=null; DataOutputStream dos=null; try { //获取了输入流 猫咪进内存了 inputStream=new FileInputStream("e:/dog.jpg"); dis=new DataInputStream(inputStream); //获取输出流 outputStream=new FileOutputStream("e:/u1/cat.jpg"); dos=new DataOutputStream(outputStream); //先读取 int num=0; while ((num=dis.read())!=-1){ dos.write(num); //复制 } } catch (Exception e) { e.printStackTrace(); }finally { //释放资源 try { dos.close(); dis.close(); outputStream.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
06.序列化和反序列化
ObjectInputStream ObjectOutputStream
序列化:序列化(Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。
持久化:持久化是将程序数据在持久状态和瞬时状态间转换的机制。
注意 实体类需要接口Serializable 要不然无法序列化
static Scanner input=new Scanner(System.in); //创建需要的输入和输出流对象 static InputStream inputStream=null; static OutputStream outputStream=null; static ObjectInputStream objectInputStream=null; static ObjectOutputStream objectOutputStream=null; public static void main(String[] args) { //注册 序列化 //register(); //登录 反序列化 login(); } //注册 private static void register() { User user=new User(); System.out.println("请输入您的用户名:"); user.setUserName(input.next()); System.out.println("请输入您的密码:"); user.setPassword(input.next()); try { outputStream=new FileOutputStream("e:/user.txt"); objectOutputStream=new ObjectOutputStream(outputStream); //把对象输出到文件中 objectOutputStream.writeObject(user); } catch (Exception e) { e.printStackTrace(); }finally { try { objectOutputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } //登录 private static void login() { try { inputStream=new FileInputStream("e:/user.txt"); objectInputStream=new ObjectInputStream(inputStream); //读取对象 User user= (User) objectInputStream.readObject(); System.out.println(user); } catch (Exception e) { e.printStackTrace(); }finally { try { objectInputStream.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
NIO:
非堵塞io 全称new io
Java NIO: Channels and Buffers(通道和缓冲区)
为了理解Buffer的工作原理,需要熟悉它的三个属性:
- capacity
- position
- limit
position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的。
这里有一个关于capacity,position和limit在读写模式中的说明,详细的解释在插图后面。
capacity
作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
position
当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.
当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
limit
在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
Buffer的分配
要想获得一个Buffer对象首先要进行分配。 每一个Buffer类都有一个allocate方法。下面是一个分配48字节capacity的ByteBuffer的例子。
|
|
这是分配一个可存储1024个字符的CharBuffer:
|
|
向Buffer中写数据
写数据到Buffer有两种方式:
- 从Channel写到Buffer。
- 通过Buffer的put()方法写到Buffer里。
从Channel写到Buffer的例子
|
|
通过put方法写Buffer的例子:
|
|
put方法有很多版本,允许你以不同的方式把数据写入到Buffer中。例如, 写到一个指定的位置,或者把一个字节数组写入到Buffer。 更多Buffer实现的细节参考JavaDoc。
flip()方法
flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。
换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。
从Buffer中读取数据
从Buffer中读取数据有两种方式:
- 从Buffer读取数据到Channel。
- 使用get()方法从Buffer中读取数据。
从Buffer读取数据到Channel的例子:
1 |
|
使用get()方法从Buffer中读取数据的例子
|
|
01他是基于缓冲区对数据进行读取或者是写入
02通道是双向的,流是单向的
03可以异步的读写
常用的实现
1.Filechannel:从文件中读写数据
2.DatagrarmChannel:通过UDP读写网络中的数据Udp:不安全 非链接 快
3.SocketChannel:通过TCp读写网络中的数据 Tcp: 安全 链接 慢
4.serverSocketChannel:可以监听新来的Tcp链接,每进来一个都会创建一个新的serverSocketChannel
内存映射
就是把文件映射到电脑的内存中,通过操作内存从而到达操作文件的目的
内存中操作速度是最快的!
Java中的读取文件方式
1.RandomAccessFile 随机读取,速度最慢 可以设置读写
2.FileInputStream 流的方式读取
3.BufferReader 缓存的方式读取
4.MappedByteBuffer 内存映射,速度最快
内存映射的三种模式 :MapMode
- READ_ONLY :对缓冲区的内容只读
- READ_WRITE :对缓冲区的内容读写
- PRIVATE: 只会对缓冲区的内容修改,不会影响到真实文件
通常适用于文件的读取! 一般不会涉及到文件袋写入
文件锁
- FileLock 基于FIleChannel对文件提供锁的功能!
- 共享锁 共享读的操作 只能有一个写的操作 适合读取数据
为了防止其他线程使用独占锁
- 独占锁 读写不能同时 只能一个读或者写 适合写数据
Lock(); 没有参数的是独占锁 有参数的是共享锁也有可能是独占锁
Nio:将buffer写入 Channel
public static void main(String[] args) { System.out.println("d"); //创建数组 String[] bytee = {"dd", "dd", "dd"}; //创建文件对象 自动创建 File file = new File("d:/a.txt"); // 创建输出流对象 FileOutputStream fos = null; // 创建管道对应的实现类 FileChannel fileChannel = null; try { fos = new FileOutputStream(file); // 获取管道 fileChannel = fos.getChannel(); // 创建缓冲区 ByteBuffer buffer = ByteBuffer.allocate(1024); // 循环出数组的数据 for (String s : bytee) { // 将训话你的数据写缓冲区 System.out.println(s.getBytes() ); buffer.put(s.getBytes()); } // 从写模式切换读模式 buffer.flip(); // 正在的写入 fileChannel.write(buffer); } catch (Exception e) { e.printStackTrace(); } finally { try { fileChannel.close(); fos.close(); } catch (Exception e) { e.printStackTrace(); } } }
Nio2:将文件内容复制到另一个文件里面
//从文件a到文件b传数据 public static void main(String[] args) { //创建需要的两个文件 File afile = new File("d:/a.txt"); File bfile = new File("d:/b.txt"); // 创建输出流对象 FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; // 创建管道对应的实现类 FileChannel inputchannel = null; FileChannel outputchannel = null; try { fileInputStream = new FileInputStream(afile); fileOutputStream = new FileOutputStream(bfile); // 获取管道 inputchannel = fileInputStream.getChannel(); outputchannel = fileOutputStream.getChannel(); // 创建缓冲区 ByteBuffer buffer = ByteBuffer.allocate(1024); // 从写模式切换读模式 int num = 0; while ((num = inputchannel.read(buffer)) != -1) { // 切换模式 buffer.flip(); //写入到b文件里面 outputchannel.write(buffer); //清空缓存区 buffer.clear(); System.out.println(buffer); System.out.println(num); } // 正在的写入 } catch (Exception e) { e.printStackTrace(); } finally { try { inputchannel.close(); outputchannel.close(); fileInputStream.close(); fileOutputStream.close(); } catch (Exception e) { e.printStackTrace(); } } }
Nio3:比较内存映射和io的时间
public static void main(String[] args) { FileChannel channel = null; try { // 找打指定的文件并且设置读写模式 RandomAccessFile file = new RandomAccessFile("d:/a.txt", "rw"); //创建管道 channel = file.getChannel(); MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); ByteBuffer byteBuffer1 = ByteBuffer.allocate(1204); byte[] bytes = new byte[1024]; long length = file.length(); long beginTime = System.currentTimeMillis(); for (int i = 0; i < length; i += 1024) { if (length - i > 1024) { buffer.get(bytes); } else { buffer.get(new byte[(int) (length - i)]); } } long endTime = System.currentTimeMillis(); System.out.println("使用内存映射时间" + (endTime - beginTime)); System.out.println("-------------------------------------------------------"); beginTime = System.currentTimeMillis(); while (channel.read(byteBuffer1) > 0) { byteBuffer1.flip(); byteBuffer1.clear(); } endTime = System.currentTimeMillis(); System.out.println("使用普通io时间" + (endTime - beginTime)); } catch (Exception e) { e.printStackTrace(); } }