java IO 流

io流在java中与Android中有很大的相似性,我们先看java中的IO流
一, 文件流:

File f = new File("e:" + File.separator + "test.txt");// separator是分割符,适用于不同系统
  if (f.exists()) {// f 存在
   if (f.isFile()) {// 如果f是文件
    // 打印相关信息
    System.out.println("文件名称" + f.getName());
    System.out.println("文件大小" + f.length());
    System.out.println("文件路径" + f.getAbsolutePath());
    // 输入流
    FileInputStream fis = null;
    try {
     fis = new FileInputStream(f);

     // 通过获得文件大小读取文件
     // int lenght = fis.available();//文件的大小
     // byte [] bytes = new byte[lenght];
     // String s = fis.read(bytes);
     // System.out.println(s);
     // 通过循环读取
     byte[] bytes = new byte[1024];
     int n = 0;
     while ((n = fis.read(bytes)) != -1) {
      String s = new String(bytes, 0, n);
      System.out.println(f.getName() + "文件的内容是:" + s);
     }

    } catch (Exception e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    } finally {
     try {
      fis.close();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }

   } else if (f.isDirectory()) {// 如果是文件夹,其实可以不要判断,这里为了显示更清楚
    // 显示文件夹下的所有文件和文件夹
    // String [] fs = f.list();//返回文件的名称列表
    File[] files = f.listFiles();
    for (File ff : files) {
     System.out.println(ff);// 默认打印文件全路径
    }
   }

  } else {// 不存在
    // 新建
   try {
    f.createNewFile();// 创建一个相应文件
    // 并在文件中写入一些信息
    FileOutputStream fos = null;
    try {
     fos = new FileOutputStream(f);
     String s = "我是中国人\r\n";// "\n"表示换行,"\r"表示回车
     String ss = "我叫钟志钢";
     fos.write(s.getBytes());
     fos.write(ss.getBytes());
    } catch (Exception e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    } finally {
     try {
      fos.close();// 一定要记得关闭流
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   f.mkdir();// 歌者创建一个文件夹
  }



二,RandomAccessFile
完成随机读取功能,可读取指定位置的内容,文件中的所有内容都是按照字节存放的,都有固定的位置
RandomaccessFile(File f , String mode) mode:
 r : 只读
 w : 只写
 rw : 读写模式,如果文件不存在,会自动创建

File f = new File("e:" + File.separator + "RandomAccessFile");
  RandomAccessFile raf = null;
  String name = null;
  int age = 0;
  String myname = null;
  int myage = 0;

  try {
   raf = new RandomAccessFile(f, "rw");
   name = "zhangsan";
   age = 10;
   raf.writeBytes(name);// 写入8字节
   raf.writeInt(age);// 写入4个字节
   name = "lishi   ";
   age = 20;
   raf.writeBytes(name);// 写入8字节
   raf.writeInt(age);// 写入4个字节
   name = "wangwu  ";
   age = 28;
   raf.writeBytes(name);// 写入8字节
   raf.writeInt(age);// 写入4个字节
   raf.close();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  try {
   raf = new RandomAccessFile(f, "r");// 只读的方式打开文件
   byte[] b = new byte[8];// 创建byte数组
   raf.skipBytes(12);// 路过12字符,读第二个
   for (int i = 0; i < b.length; i++) {
    b[i] = raf.readByte();// 一个一个字节读出来
   }
   myname = new String(b);
   myage = raf.readInt();// 读取年龄
   System.out.println("我的年龄是:" + myage + ",我的姓名是:" + myname);
   raf.seek(0);// 回到开头,读第一个
   for (int i = 0; i < b.length; i++) {
    b[i] = raf.readByte();// 一个一个字节读出来
   }
   myname = new String(b);
   myage = raf.readInt();// 读取年龄
   System.out.println("我的年龄是:" + myage + ",我的姓名是:" + myname);
   
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }



这样操作很麻烦,所以java有专门的管理方法:字节流与字符流:
三, 字节与字符流(OutputStream,InputStream, Reader,Writer四个抽象类)
   操作步骤:
 1,使用Files类打开文件
 2,通过字节流或字符流的子类,指定输出位置
 3,进行读写操作
 4,关闭输入/输出(资源操作最后必须关闭,否则可能出现未知错误)
   1,字节流: public abstract class OutputStream extends Object implements Clonseable, Fluashable
 Clonseable 表示可以关闭的操作,因为程序运行到最后肯定要关闭(close())
 Fluashable 表示刷新,清空内在中的数据(flush())
 
 OutputStrem:

 File f = new File("f:" + File.separator + "test.txt");
  OutputStream os = null;
  try {
   os = new FileOutputStream (f);//向上转型,如果文件不存在,会自动创建,如果存在,会覆盖
   String s = "I am Chinese";
   byte [] b = s.getBytes();//转化
   try {
    os.write(b);//会把之前的删除
    int a = 3;
    os.write(a);
    os.write(b, 5, 7);//从第4个字符开始,一共7个字符,可以取到Chinese
    
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }finally {//在最后关闭,不管是否出现异常,都会执行
   try {
    if(os != null){
     os.close();
    }
    
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  //如果要想保留之前的内容
  try {
   os = new FileOutputStream(f,true);//表示在文件后面追加内容
   try {
    os.write("\r\n我叫钟志钢".getBytes());
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }finally {//在最后关闭,不管是否出现异常,都会执行
   try {
    if(os != null){
     os.close();
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }



 InputStream:

File f = new File("f:" + File.separator + "test.txt");
  InputStream is = null;
  try {
   is = new FileInputStream (f);
   byte b [] = new byte[1024];//定义一个1024个字节的数据
   try {
//    is.read(b);//把所有内容都读取到b中(最大是1024),如果不确定文件的大小,可以利用如下方法:
    
//    int len = is.available();//也可以用: int len = f.lenght;
//    byte[] b2 = new byte[len];
//    is.read(b2);
    
    //或者从读取的数据时定义大小
//    int lens = is.read(b);
//    String s = new String(b, 0, lens);
    
    //is.read();//一个一个读取
//    for(int i = 0; i < b.length; i ++){
//     b[i] = (byte) is.read();
//     //当读到末尾时,就会出现b[i] = -1
//    }
//    System.out.println("is.read()"+new String(b));
    
    //以上方法的改进
    int len = 0; 
    int lend = 0;//读到的数据
    while((lend = is.read()) != -1){
     b[len] = (byte) lend;
     len++;
     System.out.println(lend);
    }
    System.out.println("输入流的数据:" + new String(b));
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }finally{
   if(is != null){
    try {
     is.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }



     2, 字符流可以直接操作字符串,无需转化
 Reader,FileReader其实在操作上与字节流很相似:

File f = new File("f:" + File.separator + "test.txt");
  Reader is = null;
  try {
   is = new FileReader (f);
   char b [] = new char[1024];//定义一个1024个字节的数据
   try {
    int len = 0; 
    int lend = 0;//读到的数据
    while((lend = is.read()) != -1){
     b[len] = (char) lend;//其实是把ASC码强力转成字符串
     len++;
     System.out.println(lend);
    }
    System.out.println("输入流的数据:" + new String(b));
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }finally{
   if(is != null){
    try {
     is.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
  



  Writer,FileWriter,

File f = new File("f:" + File.separator + "test.txt");
  Writer os = null;
  try {
   os = new FileWriter (f, true);//向上转型,如果文件不存在,会自动创建,如果存在,会覆盖
   String s = "I am Chinese";
   try {
    os.write(s);
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }finally {//在最后关闭,不管是否出现异常,都会执行
   try {
    if(os != null){
     os.close();
    }
    
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }


 

 虽然看起来很多相似的地方,但是还是有些区别:
  字节流直接操作文件,字符流需要通过缓存才能操作,也就是说在字节操作中,
   即使没有关闭,也会执行操作,在字符操作中,没有关闭之前,数据存在内存(缓存)中,是不会执行输出操作的
  硬盘上存储的数据都是字节形式的,字符只存在于内在中.
 操作实例:Copy 源文件 目标文件

 String args1 [] = new String[]{
    "f:" + File.separator + "test.txt",
    "f:" + File.separator + "test2.txt"
  };
  if(args1.length!=2){  // 判断是否是两个参数
   System.out.println("输入的参数不正确。") ;
   System.out.println("例:java Copy 源文件路径 目标文件路径") ;
   System.exit(1) ; // 系统退出
  }
  File f1 = new File(args1[0]) ; // 源文件的File对象
  File f2 = new File(args1[1]) ; // 目标文件的File对象
  if(!f1.exists()){
   System.out.println("源文件不存在!") ;
   System.exit(1) ;
  }
  InputStream input = null ;  // 准备好输入流对象,读取源文件
  OutputStream out = null ;  // 准备好输出流对象,写入目标文件
  try{
   input = new FileInputStream(f1) ;
  }catch(FileNotFoundException e){
   e.printStackTrace() ;
  }
  try{
   out = new FileOutputStream(f2) ;
  }catch(FileNotFoundException e){
   e.printStackTrace() ;
  }
  if(input!=null && out!=null){ // 判断输入或输出是否准备好
   int temp = 0 ; 
   try{
    while((temp=input.read())!=-1){ // 开始拷贝
     out.write(temp) ; // 边读边写,最好是使用这种方式,因为如果文件过大,可能内在不够用
    }
    System.out.println("拷贝完成!") ;
   }catch(IOException e){
    e.printStackTrace() ;
    System.out.println("拷贝失败!") ;
   }
   try{
    input.close() ;  // 关闭
    out.close() ;  // 关闭
   }catch(IOException e){
    e.printStackTrace() ;
   }
  }


 

四, 字节流与字符流的转换流:OutputStreamWriter,将输出的字符流转换成输出的字节流
    InputStreamReader,将输入的字节流转换成输入的字符流
 其实就是说字符便于在内在中操作,字节便于在硬盘中存储,在使用时进行相应的转换
 OutputStreamWriter:

File f = new File("d:" + File.separator + "test.txt") ; 
  Writer out = null ; // 字符输出流
  out = new OutputStreamWriter(new FileOutputStream(f)) ; // 字节流变为字符流
  out.write("hello world!!") ; // 使用字符流输出
  out.close() ;
 InputStreamReader
 File f = new File("d:" + File.separator + "test.txt") ; 
  Reader reader = null ;
  reader = new InputStreamReader(new FileInputStream(f)) ; // 将字节流变为字符流
  char c[] = new char[1024] ;
  int len = reader.read(c) ; // 读取
  reader.close() ; // 关闭
  System.out.println(new String(c,0,len)) ;


 

五, 内在操作流:ByteArrayInputStream, ByteArrayOutputStream, 主要是程序内容与内存的交换,所以操作对象是以内在为准的,

String str = "HELLOWORLD" ;  // 定义一个字符串,全部由大写字母组成
  ByteArrayInputStream bis = null ; // 内存输入流
  ByteArrayOutputStream bos = null ; // 内存输出流
  bis = new ByteArrayInputStream(str.getBytes()) ; // 向内存中输出内容
  bos = new ByteArrayOutputStream() ; // 准备从内存ByteArrayInputStream中读取内容
  int temp = 0 ;
  while((temp=bis.read())!=-1){
   char c = (char) temp ; // 读取的数字变为字符
   bos.write(Character.toLowerCase(c)) ; // 将字符变为小写
  }
  // 所有的数据就全部都在ByteArrayOutputStream中
  String newStr = bos.toString() ; // 取出内容
  try{
   bis.close() ;
   bos.close() ;
  }catch(IOException e){
   e.printStackTrace() ;
  }
  System.out.println(newStr) ;


 

六, 管道流: PipedOutputStream ,PipedInputStream 不同线程中的IO操作,从一个线程传入到另一个线程,同时进行

class Send implements Runnable{   // 线程类
 private PipedOutputStream pos = null ; // 管道输出流
 public Send(){
  this.pos = new PipedOutputStream() ; // 实例化输出流
 }
 public void run(){
  String str = "Hello World!!!" ; // 要输出的内容
  try{
   this.pos.write(str.getBytes()) ;
  }catch(IOException e){
   e.printStackTrace() ;
  }
  try{
   this.pos.close() ;
  }catch(IOException e){
   e.printStackTrace() ;
  }
 }
 public PipedOutputStream getPos(){ // 得到此线程的管道输出流
  return this.pos ; 
 }
};
class Receive implements Runnable{
 private PipedInputStream pis = null ; // 管道输入流
 public Receive(){
  this.pis = new PipedInputStream() ; // 实例化输入流
 }
 public void run(){
  byte b[] = new byte[1024] ; // 接收内容
  int len = 0 ;
  try{
   len = this.pis.read(b) ; // 读取内容
  }catch(IOException e){
   e.printStackTrace() ;
  }
  try{
   this.pis.close() ; // 关闭
  }catch(IOException e){
   e.printStackTrace() ;
  }
  System.out.println("接收的内容为:" + new String(b,0,len)) ;
 }
 public PipedInputStream getPis(){
  return this.pis ;
 }
};
public class PipedDemo{//对接
 public static void main(String args[]){
  Send s = new Send() ;
  Receive r = new Receive() ;
  try{
   s.getPos().connect(r.getPis()) ; // 连接管道
  }catch(IOException e){
   e.printStackTrace() ;
  }
  new Thread(s).start() ; // 启动线程
  new Thread(r).start() ; // 启动线程
 }
};


 

七, 打印流: PrintWriter(字符), PrintStream(字节)
 PrientSteam (OutputSteam out) 属于装饰设计模式,即好看又方便

 PrintStream ps = null ;  // 声明打印流对象
  // 如果现在是使用FileOuputStream实例化,意味着所有的输出是向文件之中
  ps = new PrintStream(new FileOutputStream(new File("f:" + File.separator + "test.txt"))) ;
  String name = "钟志钢" ; // 定义字符串
  int age = 26 ;    // 定义整数
  float score = 990.356f ; // 定义小数
  char sex = 'M' ;   // 定义字符
  //%s 表示String , %d 表示int , %f 表示小数, %c 表示字符,其实都可以用s,因为所有都可以向String转
  ps.printf("姓名:%s;年龄:%s;成绩:%s;性别:%s",name,age,score,sex) ;
  ps.close() ;


 

 以前内容的文件内容结果: 姓名:钟志钢;年龄:26;成绩:990.356;性别:M
八, BufferedReader , buffer缓冲区,
 接收键盘接收的数据:

 BufferedReader buf = null ;  // 声明对象
  buf = new BufferedReader(new InputStreamReader(System.in)) ; // 将字节流变为字符流
  String str = null ; // 接收输入内容
  System.out.print("请输入内容:然后回车") ;
  try{
   str = buf.readLine() ; // 读取一行数据,输入没有最长限制,以分割符(通常是回车)为界
  }catch(IOException e){
   e.printStackTrace() ; // 输出信息
  }
  System.out.println("输入的内容为:" + str) ;


 

九, 全并流: SequenceInputStream , 即把各种流进行合并,

InputStream is1 = null ;  // 输入流1
  InputStream is2 = null ;  // 输入流1
  OutputStream os = null ;  // 输出流
  SequenceInputStream sis = null ; // 合并流
  is1 = new FileInputStream("d:" + File.separator + "a.txt") ;
  is2 = new FileInputStream("d:" + File.separator + "b.txt") ;
  os = new FileOutputStream("d:" + File.separator + "ab.txt") ;
  sis = new SequenceInputStream(is1,is2) ; // 实例化合并流
  int temp = 0 ; // 接收内容
  while((temp=sis.read())!=-1){ // 循环输出
   os.write(temp) ; // 保存内容
  }
  sis.close() ; // 关闭合并流
  is1.close() ; // 关闭输入流1`
  is2.close() ; // 关闭输入流2
  os.close() ; // 关闭输出流


 

十, 对象序列化, ObjectOutputStream, 对象序列化 ObjectInputStream, 对象反序列化
 说的明白一点,当我们写了一个对象(例如类Person),需要存储时,就必须转换成二进制,这个过程就是序列化的过程
 要被序列化的对象必须要实现接口Serializable,表示这个对象可以被序列化
 先定义一个类:personprivate String name ; // 声明name属性,但是此属性不被序列化

 public class Person implements Serializable{
 private String name ; // 声明name属性,但是此属性不被序列化
 private int age ;  // 声明age属性
 public Person(String name,int age){ // 通过构造设置内容
  this.name = name ;
  this.age = age ;
 }
 public String toString(){ // 覆写toString()方法
  return "姓名:" + this.name + ";年龄:" + this.age ;
 }
 };


 

 序列化过程:

public static void main(String args[]) throws Exception{
  Person per[] = {new Person("张三",30),new Person("李四",31),
   new Person("王五",32)} ;
  ser(per) ;
  Object o[] = (Object[])dser() ;
  for(int i=0;i<o.length;i++){
   Person p = (Person)o[i] ;
   System.out.println(p) ;
  }
 }
 public static void ser(Object obj[]) throws Exception {
  File f = new File("D:" + File.separator + "test.txt") ; // 定义保存路径
  ObjectOutputStream oos = null ; // 声明对象输出流
  OutputStream out = new FileOutputStream(f) ; // 文件输出流
  oos = new ObjectOutputStream(out) ;
  oos.writeObject(obj) ; // 保存对象
  oos.close() ; // 关闭
 }
 public static Object[] dser() throws Exception {
  File f = new File("D:" + File.separator + "test.txt") ; // 定义保存路径
  ObjectInputStream ois = null ; // 声明对象输入流
  InputStream input = new FileInputStream(f) ; // 文件输入流
  ois = new ObjectInputStream(input) ; // 实例化对象输入流
  Object obj[] = (Object[])ois.readObject() ; // 读取对象
  ois.close() ; // 关闭
  return obj ;
 }


 

十一, 字符编码 :乱码产生的原因就是所用编码不一到的原因
 分类:iso8859-1,属于单字节编码,最多只能表示0-225字符范围,一般用在英文上
  GBK/GB2312: 中文国际编码,专门用来表示汉字, 是双字节编码
  udicode:java中使用的编码,最标准的一种,用16进制表示,但不兼容iso8859-1
  UTF: 兼容iso8859-1,也可以表示所有的语言字符,但长度1-6个字节不等,中文常使用的编码


 

 System.out.println("系统默认编码:" +
   System.getProperty("file.encoding")) ; // 获取当前系统编码

  File f = new File("f:" + File.separator + "test.txt") ; // 实例化File类
  OutputStream out = new FileOutputStream(f) ; // 实例化输出流
  byte b[] = "中国,你好!".getBytes("ISO8859-1") ; // 转码操作
  out.write(b) ; // 保存
  out.close() ; // 关闭 


 

 本文章相关源代码:

http://download.csdn.net/detail/zxjzzg/5170491

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值