zoukankan      html  css  js  c++  java
  • IO流----File,递归,字节流,字符流

     要把数据持久化存储,就需要把内存中的数据存储到内存以外的其他持久化设备(硬盘、光盘、U盘等)上。

    当需要把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作。

    当把持久设备上的数据读取到内存中的这个动作称为输入(读)Input操作。

    因此把这种输入和输出动作称为IO操作。

    1 File

    有三个实体:

    目录:就是文件夹

    文件

    路径

    Java中把文件或者目录(文件夹)都封装成File对象。并且与平台无关。

    1.1构造方法

     

    1.1.1 File(String pathname)

    例:

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("E:\zyx\javaFile");
    		System.out.println(file);
    	}
    }
    

     

    注意:

    1)导java.io.File这个包

    2)路径要转义写成E:\zyx\java(两个反斜杠)

     

    3)打印file,是默认调用的toString()方法

    4)如果文件不存在,也能构造这个对象,构造方法不会判断该路径的文件或目录是否存在

    5)如果路径写成:E:\zyx\JAVAFile,是一样的,因为windows下不区分大小写

    6windows中,文件名和文件夹名也不能相同

    1.1.2 File(String parent, String child)

    传一个父路径,一个子路径,这样更灵活,可以当成一个变量传过来

    例:

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("E:\zyx","JAVAFile");		
    		System.out.println(file);
    	}
    }
    

    1.1.3 File(File parent, String child)

    可以传过来一个File对象,那么就能用对象的方法了(前面那两个构造方法只能用字符串的方法)

    例:

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("E:\zyx\JAVAFile");
    		File file2=new File(file,"a.txt");		
    		System.out.println(file2);
    	}
    }
    

    三个构造方法,根据具体需求来用,一般用第一个直接传路径的。

    1.2成员变量

     

    这其实是两个变量,一样的用法,只是返回值不同,平时只用String的就可以。 

    Tips

     

    所以写时不要把路径写死,因为与平台无关,可以把\换成File.separator

    例:

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		//与系统有关的路径分隔符
    		String s1=File.pathSeparator;
    		System.out.println(s1); //结果是分号
    		//与系统有关的名称分隔符
    		String s2=File.separator;
    		System.out.println(s2);
    	}
    }
    

     

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("E:"+File.separator+"zyx"+File.separator+"JAVAFile");
    		System.out.println(file);
    	}
    }
    

    1.3普通方法

    1.3.1获取文件相关信息

     

    1)返回文件的绝对路径:

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("E:\zyx\JAVAFile");
    		String path=file.getAbsolutePath();
    		System.out.println(path);
    	}
    }
    

    如果是一个相对的路径:

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("abc");
    		String path=file.getAbsolutePath();
    		System.out.println(path);
    	}
    }
    

    还是输出一个绝对的路径

    注意:相对路径中用/分隔。绝对路径用\

    2)获取文件名和路径

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("E:\zyx\JAVAFile");
    		String name=file.getName(); //获取文件名或文件夹名
    		String path=file.getPath();	//获取绝对路径
    		System.out.println("name:"+name);
    		System.out.println("path:"+path);
    	}
    }
    

    如果是一个相对的路径:

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("demo02");
    		String name=file.getName(); //获取文件名或文件夹名
    		String path=file.getPath();	//获取绝对路径
    		System.out.println("name:"+name);
    		System.out.println("path:"+path);
    	}
    }
    

     

    这个方法只是把路径以字符串的形式输出一下 

    3)isAbsolute()测试抽象路径名是否为绝对路径名  

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("E:\zyx\javaFile");
    		boolean flag=file.isAbsolute();
    		System.out.println(flag);		
    	}
    }

     

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("abc");
    		boolean flag=file.isAbsolute();
    		System.out.println(flag);		
    	}
    }
    

     

    4)length()

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file=new File("E:\zyx\javaFile\eclipse.zip");
    		long size=file.length();
    		System.out.println(size);				
    	}
    }
    

    就是文件的大小:

    1.3.2文件和文件夹的创建、删除

     

    1)创建文件

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\javaFile\a.txt");
    		boolean flag=file.createNewFile();
    		System.out.println(flag);				
    	}
    }
    

      

    如果再执行一遍这个代码,结果就是false了。

    如果这样写:

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\javaFile\a");
    		boolean flag=file.createNewFile();
    		System.out.println(flag);				
    	}
    }
    

    可以看到创建了一个名字为a的文件,其文件类型是“文件”

     

    所以这个方法只能创建文件,不能创建文件夹

    2)删除文件或目录

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\javaFile\a");
    		boolean flag=file.delete();
    		System.out.println(flag);				
    	}
    }
    

    删除的文件或目录不进回收站,直接从硬盘上删除,所以要谨慎调用这个方法。

    3exists() 判断是否存在文件或文件夹

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\java");
    		boolean flag=file.exists();
    		System.out.println(flag);				
    	}
    }
    

    所以进行文件操作时,要先判定一下是否存在

    4isDirectory() 判断文件对象是否是文件夹(目录)

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\java\a");
    		boolean flag=file.isDirectory();
    		System.out.println(flag);					
    	}
    }
    

    5)创建目录

    mkdir()只能创建一个(一级)目录

    例:

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\java\b");	
    		boolean flag=file.mkdir();		
    		System.out.println(flag);					
    	}
    }

     

     

    mkdirs()可以创建多级目录,一级也能创建,所以一般用这个

    例:

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\java\f\a\b\c");			
    		boolean flag=file.mkdirs();
    		System.out.println(flag);				
    	}
    }
    

    总结:三个单词:

    File 文件

    Directory 目录

    Path 路径

    先判断是否存在,再判断是不是目录,不是,那就一定是文件

    因为系统上只有文件或文件夹

    1.3.3 listFiles()方法

    获取一个目录中的所有文件或者目录中的文件夹:

     

    1

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\java");		
    		String[] files=file.list();
    		for(String s:files){
    			System.out.println(s);
    		}			
    	}
    }
    

    2

    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\java");
    		File[] files=file.listFiles();
    		for(File f:files){
    			System.out.println(f);
    		}			
    	}
    }
    

    注意:在获取指定目录下的文件或者文件夹时必须满足下面两个条件

    1)指定的目录必须是存在的,

    2)指定的必须是目录。否则容易引发返回数组为null,出现NullPointerException

     

    1.3.4文件过滤器

     

    例:

    import java.io.File;
    import java.io.FileFilter;
    
    public class MyFileter implements FileFilter{
    	public boolean accept(File pathname) {		
    		return pathname.getName().toLowerCase().endsWith(".java"); //转小写,以.java结尾		
    	}
    }
    
    import java.io.File;
    import java.io.IOException;
    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file=new File("E:\zyx\java");
    		File[] files=file.listFiles(new MyFileter());
    		for(File f:files){
    			System.out.println(f);
    		}
    	}
    }
    

     

    图说明:

    每个文件都传进accept方法中,符合的,放入files数组中

    listFiles调用的accept方法

    2递归

    2.1递归概述

    指在当前方法内调用自己的这种现象

    1

    public class Demo04 {
    	public static void main(String[] args) {
    		System.out.println(getSum(3));
    	}	
    	//递归
    	public static int getSum(int n){
    		if(n==1){
    			return 1;
    		}
    		return n+getSum(n-1);
    	}	
    }
    

     

    图说明:

     

    2100的阶乘 (100!也就是100*99*98*...1

    import java.math.BigInteger;
    public class Test {
    	public static void main(String[] args) {
    		System.out.println(getSum(100));		
    	}	
    	//递归求阶乘
    	public static BigInteger getSum(Integer n){
    		BigInteger big=new BigInteger(n.toString());
    		if(n==1){
    			return new BigInteger("1");
    		}
    		return big.multiply(getSum(n-1));		
    	}
    }
    

    自己调用自己,但是要给出口,

    否则会栈内存溢出,

    递归次数不要太多,还是会溢出,

    2.2递归打印所有子目录中的文件路径

    import java.io.File;
    public class FileTest {
    	public static void main(String[] args) {
    		File file = new File("E:\zyx\java");
    		getFileAll(file);
    	}
    
    	// 获取指定目录以及子目录中的所有的文件
    	public static void getFileAll(File file) {
    		File[] files = file.listFiles();
    		// 遍历当前目录下的所有文件和文件夹
    		for (File f : files) {
    			// 判断当前遍历到的是否为目录
    			if (f.isDirectory()) {
    				// 是目录,继续获取这个目录下的所有文件和文件夹
    				getFileAll(f);
    			} else {
    				// 不是目录,说明当前f就是文件,那么就打印出来
    				System.out.println(f);
    			}
    		}
    	}
    }
    

    2.3递归过滤文件(包括子目录)

    import java.io.File;
    import java.io.FileFilter;
    
    public class MyFileter implements FileFilter{
    	public boolean accept(File pathname) {
    		if(pathname.isDirectory()){
    			return true;
    		}
    		return pathname.getName().toLowerCase().endsWith(".java");
    	}
    }
    
    import java.io.File;
    
    public class Demo05 {
    	public static void main(String[] args) {
    		File file=new File("E:\zyx\java");
    		getFile(file);
    	}
    	
    	//递归加过滤
    	public static void getFile(File dir){		
    		File[] files=dir.listFiles(new MyFileter());		
    		for(File f:files){
    			//如果是文件夹,则调用自己
    			if(f.isDirectory()){
    				getFile(f);
    			}else{
    				System.out.println(f);
    			}			
    		}
    	}
    }
    

    图说明:

     

    3字节流

    3.1字节输出流OutputStream

    OutputStream此抽象类是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法。

    输出流中定义都是写write方法:

     

    3.1.1 FileOutputStream

    OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。 

    构造方法:

    例:

    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		// 创建字节输出流对象
    		FileOutputStream fos = new FileOutputStream("E:\zyx\java\demo.txt");
    		// 写字节
    		fos.write(100);
    		fos.write(49);
    		fos.write(48);
    		fos.write(48);
    		// 释放资源
    		fos.close();
    	}
    }
    

    练习时可以Throws抛异常:

     

    创建的文件对象,如果文件不存在,会创建一个,如果有,则覆盖 

    write写时,底层会转换成二进制,写进也是二进制,但是是txt文本文件,所以走ascii表,解析成可以看懂的。

    写字节数组:

    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		// 创建字节输出流对象
    		FileOutputStream fos = new FileOutputStream("E:\zyx\java\demo.txt");
    		// 写字节数组
    		byte[] bytes = { 97, 98, 99, 100 };
    		fos.write(bytes);		
    		// 释放资源
    		fos.close();
    	}
    }
    

    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		// 创建字节输出流对象
    		FileOutputStream fos = new FileOutputStream("E:\zyx\java\demo.txt");
    		// 写字节数组
    		byte[] bytes = { 97, 98, 99, 100 };		
    		fos.write(bytes,1,1);
    		//fos.write("字符串转成字节数组".getBytes());
    		// 释放资源
    		fos.close();
    	}
    }
    

    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		// 创建字节输出流对象
    		FileOutputStream fos = new FileOutputStream("E:\zyx\java\demo.txt");
    		// 写字节数组		
    		fos.write("字符串转成字节数组".getBytes());
    		// 释放资源
    		fos.close();
    	}
    }
    

    Tips:

    1)一个字符是两个字节

    2)文本文件:用txt打开可以看懂,就是文本文件。看不懂的就是字节文件。

    3.1.2给文件中续写和换行

    1)续写:

     

    2) 换行

    例:

    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		// 创建字节输出流对象
    		FileOutputStream fos = new FileOutputStream("E:\zyx\java\demo.txt", true);
    		// 写字节数组
    		byte[] bytes = { 97, 98, 99, 100 };
    		fos.write(bytes);
    		fos.write(bytes, 1, 1);
    		fos.write("hello,java".getBytes());
    		// 换行
    		fos.write("
    hello,java".getBytes());
    		// 释放资源
    		fos.close();
    	}
    }
    

    3.1.3 IO异常的处理

      

    处理:

    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Demo02 {
    	public static void main(String[] args) {
    		//创建字节输出流对象
    		FileOutputStream fos=null;
    		try {
    			//创建字节输出流对象
    			fos=new FileOutputStream("E:\zyx\java\test.txt");
    			fos.write("你好".getBytes());			
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    			//如果发生异常,中止程序
    			throw new RuntimeException();
    		}finally{
    			//释放资源
    			try {
    				if(fos!=null)
    					fos.close(); //如果创建时就发生异常,则没必要关了
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    				throw new RuntimeException();
    			}
    		}		
    	}
    }
    

    说明:

    1FileNotFoundException异常是IOException异常的子类,所以抛一个IO异常就可以

    2throw new RuntimeException();这句:如果下面还有写入操作,那么上面发生异常,则不能再走了,就加一个程序终止

    3.2字节输入流InputStream

    InputStream此抽象类是表示字节输入流的所有类的超类。定义了字节输入流的基本共性功能方法。

     

    int read():读取一个字节并返回,没有字节返回-1.

    int read(byte[]): 读取一定量的字节数,并存储到字节数组中,返回读取到的字节数。

     

    3.2.1 FileInputStream

     

    构造方法:

     

    3.2.2读取数据read()方法

     

    例:

    import java.io.FileInputStream;
    import java.io.IOException;
    
    public class MyTest2 {
    	public static void main(String[] args) throws IOException {
    		FileInputStream fis=new FileInputStream("E:\zyx\java\demo.txt");
    		int len=0;
    		while((len=fis.read())!=-1){
    			System.out.print((char)len);
    		}
    		fis.close();
    	}
    }
    

    Tipsread()循环,要用一个变量len来做判断,不然还会往后读,和之前学的next()类似。

    3.2.3读取数据read(byte[])方法

     

    数组长度一般以1024为单位

    例:

    import java.io.FileInputStream;
    import java.io.IOException;
    
    public class MyTest2 {
    	public static void main(String[] args) throws IOException {
    		FileInputStream fis=new FileInputStream("E:\zyx\java\demo.txt");
    		//创建数组
    		byte[] bytes=new byte[2];
    		int len=0;
    		while((len=fis.read(bytes))!=-1){
    			System.out.print(new String(bytes,0,len)); //有效字符长度
    		}		
    		fis.close();
    	}
    }
    

    3.2.4复制文件

     

    1

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		// 明确数据源
    		FileInputStream fis = new FileInputStream("E:\zyx\java\demo.txt");
    		// 明确目的地
    		FileOutputStream fos = new FileOutputStream("E:\zyx\java\demoCopy.txt");
    		// 开始复制
    		int len = 0;
    		while ((len = fis.read()) != -1) {
    			fos.write(len);
    		}
    		fis.close();
    		fos.close();
    	}
    }
    

    2复制压缩包(或图片),并记录复制的时间

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Test {
    	public static void main(String[] args) throws IOException {
    		method01();
    	}
    	//复制
    	public static void method01() throws IOException{
    		//明确数据源
    		FileInputStream fis=new FileInputStream("E:\zyx\java\eclipse.zip");
    		//明确目的地
    		FileOutputStream fos=new FileOutputStream("E:\zyx\java\a\eclipse.zip");
    		//开始复制
    		byte[] bytes=new byte[1024];
    		long start=System.currentTimeMillis();
    		int len=0;
    		while((len=fis.read(bytes))!=-1){
    			fos.write(bytes);		
    		}			
    		fis.close();
    		fos.close();
    		long end=System.currentTimeMillis();
    		System.out.println(end-start);
    	}
    }
    

    4字符编码表

    就是生活中字符和计算机二进制的对应关系表。

    1ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx

    2iso-8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx  负数。

    3GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数

    4GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0

    5GB18030:最新的中文码表,目前还没有正式使用。

    6unicode:国际标准码表,无论是什么文字,都用两个字节存储。

    Java中的char类型用的就是这个码表。char c = 'a'; 占两个字节。

    7UTF-8:基于unicode,一个字节就可以存储数据,不用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)

    Tips:

    1Java中的字符串是按照系统默认码表来解析的,简体中文版字符串默认的码表是GBK

    2)能识别中文的码表:GBKUTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。

    3)对于开发人员,常见的编码:GBK  UTF-8  ISO-8859-1(以后jsp用)

    4)文字--->(数字) :编码。 “abc”.getBytes()  byte[]

    (数字)--->文字:解码。 byte[] b={97,98,99}  new String(b,0,len)

    5字符流

    例:

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		// 给文件中写中文
    		writeCNText();
    		// 读取文件中的中文
    		readCNText();
    	}
    
    	// 写中文
    	public static void writeCNText() throws IOException {
    		FileOutputStream fos = new FileOutputStream("E:\zyx\java\test.txt");
    		fos.write("欢迎你".getBytes());
    		fos.close();
    	}
    
    	// 读取中文
    	public static void readCNText() throws IOException {
    		FileInputStream fis = new FileInputStream("E:\zyx\java\test.txt");
    		int ch = 0;
    		while ((ch = fis.read()) != -1) {
    			System.out.println(ch);
    		}
    		fis.close();
    	}
    }
    

     

    用字节流读取的全是字节,所以要用到字符流来进行文本文件的读和写。

    5.1字符输入流Reader

    Reader,读取字符流的抽象超类

     

    read():读取单个字符并返回

    read(char[]):将数据读取到数组中,并返回读取的个数。

    5.1.1 FileReader

      

    1

    import java.io.FileReader;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		// 创建字符输入流
    		FileReader fr = new FileReader("E:\zyx\java\demo.txt");
    		int len = 0;
    		while ((len = fr.read()) != -1) {
    			System.out.print((char) len);
    		}
    		fr.close();
    	}
    }
    

    2

    import java.io.FileReader;
    import java.io.IOException;
    
    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		FileReader fr=new FileReader("E:\zyx\java\demo.txt");
    		char[] ch=new char[2]; //缓冲容器的作用
    		int len=0;
    		while((len=fr.read(ch))!=-1){
    			System.out.print(new String(ch,0,len));
    		}
    		fr.close();
    	}
    }
    

    5.2字符输出流Writer

    Writer是写入字符流的抽象类。

    5.2.1FileWriter

    构造方法

     

     

    5.2.2 flush()close()

     

    Tips

    1close有可能发生异常,不执行,所以写一次Flush刷一次

    2close只能用一次,关了后,对象就不能用了

    3flush可以无限用

    4close最后还能刷一下,所以最后的flush可以不用写

    例:

    import java.io.FileWriter;
    import java.io.IOException;
    
    public class MyTest2 {
    	public static void main(String[] args) throws IOException {
    		FileWriter fw=new FileWriter("E:\zyx\java\demo.txt",true); //有true是续写
    		fw.write(100); //走ascii
    		fw.flush();
    		
    		char[] ch={'a','中','b'};
    		fw.write(ch);
    		fw.flush();
    		
    		fw.write("你好");
    		fw.flush();
    		
    		fw.close();
    	}
    }
    

    5.2.3复制文本文件

    例:

    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class MyTest2 {
    	public static void main(String[] args) throws IOException {
    		// 明确数据源
    		FileReader fr = new FileReader("E:\zyx\java\demo.txt");
    		// 明确目的地
    		FileWriter fw = new FileWriter("E:\zyx\java\a\demo.txt");
    		int len = 0;
    		char[] ch = new char[1024];
    		while ((len = fr.read(ch)) != -1) {
    			fw.write(ch, 0, len);
    			fw.flush();
    		}
    		fr.close();
    		fw.close();
    	}
    }
    

    不能用字符流复制图片:

     

     

    可以看到,虽然复制了,但是图片无法查看。

    总结:

    文本文件用字符流

    图片,视频,压缩包等用字节流

    用到的字节数组或字符数组一般以1024为单位

  • 相关阅读:
    oracle一次删除多张表
    JS学习之动态加载script和style样式
    JS动态引入js、CSS动态创建script/link/style标签
    js设置全局变量ajax中赋值
    java获取程序执行时间
    echarts学习总结(二):一个页面存在多个echarts图形,图形自适应窗口大小
    Codeforces Round #188 (Div. 1) B. Ants 暴力
    Codeforces Round #188 (Div. 2) C. Perfect Pair 数学
    Codeforces Round #188 (Div. 2) B. Strings of Power 水题
    Codeforces Round #188 (Div. 2) A. Even Odds 水题
  • 原文地址:https://www.cnblogs.com/hzhjxx/p/10205486.html
Copyright © 2011-2022 走看看