IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java-IO流 -> 正文阅读

[Java知识库]Java-IO流

简单说明

在这里插入图片描述

流的分类:
1.操作数据单位:字节流、字符流2.数据的流向:输入流、输出流3.流的角色:节点流、处理流
二、流的体系结构
抽象基类                    节点流                     缓冲流(处理流的一种)
InputStream              		FileInputStream        BufferedInputStream
Outputstream             		FileOutputStream     BufferedOutputstream
Reader                   			FileReader                BufferedReader
Writer                  			 FileWriter                 BufferedWriter
  • 测试FiLeInputStream和FileoutpuStream的使用
  • 结论:
  • 1.对于文本文件(.txt,.java,.c,.cpp),使用字符流处理
  • 2.对于非文本文件( .jpg,.mp3,.mp4,.avi,.doc,.ppt,…),使用字节流处理
  • 使用字节流FiLeInputStream处理文本文件,可能出现乱码。

处理流之二:转换流的使用
1.转换流:属于字符流

InputStreamReader:将一个字节的输入流转换为字符的输入流OutputStreamwriter:将一个字符的输出流转换为字节的输出流
作用:提供字节流与字符流之间的转换

3.解码:字节、字节数组—>字符数组、字符串
编码:字符数组、字符串—>字节、字节数组

4.字符集
ASCII:美国标准信息交换码。用一个字节的7位可以表示.
IS 08859-1:拉丁码表.欧洲码
表用一个字节的8位表示.
GB2312:中国的中文编码表。最多两个字节编码所有字符
GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的字符,为每一个字符分配唯一的字符码,所有的文字都用两个字节来表示
UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。

注意

public static void main(String[] args){
        //在main方法中创建File对象时是相对于整个工程下创建的
        File file=new File("hello .txt");
        System.out.println(file.getAbsolutePath());

        File file1=new File("Java测试\\hello.txt");
        System.out.println(file1);
    }

File类的使用

  1. File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)

2.File类声明在java.io包下

3.File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用Io流来完成。

4.后续FiLe类的对象常会作为参数传递到流的构造器中,指明读取或写入的"终点".

File类的构造器

public class FileTest {
    /*
    1.创建File类实例
    File(String filePath);
    File(String parentPath,String child);
    File(File    parentPath,String child);

    2.相对路径:相较于某个路径下,指明路径
      绝对路径:包饭盘符在内的文件或文件目录的路径

    3.路径分隔符
    windows:\\
    unix:/
     */

    @Test
    public void test1(){
        //构造器1
        File file1=new File("hello.txt");//相对于当前module
        File file2=new File("E:\\he.txt");//绝对路径

        System.out.println(file1);
        System.out.println(file2);

        //构造器2
        File file3=new File("E:","ff");
        System.out.println(file3);

        //构造器3
        File file4=new File(file3,"hi.txt");
    }

File类中的常用方法

对于文件

 /*
    public string getAbsoLutePath():狄取绝对始在
    public string getPath() :获取路径
    public String getName() :获取名称
    public string getParent():获取上层文件目录路径。若无,返回null
    public long length():获取文件长度(即:字节数)。不能获取目录的长度。
    public Long lastModified() :获取最后一次的修改时间,毫秒值
     */
    @Test
    public void test2(){
        File file1 = new File("hello.txt" );
        File file2 =new File("E:\\ff\\hi.txt");
        System.out.println(file1.getAbsolutePath()) ;
        System.out.println(file1.getPath());
        System.out.println(file1.getName( ));System.out.println(file1.getParent());System.out.println(file1.length());
        System.out.println(new Date(file1.lastModified()));

        System.out.println();

        System.out.println(file2.getAbsolutePath());
        System.out.println(file2.getPath());
        System.out.println(file2.getName( ));System.out.println(file2.getParent( ));
        System. out.println(file2.length());
        System.out.println(file2.lastModified());

    }

对于文件路径

/*
    //如下两个方法适用于文件目录
    public string[ ] list() :获取指定目录下的所有文件或者文件目录的名称数组//打印相对路径
    public File[ ] listFiles():获取指定目录下的所有文件或者文件目录的File数组//打印绝对路径
 */
        @Test
        public void test3(){
            File file= new File("D:\\OneDrive\\桌面\\DemoTest\\Java常用类\\FengSheng\\src");
            String list[] = file.list();
            for(String f:list){
                System.out.println(f);
            }

            System.out.println();

            File[] files=file.listFiles();
            for(File f:files){
                System.out.println(f);
            }
        }

把文件重命名为指定的文件路径

 @Test
        public void test4(){
        /*
        public boolean renameTo(File dest):把文件重命名为指定的文件路径比如: file1.renameTo(file2)为例:
要想保证返回true,需要fiLe1在硬盘中是存在的,且file2不能在硬盘中存在。
         */
        File file2=new File("hello.txt");
        File file1=new File("E:\\ff\\aa.txt");
        boolean rename=file1.renameTo(file2);
        System.out.println(rename);
    }

判断文件属性的方法

/*
    public boolean isDirectory():判断是否是文件目录
    public booLean isFiLe() :判断是否是文件
    public boolean exists() :判断是否存在
    public boolean canRead( ) :判断是否可读
    public boolean canwrite() :判断是否可写
    public boolean isHidden() :判断是否隐藏
     */
    @Test
    public void test5(){
        File file1=new File("hello.txt");
        System.out.println(file1.isDirectory());
        System.out.println(file1.isFile());
        System.out.println(file1.exists());
        System.out.println(file1.canRead());
        System.out.println(file1.canWrite());
        System.out.println(file1.isHidden());

        System.out.println();

        File file2=new File("E:\\ff");

        System.out.println(file2.isDirectory());
        System.out.println(file2.isFile());
        System.out.println(file2.exists());
        System.out.println(file2.canRead());
        System.out.println(file2.canWrite());
        System.out.println(file2.isHidden());
    }

创建和删除文件或文件目录的方法

    /*
    public boolean createNewFile():创建文件。若文件存在,则不创建,返回false
    public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建。
    public boolean mkdirs():创建文件目景。如果上层文件目录不存在,一并创建
    注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目路径下。

    删除磁盘中的文件或文件目录
    public boolean delete()//删除文件或文件夹
    注意事项:Java中的删除不走回收站

     */

    @Test
    public void test6() throws IOException {
        /*
            public boolean createNewFile():创建文件。若文件存在,则不创建,返回false
            删除磁盘中的文件或文件目录
            public boolean delete()//删除文件或文件夹
         */
        File file1=new File("hi.txt");
        if(!file1.exists()){
            file1.createNewFile();
            System.out.println("创建成功");
        }else{
            file1.delete();
            System.out.println("删除成功");
        }
    }

    @Test
    public void test7(){
        //文件目录的创建
        File file1=new File("E:\\ff\\aa");
       //public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建。
        boolean mkdir=file1.mkdir();
        if(mkdir){
            System.out.println("创建成功1");
        }

        File file2=new File("E:\\ff\\aa");
       //public boolean mkdirs():创建文件目景。如果上层文件目录不存在,一并创建
        boolean mkdirs=file2.mkdirs();
        if(mkdirs){
            System.out.println("创建成功2");
        }
    }

FileReader

 @Test
    public void test1()  {
/*
    1. read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
    2.异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理
    3.读入的文件一定要存在,否则就会报FileNotFoundException。
*/
        FileReader fr= null;
        try {
            //实例化File类对象,指明要操作的文件
            File file=new File("hello.txt");

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

            //数据的读入
            //返回读入的一个字符,如果达到文件末尾,返回-1;

        /*
         int data=fr.read();
        while(data!=-1){
            System.out.print((char) data);
            data=fr.read();
        }
         */
            int data;
            while((data=fr.read())!=-1){
                System.out.println((char)data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //流的关闭操作
            try {
                if(fr!=null)
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //对read()操作升级:使用read的重载方法
    @Test
    public void testFileReader1( ){
        FileReader fr= null;
        try {
            //1.FiLe类的实例化
            File file=new File("hello.txt");
            //2.FileReader流的实例化
            fr = new FileReader(file);
            //3.读入的操作
            char[] cbuf=new char[5];
            int len;
            while((len=fr.read(cbuf))!=-1){
               /*
               //方式1:
                for(int i=0;i<len;i++){
                    System.out.print(cbuf[i]);
                }
                */
                //方式2:
                String str=new String(cbuf,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源的关闭
            try {
                if(fr!=null)
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

FileWriter

 @Test
    public void testFilewriter() throws IOException {
            /*
内存中写出数据到硬盘的文件里。

说明:

1.输出操作,对应的File可以不存在的。并不会报异常
2.File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。
FiLe对应的硬盘中的文件如果存在:
如果流使用的构造器是:Filewriter(file,false) / FiLewriter(fiLe):对原有文件的覆盖
如果流使用的构造器是:Filewriter(file,true):不会对原有文件覆盖,而是在原有文件基础上追加新内容

*/
        //.提供FiLe类的对象,指明写出到的文件
        File file = new File(  "hello1.txt" );

        //2.提供FiLewriter的对象,用于数据的写出
        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();
    }

    @Test
    public void test2(){
        /*
        将一个文件中的数据写入到另一个文件中
         */

        FileReader fr= null;
        FileWriter fw= null;
        try {
            File f1=new File("hello.txt");
            File f2=new File("hello1.txt");

            fr = new FileReader(f1);
            fw = new FileWriter(f2);

            char[] cubf=new char[5];

            int len;
            while((len=fr.read(cubf))!=-1){
                fw.write(cubf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fw.close();
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    //注意:   不能使用字符流来处理图片等字节数据

FileInputStream和FileOutputStream

 @Test
    public void testFileInputStream()throws IOException {
        //造文件
        File file=new File("hello.txt");
        //造流
        FileInputStream fis=new FileInputStream(file);

        byte[] by=new byte[5];
        int len;
        while((len=fis.read(by))!=-1){
            String str=new String(by,0,len);
            System.out.print(str);
        }
    }

    @Test
    public void testFileInputOutputStream() throws IOException {
        File file=new File("src\\aa.jpg");

        FileInputStream fis=new FileInputStream(file);
        FileOutputStream fos=new FileOutputStream("少女.jpg");

        byte[] by=new byte[5];
        int len;
        while((len=fis.read(by))!=-1){
            fos.write(by,0,len);
        }

        fis.close();
        fos.close();
    }

缓冲流

  • 处理流之一:缓冲流的使用
  • 1.缓冲流: 套接在已有的流的基础之上
  • BufferedInputStream
  • BufferedoutputStream
  • BufferedReader
  • Bufferedwriter
  • 2.作用:提供流的读取、写入的速度
  • 提高读写速度的原因:内部提供了一个缓冲区
@Test
    public void bufferedStreamTest() throws IOException{
        //1.造文件
        File srcFile = new File(  "src\\bb.jpg");
        File destFile = new File( "呱呱.jpg" );
        //2.造流
        //2.1造节点流
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);
        //2.2造缓冲流
        BufferedInputStream bis = new BufferedInputStream(fis );
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        //读取写入
        byte[] by=new byte[10];
        int len;
        while((len=bis.read(by))!=-1){
            bos.write(by,0,len);
            //bos.flush();//刷新缓冲区
        }

        //要求:先关外层流,在关内层流
        bis.close();
        bos.close();
        //说明:在关闭外层流的同时,内层流也会自动关闭,可以省略内层流的关闭
        fis.close();
        fos.close();
    }

    @Test
    public void test1()throws Exception{
        //创建文件和相应的流
        BufferedReader br=new BufferedReader(new FileReader(new File("hello.txt")));
        BufferedWriter bw=new BufferedWriter(new FileWriter(new File("hello1.txt")));
        //读写操作
        char[] cbuf = new char[ 1024];int len;

        /*
        方式1:
        while( ( len = br.read(cbuf)) != -1) {
            bw.write(cbuf, 0, len);
            //bw.flush();
        }
         */
        //方式2
        String str;
        while((str=br.readLine())!=null){
            //方法1:
//            bw.write(str+"\n");//该方法中无换行符
            //方法2:
            bw.write(str);
            bw.newLine();
        }
        //关闭资源
        bw.close();

        br.close();

    }

转换流(修改文件字符集)

@Test
    public void test1() throws Exception{
        /*
        用指定编码集读取文件
         */
        FileInputStream fis = new FileInputStream("hello.txt");
        //InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符
        // /参数2指明了字符集,具体使用哪个字符集,取决于文件保存时使用的字符集
        InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
            char[] cbuf = new char[ 20];
        int len;
        while((len = isr.read(cbuf)) != -1){
            String str = new String( cbuf,0,len);
            System.out.print(str);
        }
        isr.close();
    }

    @Test
    public void test2() throws Exception{
        /*
        用指定编码集读取文件后,用指定编码集存取文件
         */
        //造文件,造流
        FileInputStream fis=new FileInputStream("hello.txt");
        FileOutputStream fos=new FileOutputStream("hello1.txt");

        InputStreamReader is=new InputStreamReader(fis,"utf-8");
        OutputStreamWriter os=new OutputStreamWriter(fos,"gbk");

        //2.读写过程
        char[]  arr=new char[20];
        int len;
        while((len=is.read(arr))!=-1){
            os.write(arr,0,len);
        }

        //关闭资源
        is.close();
        os.close();
    }

数据流

1 DataInputStream和DataoutputStream
作用:用于读取或写出基本数据类型的变量或字符串

练习:将内存中的字符串、基本数据类型的变量写出到文件中

注意:处理异常的话,仍然应该使用try-catch-finally

 @Test
    public void test1() throws Exception{
        DataOutputStream dos = new DataOutputStream( new FileOutputStream("dd.txt"));
                dos.writeUTF(  "刘建辰");
        dos.flush( );

        dos.writeInt(  23);
        dos.flush( );//刷新操作,将内存中的数据写入文件
        dos.writeBoolean( true);
        dos.flush( );
        dos.close();
    }


    /*
    将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。
     */

    //不是直接打开bb.txt,而是通过如下方法读取到内存中查看
    @Test
    public void test2() throws Exception{
        //1.
        DataInputStream dis = new DataInputStream(new FileInputStream( "D:\\OneDrive\\桌面\\DemoTest\\Java测试\\dd.txt"));
        //2.
        String name = dis.readUTF();int age = dis.readInt();
        boolean isMale = dis.readBoolean();
        System.out.println( "name = " +name);System.out.println( "age = " + age);
        System.out.println( "isMale = " + isMale);
//3.
        dis.close();

    }

标准的输入输出流

1.标准的输入、输出流

1.1
System.in:标准的输入流,默认从键盘输入System.out:标准的输出流,默认从控制台输出

1.2
system类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流

1.3练习:
从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,
直至当输入“e”或者"exit”时,退出程序。

方法一:使用Scanner实现,调用next()返回一个字符串
方法二:使用System.in实现。System.in—>转换流—>BufferedReader的readLine()

@Test
    public void test1()throws Exception{
        InputStreamReader isr=new InputStreamReader(System.in);

        BufferedReader br=new BufferedReader(isr);

        while(true){
            String data=br.readLine();

            if("e".equalsIgnoreCase(data)||"exit".equalsIgnoreCase(data))
                break;

            String upper=data.toUpperCase();
            System.out.println(upper);
        }
        br.close();
    }

自定义输入类

public class MyInput {
    // Read a string from the keyboard
    public static String readString() {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // Declare and initialize the string
        String string = "";

        // Get the string from the keyboard
        try {
            string = br.readLine();

        } catch (IOException ex) {
            System.out.println(ex);
        }

        // Return the string obtained from the keyboard
        return string;
    }

    // Read an int value from the keyboard
    public static int readInt() {
        return Integer.parseInt(readString());
    }

    // Read a double value from the keyboard
    public static double readDouble() {
        return Double.parseDouble(readString());
    }

    // Read a byte value from the keyboard
    public static double readByte() {
        return Byte.parseByte(readString());
    }

    // Read a short value from the keyboard
    public static double readShort() {
        return Short.parseShort(readString());
    }

    // Read a long value from the keyboard
    public static double readLong() {
        return Long.parseLong(readString());
    }

    // Read a float value from the keyboard
    public static double readFloat() {
        return Float.parseFloat(readString());
    }
}

对象流

对象流的使用:
1.ObjectInputStream 2.ObjectOutPutStream
用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
当其它程序获取了这种二进制流,就可以恢复成原来的Java对象

自定义类实现序列化和反序列化

Person需要满足如下的要求,方可序列化
1.需要实现接口: SerializabLe
2.当前类提供一个全局常量: serialVersionUID:
如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自动生成的。
若类的实例变量做了修改,serialVersionUID可能发生变化。故建议,显式声明。
ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
因为static修饰的属性不归类所有,二transient关键字是专门保证其修饰的属性不被序列化

public class Person implements Serializable {

    public static final long serialVersionUID=653213154688678L;

    String name;
    int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

序列化

@Test
    public void test1() throws IOException {
        /*
        序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
        使用ObjectOutputStream实现
         */

        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("object.dat"));

        oos.writeObject(new String("呱呱"));
        oos.flush();

        oos.writeObject(new Person("aaa",18));
        oos.flush();

        oos.close();
    }

反序列化

 @Test
    public void test2()throws Exception{
        /*
        反序列化:将磁盘文件中的对象还原为内存中的一个java对象
        使用ObjectInputStream来实现
         */
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.dat"));

        /*
        读取位置不能颠倒,应与写入时的顺序一致
         */
        String str=(String)ois.readObject();
        Person p=(Person)ois.readObject();

        System.out.println(str);
        System.out.println(p);

        ois.close();
    }

随机存储文件流RandomAccessFile

/*
RandomAccessFile的使用
1.RandomAccessFile直接继承于java.Lang.object类,实现了DataInput和Dataoutput接口

2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流

3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建
如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)|

 */
public class Demo {
    @Test
    public void test1()throws Exception{
        RandomAccessFile raf1 = new RandomAccessFile(new File( "D:\\OneDrive\\桌面\\DemoTest\\Java测试\\少女.jpg"),"r");
        RandomAccessFile raf2 = new RandomAccessFile(new File( "D:\\OneDrive\\桌面\\DemoTest\\Java测试\\少女1.jpg"),  "rw");
        byte[] buffer = new byte[1024];
        int len;
        while(( len = raf1.read ( buffer)) != -1){
            raf2.write(buffer,0,len);
        }
        raf1.close();
        raf2.close();
    }

    @Test
    public void test2() throws Exception{
        RandomAccessFile raf1=new RandomAccessFile(new File("hello.txt"),"rw");

        raf1.write("xyz".getBytes());

        raf1.close();
    }

    @Test
    public void test3()throws Exception{
        RandomAccessFile raf1 = new RandomAccessFile( "hello.txt","rw");
        raf1.seek(3);//将指针调到角标为3的位置
//保存指针3后面的所有数据到StringBuilder中
        StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());

        byte[] buffer = new byte[20];
        int len;
        while((len = raf1.read(buffer)) != -1){
            builder.append(new String(buffer,0,len)) ;
        }
//调回指针,写入“xyz”
        raf1.seek(3);
        raf1.write( "xyz".getBytes());
//将StringBuiLder中的数据写入到文件中
        raf1.write( builder.toString().getBytes());
        raf1.close();
    }
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-06 12:48:23  更:2022-03-06 12:52:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:24:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码