MLDN
课程咨询[孔老师]QQ 1031143579孔老师QQ课程咨询留言 课程咨询[徐老师 ]QQ 945313230
徐老师QQ课程咨询留言
课程咨询[刘老师 ]QQ 514543793
刘老师QQ课程咨询留言
java培训
北京java培训
IT电子教育门户 高端JAVA培训 -=> 资源中心 -=> JAVA SE技术专区 -=> JAVA文件操作 -=> 正文

JAVA文件操作

 发布日期:2008-10-31 9:08:00 发布者:[IT电子教育门户]   评论:[]  浏览:

1、课程名称: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() ;
 }
};
3.3、内存流(掌握)
 一个子类决定父类的具体操作行为,那么对于整个IO操作来说,具体的输入、输出会根据子类的不同而有所不同。
 内存流:指的是所有的输入、输出都是以内存为目的地。
 内存的输出流:ByteArrayOutputStream,以内存为源目的地
 内存输入流:ByteArrayInputStream,是指把内容向内存中输入。
ByteArrayInputStream方法:
 • 构造:public ByteArrayInputStream(byte[] buf),表示把内容输入到内存里去
ByteArrayOutputstream方法:
 • 构造:public ByteArrayOutputStream()
例如:以下代码完成了一个大-小写的转换功能
import java.io.* ;
public class IODemo22{
 public static void main(String args[]) throws Exception{
  ByteArrayInputStream bis = null ;
  ByteArrayOutputStream bos = null ;
  bos = new ByteArrayOutputStream() ;
  String str = "helloworld" ;
  // 把内容输入到内存里去
  bis = new ByteArrayInputStream(str.getBytes()) ;
  // 通过bos可以把内容读取出来
  int c = 0 ;
  while((c=bis.read())!=-1){
   char x = Character.toUpperCase((char)c) ;
   bos.write(x) ;
  }
  System.out.println(bos) ;
  bis.close() ;
  bos.close() ;
 }
};
3.4、打印流(重点)
思考:
 之前如果想向一个文件中保存一些内容,需要把内容变为byte数组,很麻烦,那么对于OutptuStream本身而言,只是具备了保存的功能,但是其功能并不完善。所以后来人们为了操作IO方便(输出方便)为OutptuStream增加了一个子类 —— PrintStream。
 PrintStram之中提供了比OutputStram中更好的输出方法。
 打印流实际上也分为两种:PrintStream、PrintWriter
PrintStream的使用:
 • 构造:public PrintStream(OutputStream out)
  |- 根据传入的OutputStream来决定输出的位置。
 • 使用:print()、println()
例如:观察PrintStream使用
import java.io.* ;
public class IODemo23{
 public static void main(String args[]) throws Exception{
  PrintStream ps = null ;
  ps = new PrintStream(new FileOutputStream(new File("e:\\h.txt"))) ;
  ps.print("hello ") ;
  ps.print("world") ;
  ps.println("\r\nHELLO") ;
  ps.close() ;
 }
};
 如果需要在文件之后对内容进行追加的话,则直接编写以下代码即可:
import java.io.* ;
public class IODemo23{
 public static void main(String args[]) throws Exception{
  PrintStream ps = null ;
  ps = new PrintStream(new FileOutputStream(new File("e:\\h.txt"),true)) ;
  ps.print("hello ") ;
  ps.print("world") ;
  ps.println("\r\nHELLO") ;
  ps.println("\r\nABC") ;
  ps.close() ;
 }
};
 可以发现,使用打印流很方便的完成数据的输出。
3.5、System对IO的支持
 回顾:System.out.println() ;
 System中有以下两个静态属性:
  • System.out:对应的是标准输出,为显示器
  • System.in:对应的是标准输入,为键盘
3.6.1、System.out
 System.out是PrintStream的类型,问:能否通过此对象为OutputStream实例化?
import java.io.* ;
public class IODemo24{
 public static void main(String args[]) throws Exception{
  OutputStream out = System.out ;
  out.write("HELLO WORLD".getBytes()) ;
  out.close() ;
 }
};
 以上代码进一步验证了面向对象的多态性,那个子类为父类实例化,那么父类就具备那个子类的功能。所有的目的地由子类决定。父类只是规定出了标准。
3.6.2、System.in
 System.in对应着键盘的输入,是InputStream类型的对象。
 那么既然是InputStream类型的对象,那么下面的代码实验了由键盘输入数据:
import java.io.* ;
public class IODemo25{
 public static void main(String args[]) throws Exception{
  // 现在代码从键盘中读取信息
  InputStream input = System.in ;
  byte b[] = new byte[1024] ;
  System.out.print("请输入内容:") ;
  int len = input.read(b) ;
  System.out.println("输入的内容为:" + new String(b,0,len)) ;
 }
};
 以上确实完成了键盘的输入信息功能,但是否存在问题?
  • 开辟的空间问题。
 之前学过一种方式,不开辟一个空间,有多少读多少?
那么如果现在使用此种方式呢?
import java.io.* ;
public class IODemo27{
 public static void main(String args[]) throws Exception{
  // 现在代码从键盘中读取信息
  InputStream input = System.in ;
  StringBuffer buf = new StringBuffer() ;
  System.out.print("请输入内容:") ;
  int c = 0 ;
  while((c=input.read())!=-1){
   buf.append((char)c) ;
  }
  System.out.println("输入的内容为:" + buf) ;
 }
};
 以下代码没有指定出具体的空间大小,而是输入多少就保存多少,如果现在输入的是英文字母可以正确保存,如果是中文呢,因为是半个半个字保存的,所以是乱码。
3.6、BufferedReader(缓冲读取,重点)
 之前出现乱码的根本原因在于是分着读的。
 BufferedReader是一个字符流的子类,构造方法:
  • public BufferedReader(Reader in)
 System.in是一个字节流的对象。
 字节流-字符流的转换类:
  • InputStreamReader:把输入的字节流变为字符流
  • OutputStreamWriter:把输出的字符流变为字节流
 观察InputStreamReader,是Reader的子类,构造方法:
  • public InputStreamReader(InputStream in)
 BufferedReader中读取:public String readLine() throws IOException
键盘输入数据的标准格式:
import java.io.* ;
public class IODemo28{
 public static void main(String args[]) throws Exception{
  BufferedReader buf = null ;
  buf = new BufferedReader(new InputStreamReader(System.in)) ;
  System.out.print("请输入内容:") ;
  String str = null ;
  str = buf.readLine() ;
  System.out.println("输入的内容为:" + str) ;
 }
};
 如果现在要想输入多个数据的话,则直接重复readLine()即可。
import java.io.* ;
public class IODemo29{
 public static void main(String args[]) throws Exception{
  BufferedReader buf = null ;
  buf = new BufferedReader(new InputStreamReader(System.in)) ;
  System.out.print("请输入内容1:") ;
  String str = null ;
  str = buf.readLine() ;
  System.out.println("输入的内容1为:" + str) ;
  System.out.print("请输入内容2:") ;
  str = buf.readLine() ;
  System.out.println("输入的内容2为:" + str) ;
 }
};
3.6.1、练习一
完成以下功能
 通过程序输入两个数字,之后进行两个数字的相加操作,并把结果打印输出。
 要求:如果用户输入的不是数字,则应该提示用户输入错误,之后要求用户重新输入。
 • 字符串  整型:Integer.parseInt(String str)
A、 基础模型
import java.io.* ;
public class IODemo30{
 public static void main(String args[]) throws Exception{
  BufferedReader buf = null ;
  buf = new BufferedReader(new InputStreamReader(System.in)) ;
  int x = 0 ;
  int y = 0 ;
  System.out.print("输入第一个数字:") ;
  String str = null ;
  str = buf.readLine() ;
  x = Integer.parseInt(str) ;
  System.out.print("输入第二个数字:") ;
  str = buf.readLine() ;
  y = Integer.parseInt(str) ;
  System.out.println("计算结果:" + x + " + " + y + " = " + (x+y)) ;
 }
};
B、 为程序中加入判断
 因为数据是由用户输入的,所以必须对输入的内容进行验证。使用正则表达式。
import java.io.* ;
public class IODemo31{
 public static void main(String args[]) throws Exception{
  BufferedReader buf = null ;
  buf = new BufferedReader(new InputStreamReader(System.in)) ;
  int x = 0 ;
  int y = 0 ;
  boolean flag = true ;
  System.out.print("输入第一个数字:") ;
  String str = null ;
  while(flag){
   str = buf.readLine() ;
   if(str.matches("\\d+")){
    x = Integer.parseInt(str) ;
    flag = false ;
   }else{
    System.out.print("输入的不是数字,请重新输入:") ;
   }
  }
  System.out.print("输入第二个数字:") ;
  flag = true ;
  while(flag){
   str = buf.readLine() ;
   if(str.matches("\\d+")){
    y = Integer.parseInt(str) ;
    flag = false ;
   }else{
    System.out.print("输入的不是数字,请重新输入:") ;
   }
  }
  System.out.println("计算结果:" + x + " + " + y + " = " + (x+y)) ;
 }
};
 如果现在要求连续输入10个数字,则以上代码要重复10遍,下面设计一个输入数据的类,要求可以通过此类得到正确的整数、小数、日期(yyyy-mm-dd),和字符串,问此类如何设计,并将此类应用与之前的程序之上。
import java.io.* ;
import java.util.* ;
import java.text.* ;
class InputData{
 private BufferedReader buf = null ;
 public InputData(){
  this.buf = new BufferedReader(new InputStreamReader(System.in)) ;
 }
 public String getString(String info){
  String str = null ;
  System.out.print(info) ;
  try{
   str = this.buf.readLine() ;
  }catch(Exception e){}
  return str ;
 }
 public int getInt(String info){
  int temp = 0 ;
  boolean flag = true ;
  String str = null ;
  while(flag){
   try{
    str = this.getString(info) ;
    if(str.matches("\\d+")){
     temp = Integer.parseInt(str) ;
     flag = false ;
    }else{
     System.out.print("输入的不是数字,请重新输入,") ;
    }
   }catch(Exception e){
    System.out.print("输入的不是数字,请重新输入,") ;
   }
  }
  return temp ;
 }
 public float getFloat(String info){
  float temp = 0 ;
  boolean flag = true ;
  String str = null ;
  while(flag){
   try{
    str = this.getString(info) ;
    if(str.matches("\\d+.?\\d{1,2}")){
     temp = Float.parseFloat(str);
     flag = false ;
    }else{
     System.out.print("输入的不是数字,请重新输入,") ;
    }
   }catch(Exception e){
    System.out.print("输入的不是数字,请重新输入,") ;
   }
  }
  return temp ;
 }
 public Date getDate(String info){
  Date temp = null ;
  boolean flag = true ;
  String str = null ;
  while(flag){
   try{
    str = this.getString(info) ;
    if(str.matches("\\d{4}-\\d{2}-\\d{2}")){
     // 把一个字符传变为Date类型
     temp = new SimpleDateFormat("yyyy-MM-dd").parse(str) ;
     flag = false ;
    }else{
     System.out.print("输入的不是日期,请重新输入,") ;
    }
   }catch(Exception e){
    System.out.print("输入的不是日期,请重新输入,") ;
   }
  }
  return temp ;
 }
};
public class IODemo32{
 public static void main(String args[]) throws Exception{
  InputData input = new InputData() ;
  int x = input.getInt("输入第一个数字:") ;
  int y = input.getInt("输入第二个数字:") ;
  System.out.println("计算结果:" + x + " + " + y + " = " + (x+y)) ;
  System.out.println(input.getFloat("输入小数:")) ;
  System.out.println(input.getDate("输入日期:")) ;
 }
};
3.6.2、练习二
设计一个菜单程序
 用户运行程序之后,可以显示一个菜单:
 [1]、输入数据
 [2]、查看数据
 [3]、修改数据
 [4]、退出系统
 
 请选择:
 提示:可以通过switch完成
import java.io.* ;
import java.util.* ;
import java.text.* ;
class InputData{
 private BufferedReader buf = null ;
 public InputData(){
  this.buf = new BufferedReader(new InputStreamReader(System.in)) ;
 }
 public String getString(String info){
  String str = null ;
  System.out.print(info) ;
  try{
   str = this.buf.readLine() ;
  }catch(Exception e){}
  return str ;
 }
 public int getInt(String info){
  int temp = 0 ;
  boolean flag = true ;
  String str = null ;
  while(flag){
   try{
    str = this.getString(info) ;
    if(str.matches("\\d+")){
     temp = Integer.parseInt(str) ;
     flag = false ;
    }else{
     System.out.print("输入的不是数字,请重新输入,") ;
    }
   }catch(Exception e){
    System.out.print("输入的不是数字,请重新输入,") ;
   }
  }
  return temp ;
 }
 public float getFloat(String info){
  float temp = 0 ;
  boolean flag = true ;
  String str = null ;
  while(flag){
   try{
    str = this.getString(info) ;
    if(str.matches("\\d+.?\\d{1,2}")){
     temp = Float.parseFloat(str);
     flag = false ;
    }else{
     System.out.print("输入的不是数字,请重新输入,") ;
    }
   }catch(Exception e){
    System.out.print("输入的不是数字,请重新输入,") ;
   }
  }
  return temp ;
 }
 public Date getDate(String info){
  Date temp = null ;
  boolean flag = true ;
  String str = null ;
  while(flag){
   try{
    str = this.getString(info) ;
    if(str.matches("\\d{4}-\\d{2}-\\d{2}")){
     // 把一个字符传变为Date类型
     temp = new SimpleDateFormat("yyyy-MM-dd").parse(str) ;
     flag = false ;
    }else{
     System.out.print("输入的不是日期,请重新输入,") ;
    }
   }catch(Exception e){
    System.out.print("输入的不是日期,请重新输入,") ;
   }
  }
  return temp ;
 }
};
class Operate{
 public void add(){
  System.out.println("选择的是输入操作!") ;
 }
 public void show(){
  System.out.println("选择的是查看数据操作!") ;
 }
 public void update(){
  System.out.println("选择的是修改操作!") ;
 }
};
// 负责显示菜单
class Menu{
 public Menu(){
  while(true){
   this.showMenu() ;
  }
 }
 public void showMenu(){
  System.out.println(" ================== 菜单程序 ================== ") ;
  System.out.println("[1]、输入数据") ;
  System.out.println("[2]、查看数据") ;
  System.out.println("[3]、修改数据") ;
  System.out.println("[4]、退出系统") ;
  InputData input = new InputData() ;
  Operate o = new Operate() ;
  switch(input.getInt("请选择:")){
   case 1:
    {
     o.add() ;
     break ;
    }
   case 2:
    {
     o.show() ;
     break ;
    }
   case 3:
    {
     o.update() ;
     break ;
    }
   case 4:
    {
     System.out.println("byebye!") ;
     System.exit(1) ;
     break ;
    }
   case 5:
    {
     System.out.println("无效的选项,请重新选择!") ;
     break ;
    }
  }
 }
};
public class IODemo33{
 public static void main(String args[]) throws Exception{
  new Menu() ;
 }
};
3.7、字符编码(了解)
 在各个平台上都是有语言的支持的,那么一般对于文字来说有以下几种常见的编码方式:
  • GBK:包含了简体中文和繁体中文的编码集
  • GB2312:只包含了简体中文
  • ISO8859-1:是一个国际的通用编码
例如:取得本机的编码方式
public class IODemo34{
 public static void main(String args[]) throws Exception{
  System.getProperties().list(System.out) ;
 }
};
显示结果:
 
 任何编码都不写的情况下,肯定是GBK码,那么如果现在要保存一个文件的内容,但是文件的内容使用了ISO8859-1编码,问能正确解码吗?不可以
例如:以下代码对输出的内容进行重新编码
import java.io.* ;
public class IODemo35{
 public static void main(String args[]) throws Exception{
  OutputStream out = new FileOutputStream(new File("e:\\test.txt")) ;
  out.write("世界,你好".getBytes("ISO8859-1")) ;
  out.close() ;
 }
};
 因为程序本身与本地环境中的编码方式不一样,所以无法正确的进行解码。
程序造成乱码的根本原因:
 • 编码不一致所造成
3.8、对象序列化(重点)
 对象序列化:将一个对象进行IO操作,输入/输出。
 如果要想实现对象序列化,则对象所在的类必须实现一个序列化接口 —— Serializable,但是此接口中没有任何的定义,所以此接口只是一个标识接口。
 常见的标识接口:
  • Cloneable,表示可以被克隆
  • Serializable:标识可以被序列化
那么下面的代码以向文件中保存为例。
如果现在要想实现对象的输出和输入,则必须使用以下两个类:
 • ObjectOutputStream:对象输出流
  |- 构造方法:public ObjectOutputStream(OutputStream out) throws IOException
  |- 写对象:public final void writeObject(Object obj) throws IOException
 • ObjectInputStream:对象输入流,反序列化
  |- 构造方法:public ObjectInputStream(InputStream in) throws IOException
  |- 读对象:public final Object readObject() throws IOException,ClassNotFoundException
说明:
 • 对象可以向任何地方保存。
例如:向文件之中写入一个对象
import java.io.* ;
class Person implements Serializable{
 private String name;
 private int age ;
 public Person(String name,int age){
  this.name = name ;
  this.age = age ;
 }
 public String toString(){
  return "姓名:" + this.name + ",年龄:" + this.age ;
 }
};
public class IODemo36{
 public static void main(String args[]) throws Exception{
  Person per = new Person("zhangsan",30) ;
  ser(per) ;
 }
 public static void ser(Person per) throws Exception{
  ObjectOutputStream oos = null ;
  oos = new ObjectOutputStream(new FileOutputStream(new File("e:\\person.ser"))) ;
  // 写对象
  oos.writeObject(per) ;
  oos.close() ;
 }
};
例如:从文件之中读取出对象
import java.io.* ;
class Person implements Serializable{
 private String name;
 private int age ;
 public Person(String name,int age){
  this.name = name ;
  this.age = age ;
 }
 public String toString(){
  return "姓名:" + this.name + ",年龄:" + this.age ;
 }
};
public class IODemo37{
 public static void main(String args[]) throws Exception{
  Person per = new Person("zhangsan",30) ;
  // ser(per) ;
  System.out.println(dser()) ;
 }
 public static void ser(Person per) throws Exception{
  ObjectOutputStream oos = null ;
  oos = new ObjectOutputStream(new FileOutputStream(new File("e:\\person.ser"))) ;
  // 写对象
  oos.writeObject(per) ;
  oos.close() ;
 }
 public static Person dser() throws Exception{
  Person per = null ;
  ObjectInputStream ois = null ;
  ois = new ObjectInputStream(new FileInputStream(new File("e:\\person.ser"))) ;
  per = (Person)ois.readObject() ;
  ois.close() ;
  return per ;
 }
};
 例如:现在不希望Person类中的name属性被序列化,那么次时对于不希望被序列化的属性就可以使用transient关键字声明。
import java.io.* ;
class Person implements Serializable{
 private transient String name;
 private int age ;
 public Person(String name,int age){
  this.name = name ;
  this.age = age ;
 }
 public String toString(){
  return "姓名:" + this.name + ",年龄:" + this.age ;
 }
};
public class IODemo37{
 public static void main(String args[]) throws Exception{
  Person per = new Person("zhangsan",30) ;
  ser(per) ;
  System.out.println(dser()) ;
 }
 public static void ser(Person per) throws Exception{
  ObjectOutputStream oos = null ;
  oos = new ObjectOutputStream(new FileOutputStream(new File("e:\\person.ser"))) ;
  // 写对象
  oos.writeObject(per) ;
  oos.close() ;
 }
 public static Person dser() throws Exception{
  Person per = null ;
  ObjectInputStream ois = null ;
  ois = new ObjectInputStream(new FileInputStream(new File("e:\\person.ser"))) ;
  per = (Person)ois.readObject() ;
  ois.close() ;
  return per ;
 }
};
4、总结
 整个IO包中,实际上就五个类,一个接口、一个关键字
 • 五个类:File、OutputStream、InputStream、Reader、Writer
 • 一个接口:Serializable
 • 一个关键字:transient
 一切的操作以父类为准,但是里面有若干个子类很有用处:
 • OutputStream:
  |- FileOutputStream:文件操作类
  |- ByteArrayOutputStream:内存操作类
  |- ObjectOutputStream:对象输出流
  |- PrintStream:打印流
 • InputStream:
  |- FileInputStream
  |- ObjectInputStream
  |- ByteArrayInputStream
 • Writer:
  |- OutputStreamWriter:字符-字节的转换类
  |- FileWriter
  |- PrintWriter
 • Reader:
  |- InputStreamReader
  |- FileReader
  |- BufferedReader
 用户输入数据的标准格式
 字符编码:GBK、GB2312、ISO8859-1
 对象序列化
5、预习任务
 1、 JAVA类集
• Collection、List、Set、ArrayList、HashSet、Vector、TreeSet、Hashtable、HashMap、TreeMap、Comparable、Iterator、ListIterator、Enumeration,作用
6、作业
选举程序
A、功能描述:
有一个班采用民主投票方法推选班长,班长候选人共4位,每个人姓名及代号分别为 张三  1,李四  2,王五  3,刘六  4。程序操作员将每张选票上所填的代号(1、2、3、或4)循环输入电脑,输入数字0结束输入,然后将所有候选人的得票情况显示出来,并显示最终当选者的信息。

B、具体要求如下:
(1)、要求用面向对象方法,编写候选人类Candidate,将候选人姓名、代号和票数保存到类Candidate(候选人类)中,并实现相应的getXXX 和 setXXX方法。
(2)、编写主程序class OneTest(请考试学员统一使用主类名称:OneTest)
(3)、输入数据之前,显示出各位候选人的代号及姓名:(提示:建立一个候选人类型数组)如下图所示。
(4)、循环执行接收键盘输入的班长候选人代号,直到输入的数字为0,结束选票的输入工作,如下图所示
(5)、在接收每次输入的选票后要求验证该选票是否有效,即:如果输入的数不是0,1,2,3,4这5个数字之一,或者输入一串字母(捕捉异常),应显示出错误提示信息:此选票无效,请输入正确的候选人代号!并继续等待输入。
(6)、输入结束后显示所有候选人的得票情况,如图所示
(7)、输出最终当选者的相关信息,如图所示。

C、参考图示:

要求:
 可以将所有的选举结果保存,并再次显示

java视频教程
JAVA核心_75对象序列化练习
 JAVA核心_75对象序列化..
JAVA核心_74对象序列化
 JAVA核心_74对象序列化..
JAVA核心_73字符编码
 JAVA核心_73字符编码 ..
JAVA核心_72Scanner
 JAVA核心_72Scann..
JAVA核心_71 IO练习 二
 JAVA核心_71 IO练习..
相关文章 推荐文章
关于Java IO流学习总结[3.4]
Java文件操作增强工具[2.18]
java中四种操作xml方式的比..[1.7]
Java程序用缓冲IO来提高系统..[11.27]
在JAVA文件中获取该项目的相对..[11.2]
关于Java IO流学习总结
Java文件操作增强工具
JAVA文件操作
java中四种操作xml方式的比较
Java程序用缓冲IO来提高系统性能
热门文章
一句代码完成对文本文件读取和写入
JAVA中文件操作大全
Java基于Socket实现文件传输示..
在JAVA文件中获取该项目的相对路径
关于Java IO流学习总结
生成一个java编制的可执行文件
Java数字签名
如何将JAVA生成可执行文件?
利用JAVA操作EXCEL文件
Java文件操作详解
今日更新
关于Java IO流学习总结
Java文件操作增强工具
JAVA文件操作
java中四种操作xml方式的比较
Java程序用缓冲IO来提高系统性能
在JAVA文件中获取该项目的相对路径
使用JAVA语言来更新XML文档的常用..
利用Java控制EXCEL实例详解
Java基于Socket实现文件传输示..
为Java程序中添加播放MIDI音乐功..
JAVA招聘网
 评一评
正在读取…
  姓名:
  评论:
    
【注】 发表评论必需遵守以下条例: !!!
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款
关于我们 | 商务合作 | 招聘信息 | 客服中心 | 服务条款 | 免责声明 | 网站导航 QQ留言
Copyright 2009 魔乐培训MLDN.CN all rights reserved 版权所有 京ICP备07008611号