JAVA

File、输入、输出流、对象序列化
2、知识点
2.1、上次课程的主要知识点
 1、 String与StringBuffer的区别
  • String一旦声明之后内容不可改变,可以直接赋值,连接可以用+号
  • StringBuffer的内容可以改变,必须实例化之后赋值
 2、 Class类的作用
  • Class表示反射机制,表示一切类的组成
 • 通过Class.forName()可以找到一个类,之后通过newInstance()实例化,但是要求使用此种方式的时候类中必须存在无参构造方法。
 3、 比较器 —— Comparable
  • 用于为一个对象进行排序操作
 4、 日期操作类:
  • SimpleDateFormat ? Date ?日期显示
 5、 正则表达式:
  • 验证字符串的组成
  • 拆分、替换
 6、 使用正则验证email地址
public class RegDemo{
 public static void main(String args[]){
  String str = "a@aa.com.cn" ;
  // com com.cn cn net net.cn org edu
  System.out.println(str.matches("//w+@//w+.((com)|(com.cn)|(cn)|(net)|(net.cn)|(org)|(edu))")) ;
 }
};
2.2、本次预计讲解的知识点
 1、 File类的作用及使用
 2、 字节输入流/字节输出流、字符输入流/字符输出流
 3、 内存操作流
 4、 打印流
 5、 对象序列化
3、具体内容
 在整个JAVA中所有的文件操作都是使用java.io包完成的,此包中包含了各种操作的类及接口。
 IO包中有以下几个主要部分组成:
  • 表示与文件本身的操作:File
  • IO的输入、输出类
  • 对象序列化
3.1、File类(重点)
 在整个IO包中,File类是唯一表示文件本身的,即:文件的创建、删除、存在与否的判断。
 File类在使用的时候需要指定操作的文件路径,构造方法:
  • public File(String pathname)
例如:现在使用File类在硬盘上创建一个新的文件(e:/abc.txt)
 • 创建文件的方法:public boolean createNewFile() throws IOException
import java.io.* ;
public class IODemo01{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://abc.txt") ;
  try{
   System.out.println(f.createNewFile()) ;
  }catch(Exception e){}
 }
};
例如:删除在硬盘上建立好的文件
 • 删除文件的方法:public boolean delete()
import java.io.* ;
public class IODemo02{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://abc.txt") ;
  // 删除文件
  f.delete() ;
 }
};
 但是以上有一个问题,至少文件存在之后才可以删除。证明,在删除之前需要先判断此文件是否存在,判断语法:public boolean exists():
import java.io.* ;
public class IODemo03{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://abc.txt") ;
  if(f.exists()){
   // 删除文件
   f.delete() ;
  }
 }
};
例如:要求完成以下的功能
 • 如果文件存在则删除,如果文件不存在则创建
import java.io.* ;
public class IODemo04{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://abc.txt") ;
  if(f.exists()){
   // 删除文件
   f.delete() ;
  }else{
   try{
    f.createNewFile() ;
   }catch(Exception e){}
  }
 }
};
 发现此种操作并不是立刻生效的,有一定时间的延迟。
注意:
 如果在程序中直接输出File类的对象,则会打印路径名称。
import java.io.* ;
public class IODemo05{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://abc.txt") ;
  System.out.println(f) ;
 }
};
 输出结果:
e:/abc.txt
例如:要求列出一个目录下的所有内容
 方法名称如下:
• public String[] list():只列出了所有的文件夹或文件的名称,不是绝对路径
• public File[] listFiles():取得的是绝对路径
A、使用list()方法操作:
import java.io.* ;
public class IODemo06{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://") ;
  String s[] = f.list() ;
  for(int i=0;i<s.length;i++){
   System.out.println(s[i]) ;
  }
 }
};
B、使用listFiles()方法操作
import java.io.* ;
public class IODemo07{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://") ;
  File fs[] = f.listFiles() ;
  for(int i=0;i<fs.length;i++){
   System.out.println(fs[i]) ;
  }
 }
};
例如:区分一个给定的路径是文件还是文件夹
 • 方法名称:public boolean isDirectory()
import java.io.* ;
public class IODemo08{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://") ;
  System.out.println(f.isDirectory()) ;
 }
};
思考:
 任意给定一个路径,要求把此路径下的所有文件包括各个子文件夹的文件全部列出。
 • 思路:
  |- 通过给定的路径判断是否是一个文件夹
  |- 如果是一个文件夹,则继续列出里面的内容
  |- 之后再将此文件夹里面的内容继续判断,观察是否是目录
import java.io.* ;
public class IODemo09{
 public static void main(String args[]){
  // 告诉系统准备操作这样的一个文件
  File f = new File("e://") ;
  print(f) ;
 }
 public static void print(File f){
  if(f.isDirectory()){
   File files[] = f.listFiles() ;
   try{
    for(int i=0;i<files.length;i++){
     // 如果还有子文件夹,则肯定继续列出
     print(files[i]) ;
    }
   }catch(Exception e){}
  }else{
   System.out.println(f) ;
  }
 }
};
3.2、RandomAccessFile类(了解)
 RandomAccessFile:实现随机访问,可以在文件之中跳转。
 在保存内容的时候,必须指定内容的长度。
现在向文件之中写入如下数据:
 • zhangsan 30
 • lisi  31
 • wangwu 32
例如:通过RandomAccessFile类向文件中保存内容
 • 构造方法:public RandomAccessFile(File file,String mode) throws FileNotFoundException
  |- String mode:表示的是文件的打开模式:
   |- 只读:r,但是使用此种方式的时候必须保证文件存在。
 |- 读写:rw,使用此种方式的时候,向文件中写入数据,如果文件不存在,则会自动创建一个新的文件出来
 • 向文件中写数据:
  • 向文件中写入字符串:public final void writeBytes(String s) throws IOException
  • 向文件中写入数字:public final void writeInt(int v) throws IOException
 • 文件操作之后必须关闭:
  • 关闭:public void close() throws IOException
利用以上方法完成文件的写入,可是写的时候,必须注意,所有的内容长度必须固定。
import java.io.* ;
public class IODemo10{
 public static void main(String args[]) throws Exception{
  File f = new File("e:"+File.separator+"hello.txt") ;
  RandomAccessFile raf = null ;
  // 如果文件不存在,则会自动创建一个
  raf = new RandomAccessFile(f,"rw") ;
  String name = null ;
  int age = 0 ;
  name = "zhangsan" ;
  age = 30 ;
  raf.writeBytes(name) ;
  raf.writeInt(age) ;
  name = "lisi    " ;
  age = 31 ;
  raf.writeBytes(name) ;
  raf.writeInt(age) ;
  name = "wangwu  " ;
  age = 32 ;
  raf.writeBytes(name) ;
  raf.writeInt(age) ;
  raf.close() ;
 }
};
例如:通过RandomAccessFile取出里面的内容
 • 因为是读,所以可以使用只读的方式打开文件:r
 • 读字符串:public final byte readByte() throws IOException
  |- 使用byte的方式读取进来
 • 读数字:public final int readInt() throws IOException
 • 跳过指定长度的内容:public int skipBytes(int n) throws IOException
 • 跳回位置:public void seek(long pos) throws IOException
import java.io.* ;
public class IODemo11{
 public static void main(String args[]) throws Exception{
  File f = new File("e:"+File.separator+"hello.txt") ;
  RandomAccessFile raf = null ;
  // 如果文件不存在,则会自动创建一个
  raf = new RandomAccessFile(f,"r") ;
  String name = null ;
  int age = 0 ;
  byte b[] = new byte[8] ;
  // 跳过第一个人的信息
  raf.skipBytes(12) ;
  for(int i=0;i<b.length;i++){
   b[i] = raf.readByte() ;
  }
  age = raf.readInt() ;
  name = new String(b) ;
  System.out.println("姓名:" + name) ;
  System.out.println("年龄:" + age) ;
  raf.seek(0) ;
  for(int i=0;i<b.length;i++){
   b[i] = raf.readByte() ;
  }
  age = raf.readInt() ;
  name = new String(b) ;
  System.out.println("姓名:" + name) ;
  System.out.println("年龄:" + age) ;
  raf.close() ;
 }
};
3.3、字节流、字符流操作类(重点)
 文件操作的基本流程:
  1、 通过File类找到一个文件
  2、 通过File类去实例化字节流、字符流操作类
  3、 进行读或写的操作,在写的时候如果文件不存在则会自动创建
  4、 关闭文件
3.3.1、字节流
 在字节流中分为两种:
  • 输出流:OutputStream
  • 输入流:InputStream
例如:向文件之中打印一个“Hello World!!!”。
 • 肯定使用输出流。
  |- 定义:public abstract class OutputStream extends Objec timplements Closeable, Flushable
 • OutputStream子类:FileOutputStream
  |- 构造方法:public FileOutputStream(File file) throws FileNotFoundException
 • 输出方法:public void write(byte[] b) throws IOException
|- 可以发现只能写出一个byte数组,那么现在是一个字符串,如果要想使用此种方式,需要将一个字符串变为一个byte数组,String中的方法:public byte[] getBytes() 。
 • 关闭:public void close() throws IOException
import java.io.* ;
public class IODemo12{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  OutputStream out = null ;
  try{
   // 通过子类实例化
   out = new FileOutputStream(f) ;
  }catch(Exception e){}
  String str = "Hello World!!!" ;
  byte b[] = str.getBytes() ;
  try{
   out.write(b) ;
  }catch(Exception e){}
  try{
   out.close() ;
  }catch(Exception e){}
 }
}
例如:既然可以通过OutputStream向文件中写入内容,那么就一定可以从文件中读取内容,使用InputStream读取内容。
 • InputStream也是一个抽象类,所以必须使用其子类:FileInputStream
 • 读的方式:
  • public int read(byte[] b) throws IOException
   |- 传入一个byte数组,将所有的内容保存在byte数组之中。
   |- 此方法返回向数组中写入数据的个数
  • 将byte数组变为字符串:public String(byte b[])、public String(byte b[],int be,int len)
import java.io.* ;
public class IODemo13{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  InputStream input = null ;
  try{
   // 通过子类实例化
   input = new FileInputStream(f) ;
  }catch(Exception e){}
  byte b[] = null ;
  int len = 0 ;
  try{
   b = new byte[1024] ;
   // 把所有的内容读到数组b中
   // 返回读取的个数
   len = input.read(b) ;
  }catch(Exception e){}
  try{
   input.close() ;
  }catch(Exception e){}
  System.out.println(new String(b,0,len)) ;
 }
}
 • 但是读取的时候发现程序中开辟了一个很大的byte数组,不用的空间有些浪费,那能否根据文件的大小开辟呢?
 • File类中有取得文件长度的方法。
import java.io.* ;
public class IODemo14{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  InputStream input = null ;
  try{
   // 通过子类实例化
   input = new FileInputStream(f) ;
  }catch(Exception e){}
  byte b[] = null ;
  try{
   b = new byte[(int)f.length()] ;
   // 把所有的内容读到数组b中
   // 返回读取的个数
   input.read(b) ;
  }catch(Exception e){}
  try{
   input.close() ;
  }catch(Exception e){}
  System.out.println(new String(b)) ;
 }
}
 • 如果现在不知道文件大小,该怎么读呢?
 • 读取方法:
  |- public abstract int read() throws IOException
  |- 如果读取的内容不是“-1”,就表示还有文件,可以继续读
import java.io.* ;
public class IODemo15{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  InputStream input = null ;
  try{
   // 通过子类实例化
   input = new FileInputStream(f) ;
  }catch(Exception e){}
  byte b[] = null ;
  try{
   b = new byte[(int)f.length()] ;
   int x = 0 ;
   int foot = 0 ;
   while((x=input.read())!=-1){
    b[foot] = (byte)x ;
    foot++ ;
   }
  }catch(Exception e){
   System.out.println(e) ;
  }
  try{
   input.close() ;
  }catch(Exception e){}
  System.out.println(new String(b)) ;
 }
}
3.3.2、字符流
 一个字符 = 两个字节。
 在字符流操作中,主要使用以下两个类:
  • 字符输出流:Writer
  • 字符输入流:Reader
例如:向文件中保存一个数据
 写内容的方法:public void write(String str) throws IOException
import java.io.* ;
public class IODemo16{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  Writer out = null ;
  try{
   // 通过子类实例化
   out = new FileWriter(f) ;
  }catch(Exception e){}
  String str = "Hello World!!!" ;
  try{
   out.write(str) ;
  }catch(Exception e){}
  try{
   out.close() ;
  }catch(Exception e){}
 }
}
例如:从文件中把内容读取进来
 读的方法:
  |- public int read(char[] cbuf) throws IOException
|- public int read() throws IOException
import java.io.* ;
public class IODemo17{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  Reader input = null ;
  try{
   // 通过子类实例化
   input = new FileReader(f) ;
  }catch(Exception e){}
  char c[] = null ;
  int len = 0 ;
  try{
   c = new char[(int)f.length()] ;
   len = input.read(c) ;
  }catch(Exception e){
   System.out.println(e) ;
  }
  try{
   input.close() ;
  }catch(Exception e){}
  System.out.println(new String(c,0,len)) ;
 }
}
 当然,也可以使用read()方法读取内容,代码如下:
import java.io.* ;
public class IODemo18{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  Reader input = null ;
  try{
   // 通过子类实例化
   input = new FileReader(f) ;
  }catch(Exception e){}
  char c[] = null ;
  try{
   c = new char[(int)f.length()] ;
   int x = 0 ;
   int foot = 0 ;
   while((x=input.read())!=-1){
    c[foot] = (char)x ;
    foot++ ;
   }
  }catch(Exception e){
   System.out.println(e) ;
  }
  try{
   input.close() ;
  }catch(Exception e){}
  System.out.println(new String(c)) ;
 }
}
3.3.3、字节流和字符流的区别
 • 字节与字符的不同在于:
  • 所有的文件不管是使用Output、Writer实际上最终保存在文件上的都是字节。
  • 字符是在内存中形成的。
例如:观察以下代码
 使用字节流输出,但是并没有关闭
import java.io.* ;
public class IODemo19{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  OutputStream out = null ;
  try{
   // 通过子类实例化
   out = new FileOutputStream(f) ;
  }catch(Exception e){}
  String str = "Hello World!!!" ;
  byte b[] = str.getBytes() ;
  try{
   out.write(b) ;
  }catch(Exception e){}
 }
}
 以上代码是使用字节流进行操作,但是文件本身并没有关闭,证明字节流是直接操作文件本身的。
 那么,同样,将以上的字节流输出换为字符流输出:
import java.io.* ;
public class IODemo20{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  Writer out = null ;
  try{
   // 通过子类实例化
   out = new FileWriter(f) ;
  }catch(Exception e){}
  String str = "Hello World!!!" ;
  try{
   out.write(str) ;
  }catch(Exception e){}
 }
}
 运行之后,发现文件虽然已经创建,但是所有的内容并没有写进去,这是因为对于字符流在关闭操作的时候,会强制性的将缓存清空,那么以上代码并没有关闭,所以现在的内容还在缓存里,并没有直接到文件之中。那么面对上面的情况,如果不关闭文件该如何解决呢?
 在Writer类中提供了一个强制性清空缓存的操作:public abstract void flush() throws IOException
例如:修改之前的操作,清空缓存
import java.io.* ;
public class IODemo21{
 public static void main(String[] args){
  // 通过File找到一个文件
  File f = new File("e://hello.txt") ;
  // 输出流操作类
  Writer out = null ;
  try{
   // 通过子类实例化
   out = new FileWriter(f) ;
  }catch(Exception e){}
  String str = "Hello World!!!" ;
  try{
   out.write(str) ;
   out.flush() ;
  }catch(Exception e){}
 }
}
但是:
 一般程序对于字节流的使用相对较多,例如:图片、多媒体文件。
3.3.4、COPY功能的实现
 命令格式:copy e:/hello.txt e:/abc.ini
 此命令中有相关的错误提示。
 那么现在要求使用JAVA编写这样的一个命令,例如:Java的类为Copy.class,则可以通过初始化参数的方式输入两个路径,例如:java Copy 路径1 路径2。
 • 数据应该边读边写
 • 要确定源路径是否存在及语法格式是否正确。
import java.io.* ;
public class Copy{
 public static void main(String args[]) throws Exception{
  // 判断参数
  if(args.length!=2){
   System.out.println("命令语法不正确。") ;
   System.exit(1) ;
  }
  // 再判断源文件是否存在
  File f1 = new File(args[0]) ;
  if(!f1.exists()){
   System.out.println("系统找不到指定的文件。") ;
   System.exit(1) ;
  }
  File f2 = new File(args[1]) ;
  InputStream input = new FileInputStream(f1) ;
  OutputStream out = new FileOutputStream(f2) ;
  int x = 0 ;
  while((x=input.read())!=-1){
   out.write(x) ;
  }
  System.out.println("拷贝完成。") ;
  input.close() ;
  out.close() ;
 }

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值