我的java笔记(IO)


毕老师说集合和IO是我们以后的饭碗,所以在这两节中练得代码比较多.希望黄天不负有心人,我绝不会以后在这方面落伍的.

IO(Input Output)流:
 一:
  IO流用来处理设备之间的数据传输.
  Java对数据的操作时通过流的方式.
  Java用于操作流的对象都在IO包中.
  流按流向分为:输入流和输出流.
  流按操作数据分为两种:字节流和字符流.
 二:IO四大基类:
  字节流的抽象基类:InputStream, OutputStream
  字符流的抽象基类:Reader, Writer
  注意:这四个类都是抽象类,由着四个类派生出来的子类名称都是以其父类名作为子类名的后缀.
   如:InputStream的子类FileInputStream
   如:Reader的子类FileReader
 
三:Writer类
 要求:在硬盘上,创建一个文件并写入一些文字数据.
 找到一个专门用于操作文件的Writer子类对象,FileWriter.   后缀名是父类名,前缀名是该流对象的功能.
 1:FileWriter fw=new FileWriter("D:\\Demo1.txt");
   创建一个FileWriter对象,该对象一被初始化就必须明确要操作的文件.
   而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将被覆盖掉.
   其实该步就是明确数据要存放的目的地.
 2:fw.write("Hello,World!!!");
  调用write方法,将字符串写入到流中(即写入到缓冲区中).
 3:fw.flush();
  刷新对象中的缓冲区中的数据,将数据刷新到目的地中.
 4:fw.close(); 
  关闭流资源,但是关闭之前会刷新一次内部的缓冲区中的数据.将数据刷新到目的地中.
 5:close和flush的区别:flush刷新后,流可以继续使用,close刷新后,将会关闭流.
 
 6:FileWriter(String fileName, boolean append) 不覆盖已有的文件,并在已有文件的末尾处续写.
           根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
           append为true的时候,将数据写入文件末尾处.
 7:\r\n:回车换行符,在windows中回车换行为\r\n,在Linux中为\n
 
例:
import java .io.*;
public class WriterDemo1 {
 public static void main(String[] args) throws IOException{
  Oprator o=new Oprator();
  o.createFile();
  o.appendDemo();
 }
}
class Oprator{
 public void createFile()throws IOException{
  FileWriter fw=new FileWriter("D:\\Demo1.txt");  //在指定目录创建文件(指定文件名和要存放的位置)
  //调用write方法,将字符串写入到流中.
  fw.write("Hello,World!!!");
  //刷新流对象中的缓冲区中的数据.将数据刷新到目的地中.
  //fw.flush (); 
  
  fw.write("I am coming!!!");   //后写的内容会添加到前面内容后面
  fw.close();    //关闭流资源,但是关闭之前会刷新一次内部的缓冲区中的数据.将数据刷新到目的地中.
 }
 public void appendDemo()throws IOException{
  FileWriter fw=new FileWriter("d:\\test.txt",true);
  fw.write("zhonghu\r\narenmin");
  fw.close();
 }
}

四: Reader类:
  1:FileReader fr=new FileReader("d:\\test.txt");
   创建一个文件读取流对象,和指定名称的文件相关联.
   要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
   
  2:read()一次读取一个字符,而且会自动往下读.
    读取单个字符返回字符的整数形式,范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1

  3:通过字符数组进行读取:
    int read(char[] cbuf)  返回的是字符个数.
           将字符读入数组。
         
例:
public class ReaderDemo1 {
 public static void main(String[] args) throws IOException{
  ReaderTest rt=new ReaderTest();
  //rt.read();   //第一种读取方法
  rt.read2();    //第二种读取方法
 }
}
class ReaderTest{
 //第一种读取方法
 public void read()throws IOException{
  FileReader fr=new FileReader("d:\\test.txt");
  /*while(true){
   int ch=fr.read();
   if(ch==-1){
    break;
   }
   System.out.print((char)ch); //返回是字符的整数形式,强转成字符
  }*/
  //上面代码可以写成:
  int ch=0;
  while((ch=fr.read())!=-1){
   System.out.print((char)ch);
  }
 }
 //第二种读取方法:将字符读到数组.
 public void read2()throws IOException{
  FileReader fr=new FileReader("d:\\test.txt");
  char[] buf=new char[1024];   //用于存放读取的数据
  int num=0;      //用于记录读取数据的个数
  while((num=(fr.read(buf)))!=-1){
   System.out.print(new String(buf,0,num));      //把字符数组转换成字符串输出.
  }
 }
}

五:字符流的缓冲区:
  缓冲区的出现提高了对数据的读写效率.
 1:  缓冲区的出现是为了提高流的操作效率而出现的,所以在创建缓冲区之前,必须要先有流对象.
  对应类:
   BufferedWriter
   BufferedReader
  缓冲区要结合流才可以使用.
  在流的基础上对流的功能进行了增强.
  1:BufferedWriter:
   为了提高字符写入流效率,加入了缓冲区技术.
  只要将需要被提高效率的对象作为参数传递给缓冲区的构造函数即可.
 2:缓冲区中特有方法:
  newLine()换行作用
例:
public class BufferedWriterDemo3{
 public static void main(String[] args) throws IOException{
  BufferedTest t=new BufferedTest();
  t.test();
 }
}
class BufferedTest{
 public void test()throws IOException{
  //创建一个字符写入流对象
  FileWriter fw=new FileWriter("D:\\哈哈.java");
  
  //为了提高字符写入流效率,加入了缓冲区技术.
  //只要将需要被提高效率的对象作为参数传递给缓冲区的构造函数即可.
  BufferedWriter buf=new BufferedWriter(fw);
  buf.write("saljfoj");               //直接用缓冲区操作流对象
  buf.newLine();      //换行作用
  buf.flush();//刷新缓冲区.....记住,只要用到缓冲区,就要记得刷新.
  //其实关闭缓冲区,就是在关闭缓冲区中的流对象.关闭之前会自动刷新缓冲区
  buf.close();
 }
}
2:
 BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
  创建一个读取流对象和文件相关联.
  为了提高效率加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数.
  
 String readLine() 一次读取一行数据,方便于对文本数据的获取。
  返回字符串形式,如果读到最后则返回null
  readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符.

例:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo3 {
 public static void main(String[] args) throws IOException {
  BufferedReaderTest t=new BufferedReaderTest();
  t.test();
 }
}
class BufferedReaderTest{
 public void test()throws IOException{
  //创建一个读取流对象和文件相关联
  FileReader fr=new FileReader("D:\\String.java");
  
  //为了提高效率加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数.
  BufferedReader buf=new BufferedReader(fr);
  
  String str=null;
  while((str=buf.readLine())!=null){
   System.out.println(str);
  }
  buf.close();
 }
}


六:标准异常处理:
import java.io.FileWriter;
import java.io.IOException;

public class WriteDemo2_标准异常处理 {
 public static void main(String[] args) {
  FileWriter fw=null;     //是为了让close()识别
  try{
   fw=new FileWriter("d:\\Demo1.txt");
   fw.write("jfdsjfio");
  }catch(IOException e){
   e.printStackTrace();
  }
  finally{
   try{
    if(fw!=null){
     fw.close();
    }
   }catch(IOException e){
     e.printStackTrace();
   }
  }
 }
}


例: copy一个文件到另一个文件中去.
 思路:
 1:确定源文件.
 2:确定目标文件.
 3:从源文件中获取文件.
 4:把文件内容写入到目标文件中.
 5:关闭源文件和目标文件流

import java.io.*;
public class Practice1 {
 public static void main(String[] args)throws IOException {
  FileReader fr=null;
  FileWriter fw=null;
  try{
   fr=new FileReader("D:\\String.java");
   fw=new FileWriter("D:\\txst.txt");
   char[] ch=new char[1024];
   int num=0;
   while((num=fr.read(ch))!=-1){   //将字符串读取到字符数组中
    fw.write(ch, 0, num);
   }
  }catch(IOException e){
   e.printStackTrace();
  }
  finally{
   try{
    if(fr!=null){
     fr.close();
    }
   }catch(IOException e){
    e.printStackTrace();
   }
   try{
    fw.close();
   }catch(IOException e){
    e.printStackTrace();
   }
   
  }
 }
}

使用缓冲区copy一个文本文件.
1:确定源文件和目标文件
2:创建字符操作流对象和缓冲区对象
3:处理异常
4:复制文件内容
public class Practice3 {
 public static void main(String[] args) {
  PracticeDemo p=new PracticeDemo();
  p.demo();
 }
}
class PracticeDemo{
 public void demo(){
  BufferedReader bufr=null;
  BufferedWriter bufw=null;
  try{
   bufr=new BufferedReader(new FileReader("d:\\String.java"));
   bufw=new BufferedWriter(new FileWriter("d:\\haha.txt"));
   String str=null;
   while((str=bufr.readLine())!=null){  //一次读取一行
    bufw.write(str);
    bufw.newLine();  //回车换行
    bufw.flush();    //刷新缓冲区
   }
  }catch (IOException e){
   throw new RuntimeException("读写失败");
  }
  finally{
   try{
    if(bufr!=null){
     bufr.close();
    }
   }catch(IOException e){
    e.printStackTrace();
   }
   try{
    if(bufw!=null){
     bufw.close();
    }
   }catch(IOException e){
    throw new RuntimeException("关闭失败");
   }
  }
 }
}


七:装饰设计模式:
  当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,
  并提供加强功能,那么自定义的该类称为装饰类.
  装饰类通常会通过构造方法接收被装饰的对象.
  并基于被装饰的对象的功能      BufferedReader就是属于装饰类.
  
  装饰类通常会通过构造方法接收被装饰类的对象,并基于被装饰的对象,提供更强的功能。
  
  
  装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能,
  所以装饰类和被装饰类通常是都属于一个类或接口.
  
 装饰模式比继承要灵活,避免了继承体系的臃肿,而且降低了类与类之间的联系.

例:
class Person{
 public void food(){
  System.out.println("吃饭");
 }
}
class SupPerson{               //定义装饰类
 private Person p;
 SupPerson(Person p){
  this.p=p;
 }
 public void supFood(){
  System.out.println("开胃酒");
  p.food();
  System.out.println("甜点");
  System.out.println("抽烟");
 }
   
}
public class Practice装饰设计模式 {
 public static void main(String[] args) {
  Person p=new Person();
  //p.food();
  SupPerson sp=new SupPerson(p);
  sp.supFood();
 }
}


八:字节流:
基本操作与字符流类相同
但它不仅可以操作字符,还可以操作其他媒体文件
int available() 方法:取得要读取文件的大小.
  可以用此方法定义一个刚刚好的缓冲区,不用再使用循环.
jvm在启动时分配的内存是64M,此方法在使用时要确定要读取的 文件大小不能超过64M.
 
例:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MyOutputStream1 {
 public static void main(String[] args) throws IOException {
  //outStream();
  //inStream1();
  //inStream2();
  //inStream3();
  picture();
 }
 //输入数据
 public static void outStream()throws IOException{       
  FileOutputStream ops=new FileOutputStream("D:\\t.doc");
  String str="qwertyuiop";
  ops.write(str.getBytes());                  //将字符串转换成字节数据写入.
  ops.close();
 }
 //输出方法1:
 public static void inStream1()throws IOException{
  FileInputStream op=new FileInputStream("D:\\t.doc");
  int ch=0;
  while((ch=op.read())!=-1){              //读取单个字节,
   System.out.print((char)ch);        //输出并强制转换成char类型.
  }
  op.close();
 }
 //输入方法2:
 public static void inStream2()throws IOException{
  FileInputStream o=new FileInputStream("D:\\t.doc");
  int ch=0;
  byte buf[]=new byte[1024];
  while((ch=o.read(buf))!=-1){           //将数据读入到字节数组中.
   System.out.print(new String(buf,0,ch));
  }
  o.close();
 }
 //输入方法3:
 public static void inStream3()throws IOException{
  FileInputStream in=new FileInputStream("D:\\t.doc");
  //int available() 方法:取得要读取文件的大小.定义一个刚刚好的缓冲区,不用再使用循环.
  byte[] b=new byte[in.available()];
  in.read(b);      //将文件读取到字节数组中.
  System.out.println(new String(b));
  in.close ();
 }
 public static void picture() throws IOException{      //从D盘赋值一张图片到E盘
  FileInputStream in=new FileInputStream("D:\\Documents\\Pictures\\My Pictures\\families\\110.JPG");
  FileOutputStream out=new FileOutputStream("E:\\哈哈.jpg");
  int ch=0;
  while((ch=in.read())!=-1){
   out.write(ch);
  }
  in.close();
  out.close();
 }
}
例:演示mp3的复制,通过缓冲区.并记录copy时间
 BufferedOutputStream
 BufferedInputStream
 
public class CopyMp3Demo {
 public static void main(String[] args) throws IOException {
  CopyMp3 co=new CopyMp3();
  long start=System.currentTimeMillis();   //记录开始拷贝
  co.copy();
  long end=System.currentTimeMillis();     //记录拷贝结束时间
  System.out.println("拷贝完成:"+(end-start)+"毫秒");
 }
}
class CopyMp3{
 public void copy() throws IOException{
  BufferedInputStream bufi=new BufferedInputStream(new FileInputStream("D:\\Documents\\My Music\\汤灿 - 今宵共举杯.mp3"));
  BufferedOutputStream bufo=new BufferedOutputStream(new FileOutputStream("E:\\汤灿 - 今宵共举杯.mp3"));
  int by=0;
  while((by=bufi.read())!=-1){
   bufo.write(by);
  }
  bufi.close();
  bufo.close();
 }
}

例:自定义字节流缓冲区:
 复制mp3文件
  1:定义数组
  2:定义指针
  3:定义计数器
 
public class Practice_自定义字节流缓冲区 {
 public static void main(String[] args) throws IOException {
  CopyMp31 co=new CopyMp31();
  long start=System.currentTimeMillis();   //记录开始拷贝
  co.copy();
  long end=System.currentTimeMillis();     //记录拷贝结束时间
  System.out.println("拷贝完成:"+(end-start)+"毫秒");
 }
}
class CopyMp31{
 public void copy() throws IOException{
  MyBufferedInputStream bufi=new MyBufferedInputStream(new FileInputStream("D:\\Documents\\My Music\\汤灿 - 今宵共举杯.mp3"));
  BufferedOutputStream bufo=new BufferedOutputStream(new FileOutputStream("E:\\汤灿 - 今宵共举杯.mp3"));
  int by=0;
  while((by=bufi.myRead())!=-1){
   bufo.write(by);
  }
  bufi.myClose();
  bufo.close();
 }
}
class MyBufferedInputStream{
 private InputStream in;
 private byte[] buf=new byte[1024];
 private int pos=0;   //定义指针
 private int count=0; //定义计数器,用于记录读取的个数.
 
 MyBufferedInputStream(InputStream in){
  this.in=in;
 }
 public int myRead() throws IOException{
  if(count == 0){
   count=in.read(buf);//通过in对象读取硬盘上的数据,并存储在buf中.
   if(count<0){
    return -1;
   }
   pos=0;
   byte b=buf[pos];
   count--;   //数组中的元素
   pos++;     //数组下标
   return b&0xff;         //0xff是16进制,十进制为255.
  }else if(count>0){
   byte b=buf[pos];
   count--;
   pos++;
   return b&0xff;
  }
  return -1;
 }
 public void myClose() throws IOException{
  in.close();
 }
}

九:转换流:

readLine方法是字符流BufferedReader类中的方法,而键盘录入的read方法是字节流InputStream的方法.
将字节流对象转成字符流对象,使用转换流InputStreamReader类

InputStreamReader 是字节流通向字符流的桥梁  ,,转换流属于字符流中的.
OutputstreamWriter
 构造:InputStreamReader(InputStream in)向转换流中传字节流对象.
转换流接收字节流,然后作为参数传给字符流.

例:通过键盘录入数据.
当录入一行数据后,就将改行数据进行打印.
如果录入的数据是over,那么停止录入.
Import java.io.*;
public class Practice转换流 {
 public static void main(String[] args) throws IOException {
  /*InputStream in=System.in;  //获取键盘录入对象
  //将字节流对象转换成字符流对象,使用转换流InputStreamReader
  InputStreamReader ist=new InputStreamReader(in);
  //为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
  BufferedReader buf=new BufferedReader(ist);
  */
  //上面三句话可以变为一句最常见的键盘输入写法
  BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));//转换流接收字节流,然后作为参数传给字符流.
    
  /*OutputStream out=System.out;
  //将字节流对象转换成字符流对象,使用转换流InputStreamWriter 
  OutputStreamWriter osw=new OutputStreamWriter(out); 
  BufferedWriter bufw = new BufferedWriter(osw);  
  */
  //上面三行代码可以变为一行最为常见的输出代码
  BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
  
  
  String line=null;
  while((line=buf.readLine())!=null){
   if("over".equals(line)){
    break;
   }
   bufw.write(line.toUpperCase());
   bufw.newLine();    //换行
   bufw.flush();
  }
  buf.close();
 }
}

十:标准输入输出流:
System类中的字段:in,out。
它们各代表了系统标准的输入和输出设备。
默认输入设备是键盘,输出设备是显示器。
System.in的类型是InputStream.对应的是标准输出设备,控制台.
System.out的类型是PrintStream是OutputStream的子类FilterOutputStream 的子类.
 对应的是标准输入:键盘.
 键盘上的回车符也是输入输入范围.
 
 需求:
 通过键盘录入数据.
 当录入一行数据后,就将改行数据进行打印.
 如果录入的数据是over,那么停止录入.
 
import java.io.*;
public class Read_From_KeyBoard {
 public static void main(String[] args) throws IOException {
  InputStream in=System.in;     //从键盘输入数据.
  StringBuilder sb=new StringBuilder();
  
  while(true){
   int ch=in.read();
   if(ch=='\r'){
    continue;
   }
   if(ch=='\n'){
    String s=sb.toString();
    if("over".equals(s)){
     break;
    }
    System.out.println(s.toUpperCase());
    sb.delete(0,sb.length());
   }else{
    sb.append((char)ch);
   }
   
  }
 }
}

十一: 流操作的基本规律:
 最痛苦的就是流对象有很多,不知道该用哪一个?
 通过三个明确来完成:
  明确源和目的:
   源:输入流.InputStream   Reader
   目的:输出流. OutputStream   Writer
 2:操作的数据是否是纯文本.
  是:字符流.
  不是:字节流.
 3:当体系明确后,在明确要使用哪个具体的对象.
  通过设备来进行区分:
   源设备:内存,硬盘,键盘.
   目的设备:内存,硬盘,控制台.
 4:是否需要提高效率.
  BufferedReader,BufferedWriter
 
 扩展:存储时默认的编码表示GBK编码表, 但是想要把数据按照指定的编码表(utf-8),将数据存到文件中.
 FileWriter是使用的默认编码表GBK,但是存储时,需要加入指定的编码表utf-8,而指定编码表只有转换流可以指定.
 所以要使用对象OutputStreamWriter.
 而该转换流对象要接收一个字节输出流,而且还可以操作的文件的字节输出流.FileOutputStream.
 
 OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("d:\\haha.txt","UTF-8"));
 
 
记住:
 转换流的使用,字符和字节之间的桥梁.通常,涉及到字符编码转换时,需要用到转换流.

十二:递归:
方法自己调用自己的形式叫递归。

注意:递归时一定要明确结束条件。

应用场景:
当某一功能要重复使用时。

递归的缺点:
递归的效率比普通循环效率低,容易造成内存溢出,所以要慎用.
stackoverError:内存溢出.


例:
public class FileDemo_列出所有目录下所有内容_递归 {
static int num=0;      //用于记录文件的个数.
public static void main(String[] args) throws IOException { 
File dri=new File("d:\\");
FileWriter fw=new FileWriter(dri);

showDri(dri);
System.out.println(num);
}
public static void showDri(File dri){

System.out.println(dri);
File[] files=dri.listFiles();
for(int x=0;x<files.length;x++){
if(files[x].isDirectory()){
showDri(files[x]);
}else{
System.out.println(files[x]);
}
num++;
}
}
}




十三:Properties类:
    Properties是HashTable的子类.属于Map体系.
System.getProperties();得到系统属性.

String getProperty(String key)  根据键获取值


    1: 通过打印流把数据输出到目的地.
void list(PrintStream out) 
将属性列表输出到指定的输出流(文件)。 
void list(PrintWriter out) 
将属性列表输出到指定的输出流。 
例:Properties prop = new Properties();
   PrintWriter print = new printWriter("D:\\123.txt")
   prop.list(print);


   
    2:  可以把键值对形式的文件内容加载到Properties集合对象中
void load(InputStream inStream) 
从输入流中读取属性列表(键和元素对)。 
void load(Reader reader) 
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 
例:Properties prop = new Properties();
  FileInputStream fis=new FileInputStream("D:\\123.txt");
  prop.load(fis);   将数据从文件中加载到集合对象中.
例:
public class MyProperties {
public static void main(String[] args) throws IOException {
//setAndGet();
LoadDemo();
}
public static void setAndGet(){
Properties prop=new Properties();
prop.setProperty("张三", "34");
prop.setProperty("张四", "24");
System.out.println(prop);

String value = prop.getProperty("张三");//根据键获取值
System.out.println(value);      

Set<String> names = prop.stringPropertyNames();   //取得键值集合
for(String s:names){
System.out.println(s+"..."+prop.getProperty(s));     //根据键取得值
}
}
public static void LoadDemo() throws IOException{
Properties pro=new Properties();
FileInputStream fps=new FileInputStream("D:\\FileList.txt");

pro.load(fps);          //将流中的数据加载进集合.
pro.list(System.out);   //输出集合中的元素.
System.out.println(pro);
fps.close();
}
}


    3:把Properties集合对象中的数据,保存到一个文件中。
void store(OutputStream out, String comments) 
以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 
void store(Writer writer, String comments) 
以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 


例:
public class PropertiesDemo {
public static void main(String[] args) throws IOException {
Demo();
}
public static void Demo() throws IOException{
Properties pro=new Properties();
File file=new File("D:\\count.ini");
if(!file.exists()){
file.createNewFile();
}
FileInputStream fis=new FileInputStream(file);

pro.load(fis);//获取数据, 将文件中的数据加载到集合中.
int count=0;
String value=pro.getProperty("time");

if(value!=null){
count = Integer.parseInt(value);
if(count>=5){
System.out.println("你好,使用次数已到,请付费");
return;
}
}
count++;
pro.setProperty("time", count+"");    //  调用 Hashtable 的方法 put。
FileOutputStream fos=new FileOutputStream(file);
pro.store(fos,"");            
fos.close();
fis.close();
}
}


十四 IO包中的其他类
1:RandomAccessFile
随机访问文件,自身具备读写的方法。
通过skipBytes(int x),seek(int x)来达到随机访问。
2:管道流
PipedInputStream和PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用。
例: import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

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 PipedOutputStream类与PipedInputStream类 {
 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();//启动线程
 }
}


3:打印流
PrintWriter与PrintStream
可以直接操作输入流和文件。
例:
import java.io.* ;
public class PrintDemo03{
 public static void main(String arg[]) throws Exception{
  PrintStream ps = null ;  // 声明打印流对象
  // 如果现在是使用FileOuputStream实例化,意味着所有的输出是向文件之中
  ps = new PrintStream(new FileOutputStream(new File("d:" + File.separator + "test.txt"))) ;
  String name = "王广彬" ; // 定义字符串
  int age = 22 ;    // 定义整数
  float score = 990.356f ; // 定义小数
  char sex = 'M' ;   // 定义字符
  ps.printf("姓名:%s;年龄:%s;成绩:%s;性别:%s",name,age,score,sex) ;
  ps.close() ;
 }
}

4:序列流 
SequenceInputStream
对多个流进行合并。
例:
import java.io.*;
public class SerDemo05{
 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 ;
 }
}
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 ;
 }
}

5:操作对象
ObjectInputStream与ObjectOutputStream
被操作的对象需要实现Serializable (标记接口);
操作基本数据类型
DataInputStream与DataOutputStream
操作字节数组
ByteArrayInputStream与ByteArrayOutputStream
操作字符数组
CharArrayReader与CharArrayWrite
操作字符串
StringReader 与 StringWriter


例:
import java.io.*;
public class DataInputStreamDemo{
 public static void main(String args[]) throws Exception{ // 所有异常抛出
  DataInputStream dis = null ;  // 声明数据输入流对象
  File f = new File("d:" + File.separator + "order.txt") ; // 文件的保存路径
  dis = new DataInputStream(new FileInputStream(f)) ; // 实例化数据输入流对象
  String name = null ; // 接收名称
  float price = 0.0f ; // 接收价格
  int num = 0 ; // 接收数量
  char temp[] = null ; // 接收商品名称
  int len = 0 ; // 保存读取数据的个数
  char c = 0 ; // '\u0000'
  try{
   while(true){
    temp = new char[200] ; // 开辟空间
    len = 0 ;
    while((c=dis.readChar())!='\t'){ // 接收内容
     temp[len] = c ;
     len ++ ; // 读取长度加1
    }
    name = new String(temp,0,len) ; // 将字符数组变为String
    price = dis.readFloat() ; // 读取价格
    dis.readChar() ; // 读取\t
    num = dis.readInt() ; // 读取int
    dis.readChar() ; // 读取\n
    System.out.printf("名称:%s;价格:%5.2f;数量:%d\n",name,price,num) ;
   }
  }catch(Exception e){}
  dis.close() ;
 }
}

十五:字符编码表:
1:字符流的出现为了方便操作字符。
更重要是的加入了编码转换。
通过子类转换流来完成。
InputStreamReader
OutputStreamWriter
在两个对象进行构造的时候可以加入字符集

2:编码表的由来:
计算机只能识别二进制数据,早期由来是电信号。
为了方便应用计算机,让它可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表。
这就是编码表。


3:常见的编码表:
ASCII:美国标准信息交换码。
用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表
用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。
所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符。

4:转换流的编码应用:
可以将字符以指定编码格式存储。
可以对文本数据指定编码格式来解读。
指定编码表的动作由构造函数完成。

5:字符编码:
编码:字符串字->节数组
解码:字节数组->字符串

例:
import java.io.OutputStream ;
import java.io.FileOutputStream ;
import java.io.File ;
public class CharSetDemo02{
 public static void main(String args[]) throws Exception {
  File f = new File("D:" + File.separator + "test.txt") ; // 实例化File类
  OutputStream out = new FileOutputStream(f) ; // 实例化输出流
  byte b[] = "你好,地球".getBytes("ISO8859-1") ; // 转码操作
  out.write(b) ; // 保存
  out.close() ; // 关闭
 }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值