JavaSE(2)

Java内部类与常用类

学习地内容:

  1. 内部类
  2. Object类
  3. Object类常用方法
  4. 包装类
  5. String类
  6. BigDecimal类

内部类

内部类分类:

  1. 成员内部类
  2. 静态内部类
  3. 局部内部类
  4. 匿名内部类

内部类概念

在一个类的内部再定义一个完整的类

class Body{
    class Head{
        
    }
}

为什么要这样做呢,就比如上面的代码,头是身体的一部分,所以我们把它定义为Body的内部类

特点:

  1. 可以内部类和外部类都会生成一个字节码文件 Body.class Body$Head.class
  2. 内部类可以调用外部类的私有成员
  3. 内部类可以为外部类提高必要组件

成员内部类

在类的内部定义,和实例变量、实例方法 同级别的类

外部类的一个实例部分,创建内部类一定要先创建外部类,通过外部类实例来new内部类对象

Outer outer = new Outer();
Inner inner = outer.new Inner();

//或者可以进行简化
Inner inner = new Outer().new Inner();

当外部类与内部类存在重名属性时,优先访问内部类

对象是内部类对象

inner.show();

在这里插入图片描述

成员内部类不能定义静态成员

但是能包含静态常量

public static final String name = “张三”;

静态内部类

静态内部类级别和外部类相同

不需要通过外部类创建对象,可以直接调用

目的是给外部类提供一些功能

public class Outer{
    private String name = "张三";
    private int  age = 17;
   
    static class Inner{
        private String address = "上海";
        private String phone = "111";
        private static int count = 100;
        public void show(){
            //调用外部类属性,要创建外部类的对象
            Outer outer = new Outer();
            System.out.println(outer.name);
            //调用静态内部类属性
            System.out.println(address);
            //调用静态内部类的静态属性
            System.out.println(Inner.count);
        }
    }
}

创建静态内部类对象

Outer.Inner inner = new Outer.Inner();
inner.show();

只有内部类才能用static修饰

局部内部类

定义在外部类方法里面的类

public class Outer{
    private String name = "张三";
    private int age = 35;
    
    public void show(){
        String address = "深圳";
        //局部内部类不能加任何访问修饰符
        class Inner{
            
        }
    }
}

静态方法内部不能访问非静态属性

因为静态方法出现的时候还没有非静态方法

在这里插入图片描述

Outer outer = new Outer();
outer.show(); //不会打印出任何结果

要想打印出结果应该要在Inner类外面,show()里面加上一段代码

Inner inner = new Inner();
inner.show2();

show2()如何访问局部变量,就是和class Inner同级别的常量address

可以直接访问,但是jdk会直接把他转化成常量

为什么?

因为调用show()的时候,调用完了以后局部变量就释放掉了,但是inner在堆里,所以还存在

同时局部内部类也不能定义静态成员变量,只能是常量,和成员内部类一样。

private static final int AGE = 17;

局部内部类作用范围仅仅在所在方法中

匿名内部类

没有类名的局部内部类(一切特征都与局部内部类相同)

必须继承一个父类或者实现一个接口

定义类、实现类,创建对象的语法合并,只能创建一个该类对象

优点:减少代码量

缺点:可读性较差

也有一个字节码(.class)文件

public interface Usb {
    void service();
}
public class TestUsb {
    public static void main(String[] args) {
        /*Usb usb = new Mouse();

        usb.service();*/

//        //局部内部类
//        class Fan implements Usb{
//            @Override
//            public void service() {
//                System.out.println("连接电脑成功,风扇开始工作了");
//            }
//        }
//        //使用局部内部类创建对象
//        Usb usb = new Fan();
//        usb.service();
//
//        //因为这个类只用一次,这个定义很麻烦,所以用匿名内部类优化

        //匿名内部类
        Usb usb = new Usb(){
            @Override
            public void service() {
                System.out.println("风扇开始工作!");
            }
        };
        usb.service();
    }
}

Object类

Object类是所有列的父类

没有写extends都默认直接继承Object类

否则为间接继承Object类

Object类可以存储任何对象:

  1. 作为参数,可以接收任何对象
  2. 作为返回值可以返回任何对象

Object类中所具有的方法是所有对象都具备的方法

getClass()方法

public final Class<?> getClass(){}

返回引用中存储的实际对象类型

应用:判断两个引用中实际存储对象类型是否一致

public class TestStudent{
    public static void main(String[] args){
        Student s1 = new Student("aaa",20);
        Student s2 = new Student("bbb",30);
        
        Class class1 = s1.getClass();
        Class class2 = s2.getClass();
        if(class1 == class2)
            System.out.println("s1和s2属于同一个类")
    }
}
hashCode()方法

public int hashCode(){}

返回对象的哈希码值

hash值根据对象的地址或字符串或数组根据hash算法计算出来的int类型的数值

一般情况下,相同对象返回相同哈希码

public class TestStudent{
    public static void main(String[] args){
        Student s1 = new Student("aaa",20);
        Student s2 = new Student("bbb",30);
        
        Class class1 = s1.getClass();
        Class class2 = s2.getClass();
        if(class1 == class2)
            System.out.println("s1和s2属于同一个类")
        
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
        Sudent s3 = s1;
        System.out.println(s3.hashCode());
        //s3和s1相同,和s2不同
    }
}
toString()方法

public String toString(){}

返回该对象的字符串表示

可以根据程序需求覆盖(重写),比如展示对象各个属性值

System.out.println(s1.toString());
System.out.println(s2.toString());
打印出来的是 包的名称@hashCode
//Student类中
public String toString(){
    return "Student[name"+name+"age="+age+"]";
}
equals()方法

public boolean equals(Object obj){}

默认实现为(this == obj), 比较两个对象地址是否相同

可进行覆盖,标记连个对象内容是否相同

System.out.println(s1.equals(s2)) //判断地址是否一样

重写equals()

在这里插入图片描述

return false

finalize() 方法

当对象被判定为垃圾对象,JVM自动调用次方法,用以标记垃圾对象,进入回收队列

自动回收:JVM内存耗尽,一次性回收所有垃圾对象

手动回收机制:使用 System.gc(); 通知JVM执行垃圾回收

包装类

什么是包装类?

基本数据类型所对应的引用数据类型

Object类可以统一所有数据,包装类的默认类型是null

在这里插入图片描述

Java.lang 包内

类型转换:装箱和拆箱

类型转换:基本类型与包装类的转换

基本类型数据存在栈中

引用数据类型存放在堆中,栈中只有一个引用,指向堆中

栈中基本数据类型比如说 int a = 10;

要把a放入堆中,这个过程叫装箱

堆中拿到栈里面叫拆箱

  • 装箱:基本类型转换成引用类型
  • 拆箱:引用类型转换为基本类型
public class Demon{
    public static void main(String[] args){
        //装箱操作
        int num1 = 10;
        Integer integer1 = new Integer(num1);
        Integer integer2 = Integer.valueOf(num1);
        
        //拆箱操作
        Integer integer3 = new Integer();
        int num2 = integer3.intValue();
        
        //jdk1.5之后提供自动装箱以及拆箱功能
        int age = 30;
        //自动装箱
        Integer integer = age;
        //自动拆箱
        int age2 = integer;
        
    }
}

基本数据类型与字符串的转换

基本类型转字符串

//1、利用+号
int n1 = 15;
String s1 = n1+"";
//2、使用toString()方法
String s2 = Integer.toString(n1);
String s3 = Integer.toString(n1,16); //转换成16进制的

字符串转基本类型

String str = "150";
//使用Integer.parseXXX()
int n2 = Integer.parseInt(str);
//boolean字符串转基本类型, "true"----->true , 非"true"-------->false

整数缓存区

面试题

public class Demon2{
    public static void main(String[] args){
        Integer integer1 = new Integer(100);
        Integer integer2 = new Integer(100);
        System.out.println(integer1 == integer2);//答案是false,比较的是栈中的地址值
        
    }
}

String

字符串是常量,创建后不可改变

字符串字面值存储在字符串池中,可以共享

String s = “hello”; //字符串池中存储

String s = new String(“hello”); 创建两个对象,堆和池中各创建一个

public static void main(String[] args){
    String name = "hello";
    name = "zhangsan";
    String name2 = "zhangsan";
    
    String str = new String("java");
    String str2 = new String("java");
    System.out.println(str == str2);		//结果是false
    System.out.println(str.equals(str2));	//结果是true
}

在这里插入图片描述

String中的常用方法

  • public int length() 返回字符串长度
  • public char charAt(int index) 根据下标获取字符
  • public boolean contains(Stirng str) 判断当前字符串中是否包含str
String content = "java是世界上最好的语言";
System.out.println(content.length());
System.out.println(content.charAt(0));
System.out.println(content.contains("java"));

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重要方法:

equals() 和 compareTo()

String s1 = "hello";
String s2 = "HeLLo";
System.out.println(s1.equals(s2));
System.out.println(s1.equalsIgnoreCase(s2));	//忽视大小写
String s1 = "abc";
String s2 = "xyz";
System.out.println("s1.compareTo(s2)");		s1与s2第一个字符ASCII码值的差, 97-120 结果是-23
    										第一个一样比第二个

可变字符串(StringBuffer StringBuilder)

String增强类

StringBuffer:可变长字符串,jdk1.0提供,运行效率慢,线程安全

StringBuilder:可变长字符串,jdk5.0提供,运行效率快,线程不安全

这两个类效率比String高,比String节省内存

public static void main(String[] args){
    StringBuffer sb = new StringBuffer();
    //1.append()添加
    sb.append("java天下第一");
    System.out.println(sb.toString());
    sb.append("java真香");
    System.out.println(sb.toString());
    //显示java天下第一
    //java天下第一java真香
    
    //2.insert() 插入
    sb.insert(0,"php");	在什么位置插入
    //3.replace()
    sb.replace(0,4,"phps");		//0到4是索引位置,前闭后开
    //4.delete()
    sb.delete(0,4);			//索引位置,前闭后开
    sb.delete(0,sb.lenght());	//清空
}

StringBuilder和StringBuilder基本一样

BigDecimal类

public class Demon{
    public static void main(String[] args){
        double d1 = 1.0;
        double d2 = 0.9;
        System.out.println(d1-d2); //打印出来的是0.09999999999
        //原因是因为double类型存储的是近似值
    }
}

在需要精确运算的时候double就不能满足要求,这时候我们需要一个精度更加高的类

BigDecimal类(精确计算浮点数)

在java.math包中

BigDecimal创建对象时要传入字符串

BigDecimal bd1 = new BigDecimal("1.0");
BigDecimal bd2 = new BigDecimal("0.9");
//减法
BigDecimal r1 = bd1.subtract(bd2);
System.out.println(r1);

//加法bd1.add(bd2);
//乘法bd1.multiply(bd2);
//除法bd1.divide(bd2)
//divide方法有其他参数(保留几位小数具体查文档)

Data类

Date表示特定瞬间,精确到毫秒。Data类中大多数方法 已经被Calendar类中方法取代

时间单位:

  • 1秒 = 1000毫秒
  • 1毫秒 = 1000微秒
  • 1微秒 = 1000纳秒

很多方法已经过时,具体查jdk文档

Java集合框架

课程目标:

  1. 集合的概念
  2. Collection接口
  3. List接口与实现类
  4. 泛型与工具类
  5. Set接口与实现类
  6. Map接口与实现类

集合的概念

概念:对象的容器,定义了对多个对象进行操作的方法,可实现数组功能

和数组区别:

  • 数组长度固定,集合不固定
  • 集合只能存储引用类型,基本类型要进行装箱操作

位置:java.util.*

Collection接口

在这里插入图片描述

Collection父接口:

在这里插入图片描述

//创建Collection对象
Collection collection = new ArrayList();

//遍历数组元素,不能用for语句,因为Collection对象无下标
//1.可以用增强for
for(Object object:collection){
    System.out.println(object);
}

//2.可以用迭代器(专门用来遍历集合的一种接口)
//注意:迭代过程中不能调用collection remove方法
//可以调用Iterator对象的remove方法
Iterator it = collection.iterator();
While(it.hasNext()){
    String s = (String)it.next();
    System.out.println(s);
    it.remove();
}

List集合

List子接口

特点:有序、有下标,元素可以重复

在这里插入图片描述

//遍历集合中元素
List list = new ArrayList<>();
//1.普通for
//2.增强for
for(Object object:list){
    System.out.println(object);
}

//3.迭代器
Iterator it = list.iterator();
while(it.hasNext()){
    System.out.println(it.next());
}

//4.允许程序员按任意方向遍历列表
//和Iterator区别:可以向前、向后遍历、添加、删除、修改元素
ListIterator lit = list.listIterator();
while(lit.hasNext()){
    System.out.println(lit.nextIndex()+":"+lit.next());
}

while(lit.hasPrevious){
    System.out.println(lit.previousIndex()+":"+lit.previos());
}
//List存储数字元素会自动装箱
List list = new ArrayList<>();

list.add(20);

//删除值为20的元素
list.remove(0);//删除索引为0的元素

//想要表示删除值为20的元素
list.remove(new Integer(20));
//或者
list.remove((Object)20);
//返回子集合
list.subList(1,3);

List实现类

ArrayList 重点

  • 数据结构实现,查询快、增删慢
  • JDK1.2 运行效率快,线程不安全

Vector

  • 数据结构实现,查询快,增删慢 (和ArrayList很像)
  • JDK1.0 运行效率慢,线程安全

LinkedList:

  • 链表结构实现,增删快,查询慢
ArrayList使用

添加元素

ArrayList arrayList = new ArrayList<>();

Student s1 = new Student("刘德华"20);
Student s2 = new Student("张学友",30);

arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);

删除元素:

arrayList.remove(s1);

源码剖析:

DEFAULT_CAPACITY = 10 默认容量

​ 注意:如果没有添加元素,那么是0

elementData 存放元素的数组

size 存放元素个数

Vector使用

创建Vector对象

Vector vector = new Vector<>();

添加元素

vector.add("苹果");
vector.add("草莓");
vector.add("香蕉");

System.out.println("元素个数:"+vector.size());

删除元素:

vector.remove(0);
vector.remove("西瓜");
vector.clear();		//清空

遍历

//用枚举器
Enumeration en = vector.elements();
while(en.hasMoreElements()){
    Object o = en.nextElement();
}

判断

vector.contains("西瓜");
vector.isEmpty();
LinkedList使用

链表实现,增删快,查询慢

LinkedList linkedList = new LinkedList<>();
Student s1 = new Student("张三",21);
Student s2 = new Student("李四",21);
Student s3 = new Student("王五",21);

添加元素

linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);

System.out.println(linkedList.size());
System.out.println(linkedList.toString());

删除元素:

linkedList.remove(s1);
linkedList.clear();

遍历

//1.for遍历
for(int i = 0;i<linkedList.size();i++){
    System.out.println(linkedList.get(i))''
}

//2.增强for
for(Object object:linkedList){
    Student s = (Student)object;
    System.out.println(s.toString());
}

//3.使用迭代器
Iterator it = linkedList.iterator();
while(it.hasNext()){
    Student s = (Student)it.next();
    System.out.println(s.toString());
}

//4.使用列表迭代器
ListIterator lit = linkedList.listIterator();
while(lit.hasNext()){
    //这里面和Iterator一样
}

获取

System.out.println(linkedList.indexOf(s1));//获取位置
ArrayList和LinkedList区别

在这里插入图片描述

泛型(Generic)

Java泛型是jdk1.5引入的一个新特性

其本质是参数化类型

把类型作为参数传递

常见形式:

  1. 泛型类
  2. 泛型接口
  3. 泛型方法

语法:

<T…> T称为类型占位符,表示一种引用类型

好处:

  • 提高代码重用性
  • 防止类型转换异常
  • 提高代码安全性

泛型类

public class MyGeneric<T>{
    //1.创建变量
    T t;
    
    //2.添加方法
    public void show(T t){
        
    }
    //3.泛型作为方法的返回值
    public T get(){
        return t;
    }
}

MyGeneric<Integer> mg1 = new MyGeneric<>();//<>里面一定得是引用类型
MyGeneric<String> mg2 = new MyGeneric<>();

//不同类型的泛型对象不能相互赋值
mg1 = mg2;		//这么写会报错,一个是Integer,一个是String

泛型接口

public interface MyInterface<T>{
    String name = "张三";
    
    T server(T t);
}

public class MyInterfaceImp1 implements MyInterface<String>{
    public String server(String t){
        System.out.println(t);
    }
}
MyInterfaceImp1 mfi1 = new MyInterfaceImp1();

public class MyInterfaceImp2<T> implements MyInterface<T>{
    
}

MyInterfaceImp2 mfi2<String> = new MyInterfaceImp2<>();

泛型方法

public class MyGenericMethod{
    //这里有了<T> 所以参数和函数体内才能右T
    public <T> void show(T t){
        System.out.println("泛型方法");
    }
}

MyGenericMethod mgm = new MyGenericMethod();
mgm.show("中国加油"); //show()方法里面的参数按照传入值的类型决定

泛型集合

见之前用过的各类集合

Set子接口

无序、无下标、不能重复

Set<String> set = new HashSet<>();
set.add("苹果");
set.add("华为");

set.remove("苹果");

//遍历
for(String s:set){
    System.out.println(s);
}

Iterator<String> it = set.iterator();
while(it.hasNext()){
    System.out.println(it.next());
}

实现类

HashSet

  • 基于HashCode计算元素存放位置
  • 当存入的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入
  • 存储结构:哈希表

使用和上面的一样

就是remove不能用index删除,因为没有index

TreeSet

  • 基于排列顺序实现元素不重复
  • 实现了SortedSet接口,对集合元素自动排序
  • 元素对象的类型必须实现Comparable接口,指定排列顺序
  • 通过CompareTo方法确定是否重复元素。

Map接口

在这里插入图片描述

Map接口的特点:

  1. 用于存储任意键值对(Key-Value)
  2. 键:无序,无下标,不允许重复
  3. 值:无序、无下标、允许重复

IO流

java IO流原理

  1. IO技术用于处理设备间数据传输。如读写数据,网络通信
  2. Java程序中,对于数据的输入输出操作以流(stream)的方式进行
  3. java io包下提供了各种流类和接口,用于获取不同种类的数据
    在这里插入图片描述

一本文本文件用字符流

视频、图片用字节流

在以有的流上包一层的叫处理流

上面四个类是抽象类

IO流体系

后缀:InputStream、OutputStream都是字节流

​ Reader、Writer都是字符流

前缀:File的都是节点流,其他都是处理流,除了上图四个

抽象基类:InputStream OutputStream Reader Writer

访问文件: FileInputStream FileOutputStream FileReader FileWriter 这四个都是节点流

缓冲流: BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter

转换流: InputStreamReader OutputStreamWriter

对象流: ObjectInputStream ObjectOutputStream

从FileReader中读取数据

@Test : Junit测试 用于新写的方法的测试,不用创建main方法就能测试出结果

 @org.junit.Test
    public void testFileReader() throws IOException {
        //1.实例化File对象,指明要操作的文件
        File file = new File("Hello.txt");

        //2.提供具体的流
        FileReader fr = new FileReader(file);

        //3.数据读入
        //read()返回读入的一个字符,如果读到文件末尾就返回-1
       int data = fr.read();
       while(data != -1){
           System.out.print((char)data);
           data = fr.read();
       }

       //对上述语句进行语法上的修改
        int data2;
       while((data2 = fr.read()) != -1){
           System.out.println(data2);
       }

       //4.流的关闭操作
        fr.close();

    }

上面这个throws异常做法不好,因为假如第一步没有异常,那么就创建好了流,然后第三步出现异常就会导致抛出异常后边的就不执行了,那么第4步不执行流就没有关闭,会造成资源的浪费

用try catch finally 改进

选中一块区域,ctrl+alt+t调出surrounded with , 快速写try catch finally

 @org.junit.Test
    public void testFileReader()  {
        FileReader fr = null;
        try {
            //1.实例化File对象,指明要操作的文件
            File file = new File("Hello.txt");

            //2.提供具体的流
            fr = new FileReader(file);

            //3.数据读入
            //read()返回读入的一个字符,如果读到文件末尾就返回-1
            int data = fr.read();
            while(data != -1){
                System.out.print((char)data);
                data = fr.read();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.流的关闭操作
            try {
                //假如没有创建流就不用close
                if(fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

第二步出现异常是由于文件找不到

对read()操作升级

步骤:

  1. FIle类的实例化
  2. FileReader流的实例化
  3. 读入的操作
  4. 资源的关闭

大致一样,后面的操作就是第二第三步不一样,第二步流不一样,第三步读入操作会改成写出操作

 @Test
    public void testFIleReader2(){
        FileReader fr = null;
        try {
            //1.File类的实例化
            File file = new File("Hello.txt");

            //2.FileReader流的实例化
            fr = new FileReader(file);

            //3.读入的操作
            //方法一
            //返回每次读入cbuf[]字符的个数,如果达到文件末尾就返回-1
            char[] cbuf = new char[5];
            int len;
            while((len = fr.read(cbuf)) != -1){
                //这么写是错误的
                 //for(int i = 0;i<cbuf.length;i++)
                //错误原因:每次读五个,Hello.txt里面是helloworld123
                //第一次读hello,第二次读world
                //第三次cbuf里面是world,前三个被覆盖成了123,后面两个没动所以是:123ld
                //正确写法
                for(int i = 0;i<len;i++){
                    System.out.print(cbuf[i]);
                }
                //方法二:
                //错误写法
//            String str = new String(cbuf);
//            System.out.print(str);
                //正确写法:
                String str = new String(cbuf,0,len);
                System.out.print(str);
            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

FileReader写出(从内存中写出数据到具体文件中去)

/*
    * 内存中读出数据到硬盘中的文件中
    *
    * 注意:
    * 1.输出操作,对应的File可以不存在 ,如果不存在,在输出过程中会自动创建
    * 2.如果存在,看FileWriter构造器参数是true还是false
    * */
    @Test
    public void testFileWriter() throws IOException {
        //1.提供File对象,指明写出到的文件
        File file = new File("hello1.txt");

        //2.提供FileWriter对象,用于数据的写出,true表示在原有文件上添加
        //false就是覆盖原文件
        FileWriter fw = new FileWriter(file,true);

        //3.写出的操作
        fw.write("I have a dream!\n");
        fw.write("You need to have a dream!");

        //4.流的关闭
        fw.close();
    }

用FileReader和FileWriter实现文本复制

 @Test
    public void testFileReaderFileWriter(){
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //1.创建File类对象
            File srcFile = new File("Hello.txt");
            File destFile = new File("hello2.txt");

            //2.创建输入输出流对象
            fr = new FileReader(srcFile);
            fw = new FileWriter(destFile);

            //3.数据的读入和写出工作
            char[] cbuf = new char[5];
            int len;    //记录每次读入到cbuf数组中数据的长度
            while ((len = fr.read(cbuf)) != -1){
                fw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            //4.流的关闭
            //这里前面的try catch执行了以后后边的也会执行
                try {
                    if(fw != null)
                        fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            try {
                if(fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

用FileReader 和 FileWriter 不能实现图片复制

要用FileInputStream 和 FileOutputStream

FileInputStream和FileOutputStream

FileInputStream读取文本文件(文本文件应该用字符流来读)

文本文件(.txt.java.cpp.c) 非文本文件(.jpg,.PNG,.doc,.ppt)

 @Test
    public void testInputStream(){
        FileInputStream fis = null;
        try {
            File file = new File("Hello.txt");

            fis = new FileInputStream(file);

            byte[] cubf = new byte[5];
            int len;
            while((len = fis.read(cubf)) != -1){
                String str = new String(cubf,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

FileInputStream与FileOutputStream读写非文本文件

@Test
    public void testFileInputOutputStream(){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            File srcFile = new File("5.png");
            File destFile = new File("51.png");

            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);

            byte[] buffer = new byte[5];
            int len;
            while((len = fis.read(buffer)) != -1){
                fos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

FileInputStream 与 FileOutputStream文件复制操作写成方法

 public void copyFile(String srcPath,String destPath){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            File srcFile = new File(srcPath);
            File destFile = new File(destPath);

            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);

            byte[] buffer = new byte[5];    //读取视频一般用new byte[1024]
            int len;
            while((len = fis.read(buffer)) != -1){
                fos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    @Test
    public void testCopyFile(){
        long start = System.currentTimeMillis();
        String srcPath = "5.png";
        String destPath = "52.png";
        copyFile(srcPath,destPath);

        long end = System.currentTimeMillis();

        System.out.println("复制操作花费的时间为"+(end - start));//毫秒
    }

缓冲流

缓冲流是一种处理流

在节点流的基础上进行包装

节点流:FileReader FileWriter FileInputStream FileOutputStream

缓冲流是为了提高文件读写效率

缓冲流:BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter

作用:提升流的读取和写入的效率

缓冲流实现非文本文件复制

 @Test
    public void BufferedStreamTest(){
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1,File对象的创建
            File srcFile = new File("6.png");
            File destFile = new File("6-1.png");
            //2.造流
            //2.1造两个节点流
            FileInputStream fis = new FileInputStream(srcFile);
            FileOutputStream fos = new FileOutputStream(destFile);

            //2.2造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3.复制的细节,读取与写入的过程
            byte[] buffer = new byte[10];
            int len;
            while((len = bis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bis != null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //4.资源关闭
        //要求:先关闭外层的流,再关闭内层的流


        //说明:关闭外层流的时候内层流也会进行关闭
//        fos.close();
//        fis.close();
    }

缓冲流与节点流读写速度对比

提高读写速度的原因是因为内部提供了一个缓冲区

 public void copyFileWithBuffered(String srcPath,String destPath){
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1,File对象的创建
            File srcFile = new File(srcPath);
            File destFile = new File(destPath);
            //2.造流
            //2.1造两个节点流
            FileInputStream fis = new FileInputStream(srcFile);
            FileOutputStream fos = new FileOutputStream(destFile);

            //2.2造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3.复制的细节,读取与写入的过程
            byte[] buffer = new byte[10];
            int len;
            while((len = bis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bis != null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //4.资源关闭
        //要求:先关闭外层的流,再关闭内层的流


        //说明:关闭外层流的时候内层流也会进行关闭
//        fos.close();
//        fis.close();
    }
    @Test
    public void testCopyFileWithBuffered(){
        long start = System.currentTimeMillis();
        String srcPath = "6.png";
        String destPath = "6-1.png";
        copyFileWithBuffered(srcPath,destPath);

        long end = System.currentTimeMillis();

        System.out.println("复制操作花费的时间为"+(end - start));//毫秒
    }

缓冲流练习

加密操作

byte[] buffer = new byte[20];
int len;
while((len = bis.read()) != -1){
    for(int i = 0;i < len;i++){
        byte[i] = (byte)(byte[i] ^ 5);
    }
    
    bos.write(buffer,0,len);
}
m ^n ^n ==m

解密操作:就是再做一遍上述代码就行了

转换流

转换流提供了在字节流与字符流之间的转换

Java API提供了两个转换流

InputStreamReader 将InputStream转换成Reader

OutputStreamWriter 将Writer 转换成OutputStream

字节流中的数据都是字符时,转换成字符流会更加高效

很多时候我们用转换流来处理文件乱码问题

转换流都是字符流,看后面,后面是Reader和Writer就都是字符流

解码:字节、字节数组–>字符数组,字符串

编码:字节、字节数组–>字符数组,字符串

@Test
    public void test1(){
        InputStreamReader isr = null;
        try {
            FileInputStream fis = new FileInputStream("dcbt.txt");
            isr = new InputStreamReader(fis,"UTF-8");

            char[] cubf = new char[20];
            int len;
            while((len = isr.read(cubf)) != -1){
                String str = new String(cubf,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(isr != null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
}
转换流实现文件的读入和写出
@Test
    public void test2()  {
        InputStreamReader isr = null;
        OutputStreamWriter osw = null;
        try {
            File file1 = new File("dcbt.txt");
            File file2 = new File("dcbt_gbk.txt");

            FileInputStream fis = new FileInputStream(file1);
            FileOutputStream fos = new FileOutputStream(file2);
            //以utf-8编码格式读入
            isr = new InputStreamReader(fis,"utf-8");
            //以gbk编码形式写出
            osw = new OutputStreamWriter(fos,"gbk");

            char[] cbuf = new char[20];
            int len;
            while((len = isr.read(cbuf)) != -1){
                osw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(isr != null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if(osw != null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
}

标准输入输出流

System.in :标准 输入流

System.out:标准输出流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值