嘿,程序员——IO流(一)


System:类中的方法和属性都是静态的。

out:标准输出。默认是控制台。

in:标准输入,默认是键盘。

描述系统一些信息。

获取系统属性信息:Properties getProperties();

classSystemDemo
{
         public static void main(String[] args)
         {
                   Propertiesprop=System.getProperties();
                   //因为Properties是Hashtable的子类,也就是Map集合的一个子类对象。
                   //那么可以通过map的方法取出该集合中的元素。
                   //该集合中存储都是字符串,没有泛型定义。
                   /*
                   获取所有属性信息
                   for(Object obj :prop.keySet())
                   {
                            Stringvalue=(String)prop.get(obj);
                            System.out.println(obj+"::"+value);
                   }*/
 
                   //如何在系统中自定义一些特有信息呢?
                   System.setProperty("mykey","myvalue");
                   //获取指定属性信息
                   String value=System.getProperty("os.name");
                   System.out.println("value="+value);
                  
         }
}

Runtime对象

该类并没有提供构造函数,

说明不可以new对象,那么会直接想到该类中的方法都是静态的,

发现该类中海油非静态方法。

说明该类肯定会提供了方法获取本类对象,而且方法是静态的,并返回值类型是本类类型。

由这个特点可以看出该类使用了单例设计模式完成。

该方式是static Runtime getRuntime();

classRuntimeDemo
{
         public static void main(String[]args)throws Exception
         {
                   Runtimer=Runtime.getRuntime();
                   Processp=r.exec("notepad.exe SystemDemo.java");
                   Thread.sleep(4000);
                   p.destroy();
         }
} 

Date:

importjava.util.*;
importjava.text.*;
classDateDemo
{
         public static void main(String[] args)
         {
                   Date d=new Date();
                   System.out.println(d);//打印的时间看不懂,希望有些格式。
                   //将模式封装到SimpleDateFormat对象中
                   SimpleDateFormat sdf=newSimpleDateFormat("yyyy年MM月dd日E hh:mm:ss");
                   //调用format方法让模式格式化指定Date对象
                   String time=sdf.format(d);
                   System.out.println("time="+time);
         }
}

练习:

1、获取任意年的二月有多少天。

   思路:根据指定年设置一个时间是:

   c.set(year,2,1)//某一年的3月1日

   c.add(Calendar.DAY_OF_MONTH,-1);//3月1日。往前推一天,就是2月最后一天

2、获取昨天的现在这个时刻。

   c.add(Calendar.DAY_OF_MONTH,-1);

importjava.util.*;
importjava.text.*;
class  CalendarDemo
{
         public static void main(String[] args)
         {
                   Calendarc=Calendar.getInstance();
                   //c.set(2012,2,23);
                   c.add(Calendar.DAY_OF_MONTH,-18);
                   sop(c.get(Calendar.YEAR)+"年");
                   sop((c.get(Calendar.MONTH)+1)+"月");
                   sop(c.get(Calendar.DAY_OF_MONTH)+"日");//可以用查表法
                   sop("星期"+(c.get(Calendar.DAY_OF_WEEK)-1));
 
         }
         public static void sop(Object obj)
         {
                   System.out.println(obj);
         }
}

Math:

classMathDemo
{
         public static void main(String[] args)
         {
                   Random r=new Random();
                   for(int x=0;x<10;x++)
                   {
                            //intd=(int)(Math.random()*10+1);//随机数random是大于0小于1的随机数
                            intd=r.nextInt(10)+1;
                            sop(d);
                   }
         }
         public static void show()
         {
                   doubled=Math.ceil(16.34);//ceil返回大于指定数值的最小整数
                   doubled1=Math.floor(12.34);//floor返回小于指定数值的最大整数。
                   long l=Math.round(12.54);//四舍五入
                   sop("d="+d);
                   sop("d="+d1);
                   sop("d="+l);
 
                   double d2=Math.pow(2,3);//2的3次方
                   sop("d2="+d2);
         }
         public static void sop(Object obj)
         {
                   System.out.println(obj);
         }
}


IO(Input OutPut)流

IO流用来处理设备之间的数据传输,java对数据的操作是通过流的方式,java用于操作流的对象都在IO包中,流按操作数据分为两种:字节流与字符流。流按流向分为:输入流,输出流。

IO流常用基类:

字节流的抽象基类:InputStream,OutputStream

字符流的抽象基类:Reader,Writer

 

字节流的抽象基类:InputStream,OutputStream

字符流的抽象基类:Reader,Writer

字符流的特点。

既然IO流是用于操作数据的,

那么数据的最常见体现形式是:文件。

 

需求:在硬盘上,创建一个文件并写入一些文字数据。

找一个专门用于操作文件的Writer子类对象,FileWriter,后缀名是父类名,前缀名是该流对象的功能。

importjava.io.*;
class  FileWriterDemo
{
         public static void main(String[] args)
         {
                   //创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。
                   //而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将被覆盖。
                   //其实该步就是在明确数据要存放的目的地。
                   FileWriter fw=newFileWriter("demo.txt");
                   //调用write方法,将字符串写入到流中。
                   fw.write("abcde");
                   //刷新流对象中的缓冲中的数据
                   //将数据刷到目的地中
                   fw.flush();
                   //关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
                   //将数据刷到目的地中,
                   //和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
                   fw.close();
         }
}

IO异常处理方式

importjava.io.*;
classFileWriterDemo2
{
         public static void main(String[] args)
         {
                   FileWriter fw=null;//对象创建在外面
                   try
                   {
                            fw=newFileWriter("demo.txt");
                       fw.write("abcdefg");
                      
                   }
                   catch (IOException e)
                   {
                            System.out.println(e.toString());
                   }
                   finally
                   {
                            try
                            {
                                     if(fw!=null)//判断空指针
                                               fw.close();
                            }
                            catch (IOExceptione)
                            {
                                     System.out.println(e.toString());
                            }
           
                   }
                  
         }
}

读取方法一:

importjava.io.*;
classFileReaderDemo
{
         public static void main(String[] args)throws IOException
         {
                   //创建一个文件读取流对象,和指定名称的文件相关联。
                   //要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
                   FileReader fr=newFileReader("demo.txt");
                   //调用读取流对象的read方法。
                   //read():一次读一个字符,而且会自动往下读。
                   int ch=0;
                   while((ch=fr.read())!=-1)
                   {
                            System.out.println("ch="+(char)ch);
                   }
                   /*
                   while (true)
                   {
                            int ch=fr.read();
                            if(ch==-1)
                                     break;
                      System.out.println("ch="+(char)ch);
                   }*/
                  
                   fr.close();
         }
}

第二种方式:通过字符数组进行读取。

importjava.io.*;
classFileReaderDemo2
{
         public static void main(String[] args)throws IOException
         {
                   FileReader fr=newFileReader("demo.txt");
                   //定义一个字符数组,用于存储读到字符。
                   //该read(char[])返回的是读到字符个数。
                   char[] buf=new char[1024];
                   int num=0;
                   while((num=fr.read(buf))!=-1)
                   {
            System.out.println("num="+num+".."+newString(buf,0,num));
                   }
                  
                   fr.close();
         }
}

将c盘一个文本文件复制到D盘

复制的原理:

其实就是讲C盘下的文件数据存储到D盘的一个文件中

 

步骤:

1、在D盘创建一个文件,用于存储C盘文件中的数据。

2、定义读取流和C盘文件关联。

3、通过不断的读写完成数据存储。

4、关闭资源。

importjava.io.*;
class  CopyTest
{
         public static void main(String[] args)throws IOException
         {
                   copy_2();
         }
 
         public static void copy_2()
         {
                   FileWriter fw=null;
                   FileReader fr=null;
 
                   try
                   {
                            fw=newFileWriter("DateDemo_copy.txt");
                            fr=newFileReader("DateDemo.java");
                            char[] buf=newchar[1024];
                            int len=0;
                            while((len=fr.read(buf))!=-1)
                            {
                                     fw.write(buf,0,len);
                            }
                   }
                   catch (IOException e)
                   {
                            throw newRuntimeException("读写失败");
                   }
                   finally
                   {
                           
                                     try
                                     {
                                               if(fr!=null)
                                               fr.close();
                                     }
                                     catch (IOExceptione)
                                     {
                                     }
                                     try
                                     {
                                               if(fw!=null)
                                               fw.close();
                                     }
                                     catch(IOException e)
                                     {
                                     }
                   }
         }
         //从C盘读一个字符,就往D盘写一个字符。
         public static void copy_1()throwsIOException
         {
                   //创建目的地。
                   FileWriter fw=newFileWriter("DateDemo_copy.txt");
                   //与已有文件关联。
                   FileReader fr=newFileReader("DateDemo.java");
                   int ch=0;
                   while ((ch=fr.read())!=1)
                   {
                            fw.write(ch);
                   }
                   fw.close();
                   fr.close();
         }
} 

字符流的缓冲区

缓冲区的出现提高了对数据的读写效率。


缓冲区的出现是为了提高流的操作效率而出现的。

所以在创建缓冲区之前,必须要先有流对象。

该缓冲区提供了一个换行的方法:newLine();

importjava.io.*;
classBufferedWriterDemo
{
         public static void main(String[] args)throws IOException
         {
                   //创建一个字符写入流对象。
                   FileWriter fw=newFileWriter("buf.txt");
                   //为了提高字符写入流效率,加入缓冲技术。
                   //只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
                   BufferedWriter bufw=newBufferedWriter(fw);
                   bufw.write("abcde");
                   bufw.newLine();//换行
                   bufw.write("ghthhte");
                   //记住,只要用到缓冲区,就要记得刷新。
                   //bufw.flush();
                   //其实关闭缓冲区,就是在关闭缓冲区中的流对象
                   bufw.close();
         }
}

字符读取流缓冲区

该缓冲区提供了一次读一行的方法readLine(),方便对文本数据的获取,

当返回null时,表示读到文件末尾。

importjava.io.*;
classBufferedReaderDemo
{
         public static void main(String[] args)throws IOException
         {
                   //创建一个读取流对象和文件相关联。
                   FileReader fr=newFileReader("buf.txt");
                   //为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数。
                   BufferedReader bufr=new BufferedReader(fr);
                   String line=null;
                   while((line=bufr.readLine())!=null)
                   {
                            System.out.println(line);
                   }
                   bufr.close();
         }
}

装饰设计模式:

当想要对已有的对象进行功能增强时,

可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。

那么自定义的该类称为装饰类。

 

装饰类通常会通过构造方法接收被装饰的对象。

并基于被装饰的对象的功能,提供更强的功能。

classPerson
{
         public void chifan()
         {
                   System.out.println("吃饭");
         }
}
classSuperPerson
{
         private Person p;
         SuperPerson(Person p)
         {
                   this.p=p;
         }
         public void superChifan()
         {
                   System.out.println("开胃酒");
                   p.chifan();
                   System,out.println("甜点");
         }
}
class  PersonDemo
{
         public static void main(String[] args)
         {
                   Person p=new Person();
                   //p.chifan();
                   SuperPerson sp=newSuperPerson(p);
                   sp.superChifan();
         }
}

找到其参数的共同类型,通过多态的形式,可以提高扩展性。

装饰模式比继承要灵活,避免了继承体系臃肿,而且降低了类与类之间的关系。

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是都属于一个体系中。

字符流:

FileReader

FileWriter

BufferedReader

BufferedWriter

 

字节流:

InputStream(读)

OutputStream(写)

需求,想要操作图片数据,这时就要用到字节流。

importjava.io.*;
class  FileStreamDemo
{
         public static void main(String[] args)throws IOException
         {
                   //writeFile();
                   readFile_2();
         }
         public static void readFile_3()throwsIOException
         {
                   FileInputStream fis=newFileInputStream("fos.txt");
                   byte[] buf=newbyte[fis.available()];//定义一个刚刚好的缓冲区,不用再循环了。
                   fis.read(buf);
                   System.out.println(newString(buf));
                   fis.close();
         }
    public static void readFile_2()throwsIOException
         {
        FileInputStream fis=newFileInputStream("fos.txt");
                   byte[] buf=new byte[1204];
                   int len=0;
                   while((len=fis.read(buf))!=-1)
                   {
                            System.out.println(newString(buf,0,len));
                   }
                   fis.close();
         }
         public static void readFile_1()throwsIOException
         {
                   FileInputStream fis=newFileInputStream("fos.txt");
                   int ch=0;
                   while((ch=fis.read())!=-1)
                   {
                            System.out.println((char)ch);
                   }
                   fis.close();
         }
         public static void writeFile()throwsIOException
         {
                   FileOutputStream fos=newFileOutputStream("fos.txt");
                   fos.write("abcde".getBytes());
                   fos.close();
         }
}


字节流缓冲区和自定义缓冲区原理:

import java.io.*;
class MyBufferedInputStream
{
	private InputStream in;
	private byte[] buf=new byte[1024];
	private int pos=0,count=0;
    MyBufferedInputStream(InputStream in)
	{
		this.in=in;
	}
	//一次读一个字节,从缓冲区(字节数组)获取
	public int myRead()throws IOException
	{
		//通过in对象读取硬盘上数据,并存储buf中。
		if(count==0)
		{
			count=in.read(buf);
			if(count<0)
				return -1;
		    pos=0;
		    byte b=buf[pos];
		    count--;
		    pos++;
		    return b&255;//此处对byte类型提升为int型,前面补0,不能补1。
		}
		else
			if(count>0)
		{
			byte b=buf[pos];
			count--;
			pos++;
			return b&255;
		}
		return -1;
	}
	public void myClose()throws IOException
	{
		in.close();
	}
}
class  MyCopy
{
	public static void main(String[] args) throws IOException
	{
		copy_2();
	}
	public static void copy_2()throws IOException
	{
		FileInputStream fis=new FileInputStream("D:\\1.jpg");
		MyBufferedInputStream bufis=new MyBufferedInputStream(fis);
		FileOutputStream fos=new FileOutputStream("D:\\2.jpg");
		BufferedOutputStream bufos=new BufferedOutputStream(fos);
		int by=0;
		while((by=bufis.myRead())!=-1)
		{
			bufos.write(by);
		}
		bufos.close();
		bufis.myClose();
	}
	public static void copy_1()throws IOException
	{
		FileInputStream fis=new FileInputStream("D:\\1.jpg");
		BufferedInputStream bufis=new BufferedInputStream(fis);
		FileOutputStream fos=new FileOutputStream("D:\\2.jpg");
		BufferedOutputStream bufos=new BufferedOutputStream(fos);
		int by=0;
		while((by=bufis.read())!=-1)
		{
			bufos.write(by);
		}
		bufos.close();
		bufis.close();
	}
}
/*
byte类型11111111 -->-1
提升为int类型: 11111111 11111111 11111111 11111111 -->-1
11111111-->提升一个int类型,本来还是-1,是-1的原因是因为在8个1前面补的是1导致的,
那么只要在前面补0,就可以保留原字节数据不变,又可以避免-1的出现。怎么补0?&255
 11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
--------------------------------------
 00000000 00000000 00000000 11111111
*/

读取键盘录入

System.out:对应的是标准输出设备,控制台。

System.in:对应的是标准输入设备,键盘

当录入一行数据后,就将该数据进行打印,

如果录入的数据是over,那么停止录入。

importjava.io.*;
class  ReadIn
{
         public static void main(String[] args)
         {
                   InputStream in=System.in;
                   //int by=in.read();
                   //System.out.println(by);
                   StringBuilder sb=newStringBuilder();
                   while(true)
                   {
                            int ch=in.read();
                            if(ch=='\r')
                                     continue;
                            if(ch=='\n')
                            {
                                     Strings=sb.toString();
                                     if("over".equals(s))
                                               break;
                                     System.out.println(s.toUpperCase());
                                     sb.delete(0,sb.length());
                            }
                            else
                                     sb.append((char)ch);
                   }
         }
}

 

字节流转成字符流使用字符流缓冲中的readLine();

importjava.io.*;
class  TransStreamDemo
{
         public static void main(String[] args)
         {
                   //获取键盘录入对象
                   //InputStream in=System.in;
                   //将字节流对象转成字符流对象,使用转换流,InputStreamReader
                   //InputStreamReader isr= newInputStreamReader(in);
                   //为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
                   //BufferedReader bufr=newbufferedReader(isr);
 
                   //键盘录入最常见写法,记住!
        BufferedReader bufr=newBufferedReader(new InputStreamReader(System.in));
 
                   //OutputStreamout=System.out;
                   //OutputStreamWriter osw=newOutputStreamWriter(out);
                   //BufferedWriter bufw=newBufferedWriter(osw);
                   BufferedWriter bufw=newBufferedWriter(new OutputStreamWriter(System.out));
                   String line=null;
                   while((line=bufr.readLine())!=null)
                   {
                            if("over".equals(line))
                                     break;
                            bufw.write(line.toUpperCase());
                            bufw.newLine();
                            bufw.flush();
                   }
                   bufr.cloase();
         }
}

流操作的基本规律:

通过两个,明确来完成。

1、 明确源和目的。

源:输入流。InputStream Reader

目的:输出流,OutStream Writer

2、 操作的数据是否是纯文本。

是:字符流

不是:字节流。

3、 当体系明确后,再明确使用哪个具体对象。

通过设备来区分:

源设备:内存,硬盘,键盘。

目的设备:内存,硬盘,控制台。

 

分析举例:

需求一:将一个文本文件中的数据存储到另一个文件中,复制文件。

 

源:因为是源,所以使用读取流。InputStream Reader

是不是操作纯文本文件?

是,则选择Reader,明确体系。

明确设备:硬盘,上的一个文件。

Reader体系中可以操作文件的对象是FileReader。

是否需要提高效率:是,加入Reader体系中缓冲区BufferedReader。

FileReader fr=new FileReader(“a.txt”);

BufferedReader bufr=new BufferedReader(fr);

 

目的:OutputStreamWriter

是否是纯文本?

是,则Writer。

设备:硬盘,一个文件。

是否需要提高效率:是,加入Writer体系中缓冲区BufferedWriter。

 

FileWriter fw=new FileWriter(“b.txt”);

BufferedWriter bufw=new BufferedWriter(fw);

 

需求二:将键盘录入的数据保存到一个文件中。

源:InputStreamReader

是不是纯文本?是,Reader

设备:键盘,对应的对象是System.in

System.in对应的是字节流,为了操作键盘文本数据方便,转成字符流按照字符串操作最方便。所以既然明确了Reader,那么就将System.in转成Reader。

用了Reader体系中转换流,InputStreamReader。

InputStreamReader isr=newInputStreamReader(System.in);

需要提高效率吗?需要,BufferedReader

BufferedReader bufr=newBufferedReader(isr);

 

目的:OutputStreamWriter

是否是纯文本?是,Writer

设备:硬盘,一个文件。使用FileWriter。

FileWriter fw=new FileWriter(“c.txt”);

需要提高效率吗?需要。

BufferedWriter bufw=new BufferedWriter(fw);

 

扩展:想要把录入的数据按照指定的编码表(utf—8),将数据存入到文件中。

目的:OutputStreamWriter

是否是纯文本?是,Writer

设备:硬盘,一个文件。使用FileWriter。

但是存储时,需要加入指定编码表,而指定编码表只有转换流可以指定。

所以要使用的对象是OutputStreamWriter。

而该转换流对象要接收一个字节输出流,而且还可以操作文件的字节输出流。FileOutputStream。

OutputStreamWriter osw=newOutputStreamWriter(new FileOutputStream(“d.txt”),”utf-8”);

所以,记住,转换流什么时候使用?字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值