黑马程序员_流、字符编码总结

------- android培训 java培训 、期待与您交流! ----------

一.流的分类:

按操作数据:

字符流: Writer,Reader字符流可以指定编码表。

字节流:InputStream ,OutputStream

按流向:

输入流:Writer,OutputStream

输出流:ReaderInputStream

二、有关对象的注意事项

(1)、FileWrite对象

FileWriterfw=new FileWriter(1.txt);

fw.writer(“aaaaaa”);

fw.flush();//刷新

fw.close();

这句话的注意事项:

1)他会自动创建1.txt 文件,如果已有这个文件,他会覆盖已有的文件。

2)向文件中写入字符串时要进行刷新,因为你写入了流中,进行刷新才会将流中的数据写入文件中。写一次刷一次。

3)close()和flush的区别:close方法是先刷新后关流。

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

写完之后一定要关流。

(2)对异常处理的方式

 public static void main(String[] args)
  {
      FileWriter fw = null;//把引用定义到外边是因为如果你在try里面定义的化,其他代码访问不到。
      try
      {
          fw = newFileWriter("demo.txt");
          fw.write("abcdefg");
      }
      catch (IOException e)
      {
          System.out.println("catch:"+e.toString());
      }
      finally
      {
          try
          {
              if(fw!=null)
                  fw.close(); //close()一定要写在finally里,因为流必须得关,当你初始化成功时。              
          }
          catch (IOException e)
          {
              System.out.println(e.toString());
          }
      }
  }
}

文件的读写

1)  对已有文件的续写

FileWriter fw=new FileWrite(“1.txt”,true);

true代表可以已有数据的末尾追加数据,如果文件没有就创建.

fw.Write(“asd\r\n sfds”);  //\r\n表示在记事本中的换行。

文本文件的读取

FileReader:

1)读中的close()关闭之前不刷新。

2)读取的文件必须存在,否则发生异常。FileNotFoundException

3)文件读取的结尾标志是-1;(一次读单个字符)int read();返回字符对应的ASCII

读取方式一:

 FileReader fr=new FileReader(“1.txt”)
       int num=0;
       while((num=fr.reader()!=-1)
        {
            System.out.println(char(num))
         }

 4)intread(char[ ])返回读到字符的个数。把读到的字符先存到数组中。

  读取方式二:

 FileReader fr=new FileReader(1.txt);
char[]buf=new char[1024];
intnum=0;
while((num=fr.read(buf))!=-1)
{
System.out.println(newString(buf,0,num);
}

复制文件:实际上就是把一个文件的数据写到另一个文件中。

如下代码:

public class CopyText{
    public static voidmain(String[] args) {
        FileReaderfr=null;
        FileWriterfw=null;
            try {
                fr=newFileReader("1.txt");
                fw=newFileWriter("copy_1.txt");
                char[] buf=new char[1024];
                int num=0;
                while((num=fr.read(buf))!=-1)
                {
                    fw.write(buf,0,num);
                }
            }catch(IOException e) {
                e.printStackTrace();
            }finally
            {
                try {
                      if(fr!=null)
                          fr.close();
                }catch(Exception e2) {
                    e2.printStackTrace();
                }
                if(fw!=null)
                    try {
                        fw.close();
                    }catch(IOException e) {
                        e.printStackTrace();
                    }          
            }          
    }
}

缓冲区:BufferReader 、BufferWriter

只要用到缓冲区,就要进行刷新。其实关闭缓冲区就是关闭缓冲区中的流操作。

缓冲区中的特有方法:

BufferWriter中newLine();跨平台的换行符。返回的是终止符之间的数据,并不返回终止符。

BufferReader中readLine();一行一行的读。 

读文件的方法:          

FileReaderfr=new FIleReader(“1.txt”);
BufferedReaderbufr=new BufferedReader(fr);
Stringline=null;
While((line=bufr.readLine()!=null))
{
  System.out.println(line);
}
通过缓冲区中复制文件:

readLine()的原理:无论是读一行还是读取多个字符,其实最终都是在硬盘上一个一个读取。最终使用的还是read方法,一次读一个的方法。

 代码如下:

BufferedReaderbufr=newBufferedReader(newFileReader("1.txt"));
 BufferedWriter bufw=newBufferedWriter(newFileWriter("copy_1.txt"));
       String line=null;
       while((line=bufr.readLine())!=null)
       {
           bufw.write(line);
bufw.newLine();
        bufw.flush();
       }
       bufr.close();
bufw.close();

自定义缓冲区:

装饰设计模式:当想要对已有的对象进行功能的增强,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。自定义的类称为装饰类。

装饰和继承的区别:继承是不断向上抽取的。

                  装饰是在原有类的基础上对他进行包装。

字节流:OutPutStream、InPutStream

用于操作图片数据FileOutPutStream

字节流不用刷新

字节流中读一个字符的方法返回的是字符的ASCII

读一个字节数组的方法返回的是文件中字符的个数

字节流进行图片的拷贝

  代码如下:

 class CopyPic
{
   public static void main(String[] args)
   {
       FileOutputStream fos = null;
       FileInputStream fis = null;
       try
       {
           fos = new FileOutputStream("copy_1.bmp");
           fis = newFileInputStream("1.bmp");
           byte[] buf = new byte[1024];
           int len = 0;
           while((len=fis.read(buf))!=-1)
           {
               fos.write(buf,0,len);
           }
       }
       catch (IOException e)
       {
           throw new RuntimeException("复制文件失败");
       }
       finally
       {
           try
           {
               if(fis!=null)
                   fis.close();
           }
           catch (IOException e)
           {
               throw new RuntimeException("读取关闭失败");
           }
           try
           {
               if(fos!=null)
                   fos.close();
           }
           catch (IOException e)
           {
               throw new RuntimeException("写入关闭失败");
           }
       }
   }
}

字节流特有的方法:

intavailable();用于获得文件中数据的个数。

拷贝图片:实际上就是用字节流读取一个文件然后再写入一个文件中

字节流的缓冲区:

自定义字节流缓冲区:

读的是字节为什么返回的是int型的呢?

读取键盘录入:System.in

注意事项:每读一行就要清空一下缓冲区

转换流:InputStreamReader

BufferReaderbr=new BufferReader(new InputStreamReader(System.in));

把键盘上的录入存入文件。

按照指定的编码表:转换流中可以指定编码表,

OutputStreamWriter();

在gbk中一个中文代表3个字节

在UTF-8中一个中文代表4个字节

改变设备的输入输出System.setIn(); System.getOut();

异常的日志信息:

把控制台上的异常信息写入一个文件中。

系统信息: Properties  getProperties();System.getProperties();

获取系统的配置信息

File的概述

1)构造函数

Filef=new File(“a.txt”);//这个文件不一定存在

separator是默认的目录分割符,具有跨平台性

2)功能

创建: boolean  creatNewFile();在指定位置创建文件,如果该文件已经存在则不创建。

临时文件:creatTempFile()

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

mkdirs();创建多级文件夹。 

删除:boolean delete();

      void deleteOnExit();程序退出时删除文件

判断:boolean  canExecute():判断是否可执行

      Boolean exists();文件是否存在

     isFile();是否是文件

     isDirectory();是否是目录

     判断文件或目录是必须先判断该文件对象封装的内容是否存在

     isAbsolute();判断是否是绝对路径。文件不存在也可判断

获取信息:

      getName();

      getPath();

getParent();//如果没有明确绝对路径的话,返回的是null。

getAbsolutePath()

long  lastModified()//最后一次修改的时间

long  length()

renameTo();重命名。相当于剪切

listRoot();列出了计算机中的盘符

list()列出当前盘符下的所有文件

文件名过滤:

String[]arr=dir.list(new FilenameFilter()
{
  Public Boolean accept(File dir ,String name)
{
Return  name.endsWith(“.bmp”);  
}
}
)

遍历指定目录下的所有文件。利用递归原理

删除带内容的目录:

代码如下:

import  java.io.*;
classFileDemo3
{
public static void main(String[] args)
{
     File dir = newFile("d:\\testdir");
     System.out.println(dir.delete());
}
public static String getLevel(int level)
{
     StringBuilder sb = new StringBuilder();
     sb.append("|--");
     for(int x=0; x<level; x++)
     {
         sb.insert(0,"|  ");
     }
     return sb.toString();
}
public static void showDir(File dir,int level)
{
     System.out.println(getLevel(level)+dir.getName());
     level++;
     File[] files = dir.listFiles();
     for(int x=0; x<files.length; x++)
     {
         if(files[x].isDirectory())
             showDir(files[x],level);
         else
             System.out.println(getLevel(level)+files[x]);
     }
}

总结:主要思想是利用递归原理,当判断是目录时然后再回调知道不是目录为止,这样一层一层的进入。

列出所有的列表,存放到一个文件中:

Properties的应用:

如下代码:

import  java.io.*;
import  java.util.*;
class  JavaFileList
{
public static void main(String[] args) throwsIOException
{
     File dir = new File("d:\\java20");
     List<File> list = newArrayList<File>();
     fileToList(dir,list);
     File file = newFile(dir,"javalist.txt");
     writeToFile(list,file.toString());
}
public static void fileToList(Filedir,List<File> list)
{
     File[] files = dir.listFiles();
     for(File file : files)
     {
         if(file.isDirectory())
             fileToList(file,list);
         else
         {
             if(file.getName().endsWith(".java"))
                 list.add(file);
         }
     }
}
public static void writeToFile(List<File>list,String javaListFile)throws IOException
{
     BufferedWriter bufw =  null;
     try
     {
         bufw = new BufferedWriter(newFileWriter(javaListFile));
        
         for(File f : list)
         {
             String path = f.getAbsolutePath();
             bufw.write(path);
             bufw.newLine();
             bufw.flush();
         }
     }
     catch (IOException e)
     {
         throw e;
     }
     finally
     {
         try
         {
             if(bufw!=null)
                 bufw.close();
         }
         catch (IOException e)
         {
             throw e;
         }
     }
}
}
总结:这个代码主要的思想是:先建立一个集合用于存储所遍历到的目录,遍历目录时用的思想是递归算法,然后再利用流把集合中的数据写到文件中。

1.  getProperty();//获取键值

2.  setProperty();//设置键值

3.  stringPropertyName();//返回的是Set集合

 Properties存取配置文件:

 把文件中的内容加载到Properties中通过load()方法和store()方法进行加载和保存,实际上他就是Map和IO的结合体。

限制一个程序运行的次数。

如下例子:

import java.io.*;
import java.util.*;
class RunCount
{
    publicstatic void main(String[] args) throws IOException
    {
        Propertiesprop = new Properties();
        Filefile = new File("count.ini");
        if(!file.exists())
            file.createNewFile();
        FileInputStreamfis = new FileInputStream(file);
        prop.load(fis);
        intcount = 0;
        Stringvalue = prop.getProperty("time");
        if(value!=null)
        {
            count= Integer.parseInt(value);
            if(count>=5)
            {
                System.out.println("您好,使用次数已到!");
                return;
            }
        }
        count++;
        prop.setProperty("time",count+"");
        FileOutputStreamfos = new FileOutputStream(file);
        prop.store(fos,"");
        fos.close();
        fis.close();
    }
}
总结:思想是定义一个计数器,每运行一次,计数器加1,然后写到配置文件中,因为写入文件的计数器的值不会改变,当你读到五次时就不让读了

IO中的其他流对象:

PrintStream():

字节打印流构造函数可以接受的参数类型:File对象、字符串路径

字节输出流Outputstream

PrintReader();字符打印流 可以接受的参数类型:file对象,字符串路径字节输出流,字符输出流。

合并流:SequenceInputStream:

操作对象的流:ObjectInputStream   ObjectOutputStream

对象的持久化存储;注意事项:

1、 把对象传入并且写到文件中。

2、 对象必须实现Serializable接口

3、 如果想改变类中的内容,在经过ObjectInputStream读时会出现异常,因为当你改变类时与原来的类的序列号不对应了,解决这个问题可以自定义一个固定的序列号,

4、 静态的不能被序列化。

5、 如果不想被序列化,加上transient

管道流:PipedInputStream  PipeOutputStream

RandomAccessFile 随机访问文件的读取和写入

1、 只能操作文件

2、  writeIn();写入四个字节

3、 构造函数中要传入模式

4、 可以调整指针来取出想要的seek(8)

5、 SkipBtes();跳过多少个字节。取下一个

6、 可以随机添加

7、 如果模式为只读r,不会创建文件,回去读取一个已存在的文件,如果为rw模式,文件如果没有会创建

可以实现多线程的下载

操作基本数据类型:DataInputStream DataOutputStream

writeUTF(String str)

一、操作对象的流--------àObjectOutputStreamObjectInputStream

主要的特点是它可以将对象存入文件中。

import java.io.*;
public classObjectTest {
public static voidmain(String[] args) throwsIOException {
 Read();
 Write();
    }
public static void Read() throwsIOException,FileNotFoundException, ClassNotFoundException {
ObjectInputStream objIn=
newObjectInputStream(newFileInputStream("G:\\Workspaces\\MyEclipse8.5\\javabase\\src\\day21\\1.txt"));
         Person p=(Person)objIn.readObject();
         System.out.println(p);
         objIn.close();
    }
    public static void Write() throwsIOException, FileNotFoundException {
        ObjectOutputStreamobjOut=
newObjectOutputStream(new FileOutputStream("G:\\Workspaces\\MyEclipse8.5\\javabase\\src\\day21\\1.txt"));
        objOut.writeObject(new Person("lisi1",23,”kr”));
                 objOut.close();
    }
}
public class Person {
    Stringname;
     transient int age;
static String country=”cn”;
    publicPerson(String name, intage,String country) {
        super();
        this.name = name;
        this.age = age;
       this.country=country;
    }
   public StringtoString()
    {
        return name+"::"+age;
    }
}

这个小程序注意的问题:

1.要想序列化的类必须实现Serializable接口,这个接口没有方法,它相当于一个标记。如果没实现会产生java.io.NotSerializableException异常

2.当你改变Person类中的内容时,就会生成一个新的序列号。当你在读Person对象时,会产生:java.io.InvalidClassException 这个表示无效的类异常,也就是你刚才的序列号和你现在的序列号不同了。

3.这时如果你想要读出改变后的,可以自定义一个序列号,例如:public static final long serialversionUID=40L(这个值是随便写的)

4.当你对非静态的成员不想进行序列化是可以加上关键字:transient

5.  静态的不可以被序列化,因为:静态在方法区中而没在堆内存中

二、管道流 ------àpipedInputStream  pipedOutputStream

不建议使用单线程,因为容易发生死锁,

 pipedInputStream  in=new pipedInputStream();

 pipedOutputStream out=new pipedOutputStream();

 in.connect(out) ;----à把两个流联系起来

三、     RandomAccessFile内部封装了一个数组,可以通过getFilePointer()获取指针的位置,可以通过seek改变指针的位置。

注意:该类只能操作文件

在操作文件时时有模式的,例如r,rw

 如果你写入的模式是r,则表示只能进行读操作

 如果你写入的是rw,则表示既可以进行读操作,又可以进行写操作

RandomAccessFile类可以在任意位置进行读写,因为有skipBytes( )方法,它可以跳过指定的字节数。Seek()可以调整指针的位置

DataInputStream与DataOutputStream

用于操作基本数据类型的数据的流对象。

例如:int num = dis.readInt();

      boolean b = dis.readBoolean();

      double d = dis.readDouble();

注意:它里面有一个特殊的方法:writeUTF(" "),用它写入的数据必须用对应的特定的流读出来,否则会出现乱码。

用于操作字节数组的流对象。

ByteArrayInputStream:在构造的时候,需要接收数据源,。而且数据源是一个字节数组。

ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。

这就是数据目的地。

因为这两个流对象都操作的数组,并没有使用系统资源。

所以,不用进行close关闭

有关流的总结:

流操作的基本规律:

最痛苦的就是流对象有很多,不知道该用哪一个。

通过三个明确来完成。

1,明确源和目的。

  源:输入流。InputStream  Reader

  目的:输出流。OutputStream  Writer。

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

  是:字符流。

  不是:字节流。

3,当体系明确后,在明确要使用哪个具体的对象。

  通过设备来进行区分:

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

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

字符编码:

编码:当把字符串转换成字节时编码

     编码也可以这样理解:当你把认识的转成不认识的时就是编码。

解码:当把字节转换成字符时解码

     解码也可以这样理解:当你把不认识的转成认识的时就是解码

当你解码是出问题或是解错时,可以采用再编一次,解一次的方式进行,也就是说

       String s="你好";
       byte[] b =s.getBytes("gbk");
       String s1 = new String(b,"iso8859-1");
       byte[] b1 =s1.getBytes("iso8859-1");
       System.out.println(new String(b1,"gbk"));

当你用jbk编的码而你不小心用了iso8859-1解的码这时你可以采用你写错的码在进行编一次,然后在进行解码。

总结:当你用到复制文件,键盘录入等等,就一定得有流,流主要记住两大派,字节流和字符流,如果用到编码时,就要想到转换流。

     编码的一个主要思想:当你解码是出问题或是解错时,可以采用再编一次,解一次的方式进行


------- android培训java培训、期待与您交流! ----------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值