06-Java基础-File & I\O

2018-03-14  本文已影响0人  xiaohan_zhang

异常、File类、I\O流

异常

异常就是Java程序在运行过程中出现的错误。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。



从大体来分异常为两块:
1、error---错误 : 是指程序无法处理的错误,表示应用程序运行时出现的重大错误。例如jvm运行时出现的OutOfMemoryError以及Socket编程时出现的端口占用等程序无法处理的错误。
2、Exception --- 异常 :异常可分为运行时异常跟编译异常
1)运行时异常:即RuntimeException及其子类的异常。这类异常在代码编写的时候不会被编译器所检测出来,是可以不需要被捕获,但是程序员也可以根据需要进行捕获抛出。
2)编译异常:RuntimeException以外的异常。这类异常在编译时编译器会提示需要捕获,如果不进行捕获则编译错误。

try
{
   // 程序代码
}catch(ExceptionName e1)
{
   //Catch 块
}

Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。

public static void main(String args[]){
      try{
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
      }
      System.out.println("Out of the block");
   }
/*
以上代码编译运行输出结果如下:
Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block
*/
try{
   // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}
try{
  // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}finally{
  // 程序代码
}

注意下面事项:
1.catch 不能独立于 try 存在。
2.在 try/catch 后面添加 finally 块并非强制性要求的。
3.try 代码后不能既没 catch 块也没 finally 块。
4.try, catch, finally 块之间不能添加任何代码。

    public static void main(String[] args){
        try {
            str2int("a");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void str2int(String str) throws Exception { //这里将得到的异常向外抛出
        try {
            System.out.println(Integer.parseInt(str));

        } catch(NumberFormatException e) {
            //TODO 这里可以做一些处理,处理完成后将异常报出,让外层可以得到异常信息
            throw new Exception("格式化异常");
        }
    }
/*
输出结果
java.lang.Exception: 格式化异常
    at Exception.ExceptionDemo.str2int(ExceptionDemo.java:37)
    at Exception.ExceptionDemo.main(ExceptionDemo.java:25)
*/
public class Person {
    private int age;
 
    public int getAge() {
        return age;
    }

    public void setAge(int age) throws AgeOutOfBoundsException{
        if (age <= 150 && age > 0){
            this.age = age;
        }else {
            throw new AgeOutOfBoundsException("年龄非法");
        }
    }
}


public class ExceptionDemo {

    public static void main(String[] args){
        customExceptionDemo();
    }

    private static void customExceptionDemo(){

        Person person = new Person();
        try {
            person.setAge(-1);
        } catch (AgeOutOfBoundsException e) {
            e.printStackTrace();
        }
    }
}

class AgeOutOfBoundsException extends Exception{
    public AgeOutOfBoundsException() {
    }

    public AgeOutOfBoundsException(String message) {
        super(message);
    }
}
File类
I/O流

IO流用来处理设备之间的数据传输。
Java对数据的操作是通过流的方式。
流按流向分为两种:输入流,输出流。

流按操作类型分为两种:
字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
字符流 : 字符流只能操作纯字符数据,比较方便。

IO流常用父类
字节流的抽象父类:
InputStream
OutputStream
字符流的抽象父类:
Reader
Writer

FileInputStream fileInputStream = new FileInputStream("rr.txt");
int read;
// 每次读一个字节  -1表示结束
while ((read = fileInputStream.read()) != -1){
       System.out.println(read);
}
fileInputStream.close(); // 关闭流释放资源
// 拷贝方式一 不推荐使用
// 如果t.txt文件不存在,就创建一个,否则,在将原文件清空
// FileOutputStream fileOutputStream = new FileOutputStream("/Users/zhangxiaohan/Desktop/t.txt");
// 如果t.txt文件不存在,就创建一个,否则,在原文件基础上增加内容
FileOutputStream fileOutputStream = new FileOutputStream("/Users/zhangxiaohan/Desktop/t.txt", true); 
fileOutputStream.write(65);
fileOutputStream.write(66);
fileOutputStream.write(67);
fileOutputStream.close();

字节数组拷贝之available()方法:
int read(byte[] b)  一次读取一个字节数组
write(byte[] b)    一次写出一个字节数组
available()      获取读的文件所有的字节个数
弊端:有可能会内存溢出 不推荐

// 拷贝方式二  不推荐使用
FileInputStream fis = new FileInputStream("致青春.mp3");
FileOutputStream fos = new FileOutputStream("copy.mp3");
byte[] arr = new byte[fis.available()]; //根据文件大小做一个字节数组
fis.read(arr);          //将文件上的所有字节读取到数组中
fos.write(arr);         //将数组中的所有字节一次写到了文件上
fis.close();
fos.close();
// 第三种拷贝
FileInputStream fis = new FileInputStream("致青春.mp3");
FileOutputStream fos = new FileOutputStream("copy.mp3");
int len;
byte[] arr = new byte[1024 * 8];        //自定义字节数组
        
while((len = fis.read(arr)) != -1) {
    fos.write(arr, 0, len);             //写出字节数组写出有效个字节个数
}
        
fis.close();
fos.close();

BufferedOutputStream
BufferedOutputStream也内置了一个缓冲区(数组)
程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中,直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。

FileInputStream fis = new FileInputStream("致青春.mp3");     //创建文件输入流对象,关联致青春.mp3
BufferedInputStream bis = new BufferedInputStream(fis);    
 //创建缓冲区对fis 包装
FileOutputStream fos = new FileOutputStream("copy.mp3");    //创建输出流对象,关联copy.mp3
BufferedOutputStream bos = new BufferedOutputStream(fos);   //创建缓冲区对fos 包装
        
int b;
while((b = bis.read()) != -1) {     
    bos.write(b);
}
        
bis.close();    //只关包装后的对象即可
bos.close();
字符流

字符流也可以拷贝文本文件, 但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节.
程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流
读取的时候是按照字符的大小读取的,不会出现半个中文
写出的时候可以直接将字符串写出,不用转换为字节数组

FileReader fr = new FileReader("aaa.txt");
int ch;
while((ch = fr.read()) != -1) { //将读到的字符赋值给ch
    System.out.println((char)ch);   //将读到的字符强转后打印
}
        
fr.close();     
FileWriter fw = new FileWriter("aaa.txt");
fw.write("aaa");
fw.close();
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
    
int ch;
while((ch = fr.read()) != -1) {
    fw.write(ch);
}
    
fr.close();
fw.close();
BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));  //创建字符输入流对象,关联aaa.txt
BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));  //创建字符输出流对象,关联bbb.txt
        
int ch;             
while((ch = br.read()) != -1) {     //read一次,会先将缓冲区读满,从缓冲去中一个一个的返给临时变量ch
    bw.write(ch);                   //write一次,是将数据装到字符数组,装满后再一起写出去
}
        
br.close();                         //关流
bw.close();  
BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));
String line;
while((line = br.readLine()) != null) {
    bw.write(line);
    //bw.write("\r\n");                 //只支持windows系统
    bw.newLine();                       //跨平台的
}
        
br.close();
bw.close(); 
LineNumberReader lnr = new LineNumberReader(new FileReader("aaa.txt"));
lnr.setLineNumber(100);             //设置行号,行号从101开始,默认从0开始
while((line = lnr.readLine()) != null) {
    System.out.println(lnr.getLineNumber() + ":" + line);//获取行号
}   
lnr.close(); 
interface Coder {
    public void code();
}
        
class Student implements Coder {
        
    @Override
    public void code() {
        System.out.println("javase");
        System.out.println("javaweb");
    }   
}
        
class SuperStudent implements Coder {
    private Student s;                      //获取到被包装的类的引用
    public ItcastStudent(Student s) {       //通过构造函数创建对象的时候,传入被包装的对象
        this.s = s;
    }
    @Override
    public void code() {                    //对其原有功能进行升级
        s.code();
        System.out.println("数据库");
        System.out.println("ssh");
        System.out.println(".....");
    }   
} 
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8"));  //高效的用指定的编码表读
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"), "GBK"));  //高效的用指定的编码表写
int ch;
while((ch = br.read()) != -1) {
    bw.write(ch);
}       
br.close();
bw.close();
递归

方法自己调用自己。
构造方法不能使用递归调用。
好处:不用知道循环次数。
弊端:不能调研次数过多,容易导致栈内存溢出。

private static int test(int num){

   if (num > 1){
        return num * test(num - 1) ;
    }else {
        return num;
    }
}
SequenceInputStream(InputStream, InputStream)
FileInputStream fis1 = new FileInputStream("a.txt");            //创建输入流对象,关联a.txt
FileInputStream fis2 = new FileInputStream("b.txt");            //创建输入流对象,关联b.txt
SequenceInputStream sis = new SequenceInputStream(fis1, fis2);  //将两个流整合成一个流
FileOutputStream fos = new FileOutputStream("c.txt");           //创建输出流对象,关联c.txt
            
int b;
while((b = sis.read()) != -1) {                                 //用整合后的读
    fos.write(b);                                               //写到指定文件上
}           
sis.close();
fos.close(); 
SequenceInputStream(Enumeration)
FileInputStream fis1 = new FileInputStream("a.txt");    //创建输入流对象,关联a.txt
FileInputStream fis2 = new FileInputStream("b.txt");    //创建输入流对象,关联b.txt
FileInputStream fis3 = new FileInputStream("c.txt");    //创建输入流对象,关联c.txt
Vector<InputStream> v = new Vector<>();                 //创建vector集合对象
v.add(fis1);                                            //将流对象添加
v.add(fis2);
v.add(fis3);
Enumeration<InputStream> en = v.elements();             //获取枚举引用
SequenceInputStream sis = new SequenceInputStream(en);  //传递给SequenceInputStream构造
FileOutputStream fos = new FileOutputStream("d.txt");
int b;
while((b = sis.read()) != -1) {
    fos.write(b);
}
sis.close();
fos.close();
FileInputStream fis = new FileInputStream("a.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b;
while((b = fis.read()) != -1) {
    baos.write(b);
}
            
//byte[] newArr = baos.toByteArray();               //将内存缓冲区中所有的字节存储在newArr中
//System.out.println(new String(newArr));
System.out.println(baos);
fis.close();
// Person
public class Person implements Serializable {
   
}


public class Demo3_ObjectOutputStream {
    /**
    * @param args
    * @throws IOException 
    * 将对象写出,序列化
    */
     public static void main(String[] args) throws IOException {
        Person p1 = new Person("张三", 23);
        Person p2 = new Person("李四", 24);
    //      FileOutputStream fos = new FileOutputStream("e.txt");
    //      fos.write(p1);
    //      FileWriter fw = new FileWriter("e.txt");
    //      fw.write(p1);
    //无论是字节输出流,还是字符输出流都不能直接写出对象
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e.txt"));//创建对象输出流
    oos.writeObject(p1);
    oos.writeObject(p2);
    oos.close();
    }           
}
public class Demo3_ObjectInputStream {
    /**
    * @param args
    * @throws IOException 
    * @throws ClassNotFoundException 
    * @throws FileNotFoundException 
    * 读取对象,反序列化
    */
    public static void main(String[] args) throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e.txt"));
    Person p1 = (Person) ois.readObject();
    Person p2 = (Person) ois.readObject();
    System.out.println(p1);
    System.out.println(p2);
    ois.close();
    }           
}
// 将对象存储在集合中写出
Person p1 = new Person("张三", 23);
Person p2 = new Person("李四", 24);
Person p3 = new Person("马哥", 18);
Person p4 = new Person("辉哥", 20);
    
ArrayList<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
    
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("f.txt"));
oos.writeObject(list);                                  //写出集合对象
    
oos.close();
// 读取到的是一个集合对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("f.txt"));
ArrayList<Person> list = (ArrayList<Person>)ois.readObject();   //泛型在运行期会被擦除,索引运行期相当于没有泛型
                                                                            //想去掉黄色可以加注解                    @SuppressWarnings("unchecked")
for (Person person : list) {
    System.out.println(person);
}
        
ois.close();
PrintStream ps = System.out;
ps.println(97);                 //其实底层用的是Integer.toString(x),将x转换为数字字符串打印
ps.println("xxx");
ps.println(new Person("张三", 23));
Person p = null;
ps.println(p);                  //如果是null,就返回null,如果不是null,就调用对象的toString()
System.setIn(new FileInputStream("a.txt"));             //修改标准输入流
System.setOut(new PrintStream("b.txt"));                //修改标准输出流
            
InputStream in = System.in;                             //获取标准输入流
PrintStream ps = System.out;                            //获取标准输出流
int b;
while((b = in.read()) != -1) {                          //从a.txt上读取数据
ps.write(b);                                        //将数据写到b.txt上
}
            
in.close();
ps.close();
上一篇 下一篇

猜你喜欢

热点阅读