当前位置:网站首页 > Java基础 > 正文

O基础java程序员



一、I/O流概述

  概念:I/O流用来处理设备之间的数据传输。Java对数据的操作是通过流的方式,而操作流的对象都放在IO包中。

  分类

    按操作数据分为:字符流与字节流。

    按流向分为:输入流与输出流。

   IO流常用基类

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

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

注意:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。如FileReader、FileInputStream等。

二、字符流

   FileReader和FileWriter专门用于操作文件。

   创建文件:

     FileWriter fw = new FileWriter("test.txt");

  创建一个FileWriter对象。该对象一被初始化就必须要明确**作的文件。而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。其实该步就是在明确数据要存放的目的地。

     FileWriter fw1 = new FileWriter("test.txt",true);

  创建一个FileWriter对象。传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写(如果没有该文件则会创建一个)。

O基础java程序员     fw.write("abcde");

调用write方法,将字符串写入到流中。

     fw.flush();

   刷新流对象中的缓冲中的数据,为了将数据写入目标文件。如果不刷新文件将一直在缓冲中直到fw关闭。

     fw.close();

关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地中。

  close和flush区别:

  flush刷新后,流可以继续使用,close刷新后,会将流关闭。

   读取文件:

   1、按字符读取

     FileReader fr = new FileReader("demo.txt");

创建一个文件读取流对象,和指定名称的文件相关联。要保证该文件是已经存在的,如果不存在,会发生异常 FileNotFoundException。

1 int ch = 0; 2 while((ch=fr.read())!=-1) 3 { 4 System.out.println((char)ch); 5 } 6 fr.close();

   通过调用读取流对象的read方法。read()一次读一个字符,而且会自动读取下一个。返回的是该字符对应的整数,如果读到流的末尾就返回-1。

   2、按字符数组读取

     FileReader fr = new FileReader("Test.txt");

建立一个流对象,将已存在的一个文件加载进流。

     char[] ch = new char[1024];

创建一个临时存放数据的数组。

1 int num = 0; 2 while((num=fr.read(ch))!=-1) 3 //read(char[])返回的是读到字符个数。如果数据没有超过数组长度if也可以,但如果超出了数组长度就要用while,所以使用while 4 { 5 System.out.println(new String(ch,0,num)); 6 } 7 fr.close();

  通过调用流对象的读取方法将流中的数据读入到字符数组中。返回的是读取到的字符个数。如果到达流的末尾就返回-1.

  IO异常的处理:

创建文件时:

 1 FileWriter fw = null;  2 try  3  {  4 fw = new FileWriter("Test.txt");  5 fw.write("text");  6  }  7 catch (IOException e)  8  {  9  System.out.println(e.toString()); 10  } 11 finally 12  { 13 If(fw!=null) 14 try 15  { 16  fw.close(); 17  } 18 catch (IOException e) 19  { 20  System.out.println(e.toString()); 21  } 22 }

读取文件时:

 1 FileReader fr = null;  2 try  3  {  4 fr = new FileReader("c:\test.txt");  5 char[] buf = new char[1024];  6 int len= 0;  7 while((len=fr.read(buf))!=-1)  8  {  9 System.out.println(new String(buf,0,len)); 10  } 11  } 12 catch (IOException e){ 13 System.out.println("read-Exception :"+e.toString()); 14  } 15 finally 16  { 17 if(fr!=null) 18  { 19 try 20  { 21  fr.close(); 22  } 23 catch (IOException e) 24  { 25 System.out.println("close-Exception :"+e.toString()); 26  } 27  } 28 }

     定义文件路径时,一定要将文件路径书写正确注意''和'/'的区别。在读取文件时,如果文件不存在,否则会抛出异常。

文件复制简易代码:

 1 import java.io.FileReader;  2 import java.io.FileWriter;  3 import java.io.IOException;  4  5 public class CopyFile {  6  7 public static void main(String[] args) throws IOException {  8  9 //创建要写如的文件 10 FileWriter fw = new FileWriter("a.txt"); 11 //读取已有的文件 12 FileReader fr = new FileReader("b.txt"); 13 int ch = 0; 14 while((ch=fr.read()) != -1){ 15  fw.write(ch); 16  } 17  fw.close(); 18  fr.close(); 19  } 20 21 }

     字符流缓冲区:字符流缓冲区BufferedWriter和BufferedReader

   好处:缓冲区的出现提高了对数据的读写效率。缓冲区是为了提高流的操作效率而出现的。所以得先有流对象,缓冲区才会起作用。

  字符写入流缓冲区:BufferedWriter

      该缓冲区中提供了一个跨平台的换行符,newLine()方法。

  字符读取流缓冲区:BufferedReader

   该缓冲区提供了一个一次读一行的方法readLine(),方便于对文本数据的获取。当返回null时,表示读到文件末尾。

     readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。其实现原理还是read()方法。

模拟BufferedReader代码:

 1 import java.io.*;  2 class MyBufferedReader extends Reader  3 {  4 private Reader r;  5 MyBufferedReader(Reader r)  6 {  7 this.r = r;  8 }  9 //可以一次读一行数据的方法。 10 public String myReadLine()throws IOException 11 //该异常应该抛不应try,因为这是一个功能,为了被其它使用者调用,出现的问题也应该由调用者处理 12 { 13 //定义一个临时容器。BufferReader封装的是字符数组。为了演示方便。定义一个StringBuilder容器。因为最终要将数据变成字符串。 14 StringBuilder sb = new StringBuilder(); 15 int ch = 0; 16 while((ch=r.read())!=-1) 17 { 18 if(ch==' ') 19 continue; 20 if(ch==' ') 21 return sb.toString(); 22 else 23 sb.append((char)ch); 24 } 25 if(sb.length()!=0) 26 return sb.toString(); 27 return null; 28 } 29 //覆盖Reader类中的抽象方法。 30 public int read(char[] cbuf, int off, int len) throws IOException 31 { 32 return r.read(cbuf,off,len) ; 33 } 34 public void close()throws IOException 35 { 36 r.close(); 37 } 38 public void myClose()throws IOException 39 { 40 r.close(); 41 } 42 }

     装饰设计模式:

  概念:自定义一个类,将已有对象传入,基于已有的功能,并提供加强功能,该类就称为装饰类。装饰类通常会通过构造方法接收被装饰的对象,并在对象的基础功能上,提供更强的功能。通常情况下,装饰类和被装饰类都会同属于一个接口或者类,是同一体系中的成员。

  装饰和继承的区别:以前是通过继承让每一个子类都具备缓冲功能。那么做继承体系会很复杂,并不利于扩展。现在优化思想。单独描述一下缓冲内容。将需要被缓冲的对象传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。这样继承体系就变得很简单。优化了体系结构。装饰模式比继承要灵活。避免了继承体系臃肿。而且降低了类与类之间的关系。装饰类因为是增强已有对象,它具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是都属于一个体系中的。

装饰类demo:

 1 class Person  2 {  3 public void chifan()  4  {  5 System.out.println("吃饭");  6  }  7 }  8 class SuperPerson  9 { 10 private Person p ; 11  SuperPerson(Person p) 12  { 13 this.p = p; 14  } 15 public void superChifan() 16  { 17 System.out.println("开胃酒"); 18  p.chifan(); 19 System.out.println("甜点"); 20 System.out.println("来一根"); 21  } 22 } 23 class PersonDemo 24 { 25 public static void main(String[] args) 26  { 27 Person p = new Person(); 28 //p.chifan(); 29 SuperPerson sp = new SuperPerson(p); 30  sp.superChifan(); 31  } 32 }

     LineNumberReader类:BufferedReader的子类,跟踪行号的缓冲字符输入流。此类定义了方法setLineNumber(int lineNumber)和getLineNumber(),它们可分别用于设置和获取当前行号。默认情况下,行编号从0开始。

三、字节流

  特点:不但可以操作字节流,还可以字符流等其它流媒体。

  字节流读一个字节的read()方法为什么返回值类型不是byte,而是int?

  因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。所以,为了避免这种情况将读到的字节进行int类型的提升。并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。而在写入数据时,write()方法其实在做强转动作,只写该int类型数据的最低8位。所以,read()方法在做提升,write()方法在做强转。可以保证原数据不变化。

字节流自定义缓冲区:

 1 import java.io.*;  2 class MyBufferedInputStream  3  {  4  private InputStream in;  5 private byte[] buf = new byte[1024*4];  6 private int pos = 0,count = 0;  7  MyBufferedInputStream(InputStream in)  8  {  9 this.in = in; 10 } 11 //一次读一个字节,从缓冲区(字节数组)获取。 12 public int myRead()throws IOException 13 { 14 //通过in对象读取硬盘上数据,并存储buf中。 15 if(count==0){ 16 count=in.read(buf); 17 if(count<0) 18 return -1; 19 pos=0; 20 } 21 byte b=buf[pos]; 22 pos++; 23 count--; 24 return b&255;//将b提升为int型并在前面补0 25 } 26 public void myClose()throws IOException 27 { 28 in.close(); 29 } 30 }

四、转换流

  读取键盘的录入:System.in和System.out,分别代表了系统标准的输入和输出。默认的输入设备是键盘,输出设备是显示器。

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

     System.out:类型是PrintStream,它是 OutputStream 的子类 FilterOutputStream 的子类,默认的输出设备:控制台。

  InputStreamReader 和 OutputStreamWriter:

    InputStreamReader :字节转字符,字节流通向字符流的桥梁。将字节解码为字符,专门用于操作字节流的字符流对象。

      字节流转换为字符流 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

      OutputStreamWriter :字符转字节,字符流通向字节流的桥梁。将字符编码成字节。

      字符流转换为字节流 BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

  注意:转换流的原因是因为它可以指定编码表,它是字符流与字节流之间的桥梁,方便了字符流与字节流之间的操作。

  转换流的应用:字节流处理的是文本数据,即字节流中的数据都是字符时,转成字符流操作更高效。

  流操作的基本规律

    1、明确源和目的。

          源:输入流 InputStream   Reader

        目的:输出流 OutputStream Writer

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

          是:字符流。

          不是:字节流。

     3、明确使用哪个对象后。通过设备来进一步区分:

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

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

  转换流什么时候用?

   转换流是字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。

  注意:可以通过System类的setIn(),setOut()方法对默认设备进行改变。

五、File类

  用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传递给流的构造函数。流对象也能操作文件,但不能操作文件夹和文件的属性信息。流只能操作数据,想要操作被数据封装成的文件的信息,必须使用file对象。

   File类常见方法:

1、创建

      createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。

     mkdir() :只能创建一级文件夹。

      mkdirs():可以创建多级文件夹。

      2、删除。

     delete():删除失败返回false。如果文件正在被使用,则删除不了返回false。

     deleteOnExit():在程序退出时删除指定文件。

3、修改

     renameTo(File dest): 重新命名此抽象路径名表示的文件。有剪切的效果。

4、判断

     canExecute() :判断文件是否可执行。

     exists() :文件是否存在.用流操作对象时,如果文件存在了才能去读取,如果文件不存在流一读就会抛异常。可以先用本方法判断。

   isFile():是否是文件。

     isDirectory():是否是目录。

isHidden():是否是隐藏文件。

isAbsolute():是否是绝对路径。

 5、获取信息

length() :文件大小,不能获取文件夹大小。

lastModified(): 最后一次修改的时间。

listRoots():返回当前的系统盘符。

getName()

getPath()

getAbsolutePath():当路径是绝度路径时,path和AbsolutePath返回的是一样的,当路径是相对路径时,path返回相对路径,AbsolutePath返回的是当前路径的前面加上所属目录的绝对路径。

getParent():getParent()+getName()=getPath()

getAbsoluteFile():File和String可以互换,字符串new一下可以变成对象,对象toString一下变成字符串。

getParentFile()

6、其它

      list() :返回指定路径下的文件和文件夹名称,包括隐藏文件。调用list方法的file对象必须是封装了一个目录,该目录还必须存在。当对象是一个文件时,返回的是null,会造成空指针异常。如果对象是一个空目录,则返回一个长度为0的数组。

listFiles() :返回指定路径下的文件和文件夹对象。不能拿文件夹内的文件。

六、Properties类

   概念:它是Hashtable的子类。具备Map集合的特点,而且它里面存储的键值对都是字符串,是集合中和IO技术相结合的集合容器。

   特点:可以用于键值对形式的配置文件。那么在加载数据时,需要数据有固定格式:键=值。

   常用方法
       load(InputStream inStream):从输入流中读取属性列表(键和元素对)。

     load(Reader reader) :按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。

       list(PrintStream out) :将属性列表输出到指定的输出流。  

     list(PrintWriter out):将属性列表输出到指定的输出流。  

      setProperty(String key, String value) :调用 Hashtable 的方法 put。 改变的是内存中的结果,store方法是将内存中结果保存到文件中。

      getProperty(String key) :用指定的键在属性列表中搜索属性。

      stringPropertyNames() J:返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。   

      store(OutputStream out, String comments) :以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。

      store(Writer writer, String comments): 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符流。
七、字符编码

   字符流的出现是为了方便操作字符,更重要是的加入了编码转换。

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

     ASCII: 美国标准信息交换码。用一个字节的7位可以表示。

     ISO8859-1:拉丁码表,欧洲码表。用一个字节的8位表示。

     GB2312:中国的中文编码表,用两个字节表示。GBK:中国的中文编码表升级,融合了更多的中文文字符号。

     Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode。

     UTF-8:最多用三个字节表示一个字符。一个字节可以的用一个字节,一个字节无法表示的用两个字节,两个字节无法表示的用3个字节,一个字节0开头,两个字节分别用110和10开头,三个字节分别用1110、10和10开头。

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

   1、将“你好”两个字符查指定的utf-8的码表,获取对应的数字,并写入到text.txt文件中。

1 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("text.txt"),"utf-8"); 2 osw.write("你好"); 3 osw.close();

   2、读取硬盘上的文件数据,将获取到的数据查指定utf-8的码表来解析该数据。

1 InputStreamReader isr = new InputStreamReader(new FileInputStream("text.txt"),"utf-8"); 2 char[] buf = new char[10]; 3 int num = isr.read(buf); 4 String s = new String(buf,0,num); 5 System.out.println(s);

     传入编码表的方法都会抛出不支持编码异常(UnsupportedEncodingException)。

  字符编码:

    编码:字符串变成字节数组。

    String-->byte[]: str.getBytes(charsetName);

    解码:字节数组变成字符串。

    byte[]-->String: new String(byte[],charsetName);

版权声明


相关文章:

  • java基础逻辑运算符2024-10-20 22:02:01
  • flink编程基础java2024-10-20 22:02:01
  • 零基础轻松学java 豆瓣2024-10-20 22:02:01
  • 2022 java基础面试题2024-10-20 22:02:01
  • java基础编程题打印2024-10-20 22:02:01
  • java数据基础及程序结构2024-10-20 22:02:01
  • 优秀的Java基础入门教材推荐2024-10-20 22:02:01
  • 多线程java基础2024-10-20 22:02:01
  • java基础语言和内存的区别2024-10-20 22:02:01
  • java 基础开源类库2024-10-20 22:02:01