Java当中的IO流(上)

标题图

Java当中的IO流

Java中,字符串string可以用来操作文本数据内容,字符串缓冲区是什么呢?其实就是个容器,也是用来存储很多的数据类型的字符串,基本数据类型包装类的出现可以用来解决字符串和基本数据类型之间的转换问题.

"字符串" 转换parseXxx() -- 基本数据类型
"123456" -> parseInt -> 123456

基本数据类型包装类的出现,也提供了更多的操作.

对于集合框架,对象多来,便于存储和操作.

简书作者:达叔小生
add put 添加存储, Collection - Iterator
Map - Set - Iterator

IO流的出现是为了存储数据和读取数据的操作.数据存储到内存中如,对象,字符串,日期,系统信息等.内存和硬盘的关系是input输入和output输出的关系.所以输出输出就可以简称io了哦.(还不知道为啥io?因为input和output)

Java提供了io技术的操作,数据是在硬盘上的,在文件中体现的,所以要了解文件的相关信息,在学习过程中,遇到不会的就百度,先百度,一般问题都可以解决的.

了解Java中的File文件

java.io
类 File
java.lang.Object
 -> java.io.File
知道的实现接口:
Serializable,Comparable<File>

文件继承和实现:

public class File extends Object implements Serializable,Comparable<File>

File的字段:

字段说明
pathSeparator返回一个静态的字符串,为static string,与系统有关的路径分隔符 ,表示为一个字符串
pathSeparatorChar返回为一个静态的字符,为static char,与系统有关的路径分隔符
separator返回一个静态的字符串,为static string,与系统有关的默认名称分隔符,表示为一个字符串
separatorChar返回为一个静态的字符,为static char,与系统有关的默认名称分隔符

构造方法:

字段说明
File(File parent, String child)根据 parent 抽象路径名和 child 路径名 字符串创建一个新的File实例
File(String pathname)通过将给定的路径名 字符串 转换为抽象路径名来创建一个新File实例
File(String parent, String child)根据parent路径名 字符串和 child 路径名 字符串创建一个新File实例
File(URI uri)通过将给定的 file; URI 转换为一个抽象路径名 来创建一个新的 File 实例.

File

public File(String pathname)
通过将给定路径名 字符串转换为抽象路径名来创建一个新 File 实例.
参数为pathname: 路径名 字符串
抛出:NullPointerException,如果pathname为null的话
File
public File(String parent, String child)
根据parent路径名,字符串类型,和 child 路径名, 字符串类型, 创建一个新的File实例.
参数:
parent为父路径名字符串
child为子路径名字符串
抛出的异常为:
NullPointerException:如果child为null

构造函数

File(File parent, String child)
File(String pathname)
File(String parent, String child)
File(URI uri)
import java.io.File;
public class FileDemo{
 public static void main(String[] args){
 // 创建路径
  String pathName = "e:\\java\\demo";
// 创建文件对象,将demo文件夹封装成File对象
  File f = new File(pathName);
 }
}

同理可以改为文件路径:

// File(String pathname)
String pathName = "e:\\java\\demo\\demo.java";
File f = new File(pathName);
// 将文件封装成File对象

结果为:

e:\\java\\demo\\demo.java

Java中的File对象,可以封装不存在的文件和文件夹,虽然没有,但是也可以生成创建,变成对象.

// File(String parent, String child)
File f = new File("e:\\java\\demo","demo.java");
// 同样可以创建,结果为:
e:\\java\\demo\\demo.java

File(File parent, String child)

// File(File parent, String child)
// 是将parent 封装成File对象了
File dir = new File("e:\\java\\demo");
File f = new File(dir,"demo.java");
// 结果为:
e:\\java\\demo\\demo.java

要点:

盘符: "/"标题为UNIX中的根目录,"\\\\"表示为 Microsoft Windows UNC 路径名.

private static final String PILE_SEPARATOR = System.getProperty("file.separator");
// File f = new File("e:" + PILE_SEPARATOR + "java\\demo\\demo.java");
File f = new File("e:" + PILE_SEPARATOR + "java"+ PILE_SEPARATOR +"demo"+ PILE_SEPARATOR +"demo.java");

separator 相关

字段说明
file.separator文件分隔符,如"/"
path.separator路径分隔符,如":"
line.separator行分隔符,如:"/n"
separator
public static final String separator
与系统有关的默认 -> 名称分隔符,表示为字符串
separatorChar
public static final char separatorChar
与系统有关的默认 -> 名称分隔符
pathSeparatorChar
public static final char pathSeparatorChar
与系统有关的 -> 路径分隔符

进一步优化:

File.pathSeparator: -> String-File
File.pathSeparatorChar: -> char-File
Separator: -> String-File
SeparatorChar: -> char-File
class: -> Class<java.io.File>
File.listRoots(): -> File[]-File
// File.separator
File f = new File("e:" + File.separator + "java"+ File.separator +"demo"+ File.separator +"demo.java");

File方法

字段说明
canExecute()返回类型为boolean,是用来测试程序是否执行了此抽象路径名表示的文件
canRead()返回类型为boolean,是用来测试程序是否可以读取此抽象路径名表示的文件
canWrite()返回类型为boolean,是用来测试程序是否修改此抽象路径名表示的文件
compareTo(File pathname)返回类型为Int类型,是按照字母顺序进行比较的两个抽象路径名
createNewFile()返回boolean类型,当且仅当不灿在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件
createTempFile(String prefix, String suffix)返回类型为static File,在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称
createTempFile(String prefix, String suffix, File directory)返回为static File,在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称
delete()返回为boolean类型,用来删除此抽象路径名表示的文件或目录
deleteOnExit()返回void,在虚拟机终止时,请求删除此抽象路径名表示的文件或目录
equals(Object obj)返回的类型为boolean,测试此抽象路径名与给定对象是否相等
exists()返回类型为boolean,测试此抽象路径名表示的文件或目录是否存在
getAbsoluteFile()返回类型为File,返回此抽象路径名的绝对路径名形式
getCanonicalFile()返回类型为File,返回此抽象路径名的规范形式

文件属性:

文件类型
位置
大小
占用空间
修建时间
修改时间
访问时间
属性

FileMethodDemo

public class FileMethodDemo{
 public static void main(String[] args){
  // 封装文件 java目录文件
  File file = new File("e:\\java\\demo\\demo.java");
 }
}
File file = new File(" ");
System.out.println(file);
// 结果为 空
               // 结果什么也没显示
如果:
File file = new File(".");
// 结果
.
如果:
File file = new File("hello.txt");
// 结果
hello.txt
// 如果想要什么路径可以用改方法,自己也可以查api
System.out.println(file.getAbsolutePath());
// 可以得到结果 默认路径

可以查看系统信息,为SystemInfo文件,看看默认路径

File file = new File("hello.java");
// 相对路径
String absPath = file.getAbsolutePath();
// 拿的是new File()中的写啥拿啥, File中封装的路径是啥,就拿啥哦~
String path = file.getPath();
// 获取文件名
String filename = file.getName();
// 文件长度
long size = file.length();
// 文件修改时间
long time = file.lastModified();
// 可以修改时间
String date = DateFormat.getDateInstance(DateFormat.LONG).format(new Date(time));

String date = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG).format(new Date(time));

用文件类方法,对文件进行创建和删除操作

File.canExecute(): 为可不可以执行,就是文件类型为xxx.exe的,相信你也看过这种.
返回类型为boolean

文件可读可写:

File.canRead(): 可读
返回类型为boolean
File.canWrite(): 可写
返回类型为boolean

创建文件

file.createNewFile();
// 声明异常
import java.io.IOException
public static void main(String[] args) throws IOException {
}
public class FileMethodDemo{
 public static void main(String[] args) throws IOException {
  // 创建文件
  File file = new File("e:\\hello.txt");
  // 文件不存在,则创建为true
  // 文件存在,则不创建为false
  // 路径错误,内存不够,则IOException
  boolean b = file.createNewFile();
  System.out.println("b=" + b);
 }
}

删除文件

File file = new File("e:\\hello.txt");
boolean b = file.delete();
// 彻底删除,不存在回收站中
// 注意
如果文件不存在,进行删除为false
如果文件正在使用,进行删除为false

对文件进行判断存不存在

简书作者:达叔小生
boolean b = file.exists();
System.out.println("b="+b);

对目录进行创建,删除,判断

dir.mkdir(); 为创建一个目录
dir.mkdirs(); 为创建一个路径,创建目录中的目录

File dir = new File("e:\\hello)";
boolean b = dir.mkdir();
// 创建目录
File dir = new File("e:\\hello\\da\\shu\\dashu)";
boolean b = dir.mkdirs();
// 创建多级目录

删除目录

File dir = new File("e:\\hello\\da\\shu\\dashu)";
boolean b = dir.delete();
// 注意
删除目录,无法直接删除,只能删除最后一个目录
如果目录中还有目录,也不能一次性删除

要判断是文件还是目录

File.isFile(); // 判断是否是文件
File.isDirectory(); // 判断是否是目录

为啥要判断呢?

File file = new File("e:\\hello.txt");
// hello.txt
File file = new File("e:\\hello");
// hello也可以是文件哦~
给个
file.createNewFile();
// 就可以创建了哦~没有扩展名的文件

因为这个可以是目录也可以是文件啊~不信自己建立一个,叫名为hello.txt的目录试试.

使用方法

File dir = new File("e:\\java");
// 遍历目录,获取目录文件名
String[] names = dir.list();
for(String name : names) {
 System.out.println(name);
}

listFiles():
返回类型为File[]
返回一个抽象路径名数组,路径名

File dir = new File("e:\\java");
File[] files = dir.listFile();
for(Files file : files){
 System.out.println(file.getName());
}
// 如果目录不存在
抛出: 
java.lang.NullPointerException
// Java的健壮性
要进行健壮性的判断,防止错误

对文件进行过滤,进行筛选

// 获取目录下的所有文件
File dir = new File("e:\\java");
File[] files = dir.listFiles();
for(Files file : files){
 // 进行筛选  
 if(file.getName().endsWith(".java")){
  System.out.println(file.getName());
 }
}

listFiles()
返回类型为File[]
返回一个抽象路径名的数组,路径名为表示此抽象路径名表示的目录中的文件

listFiles(FileFilter filter)
返回为File[]
返回为抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定的过滤器的文件和目录

listFiles(FilenameFilter filter)
返回为File[]
返回为抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定的过滤器的文件和目录

接口FilenameFilter

java.io
接口FilenameFilter
public interface FilenameFilter

方法:

方法说明
accept(File dir, String name)返回类型为boolean ,测试指定文件是否应该包含在某一文件列表中
accept
boolean accept(File dir, String name)
参数:
dir为文件所在目录
name为文件名
public class FilenameFilterByJava implements FilenameFilter {
 @Override
 public boolean accept(File dir, String name) {
  return name.endsWith(".java");
 }
}
File dir = new File("E:\\java");
File[] files = dir.listFiles(new FilenameFilterByJava());
for(File file : files){
 System.out.println(files.getName());
}

listFiles内部代码

public File[] listFiles(FilenameFilter filter){
 // 使用了File类中的方法list(),获取了所有名称数组
 String s[] = list();
// 健壮性判断
 if(s == null) return null;
 // 创建一个集合,类型为File类型
 ArrayList<File> files = new ArrayList<>();
 // 遍历数据名字
 for(String str : s)
  if((filter == null) || filter.accept(this, s))
   files.add(new File(s, this));
  // 集合转数组,不用增删操作
  return files.toArray(new File[files.size()]);
}
public class FilenameFilterByBuffix implements FilenameFilter {
 private String suffix;
 public FilenameFilterByBuffix(String suffix){
  super();
  this.suffix = suffix;
 }

 @Override
 public boolean accept(File dir, String name){
  return name.endsWith(suffix);
 }
}
// 这时候改为
File dir = new File("E:\\java");
// File[] files = dir.listFiles(new FilenameFilterByJava());

File[] files = dir.listFiles(new FilenameFilterByBuffix(".java"));

文件夹过滤

public class FileFilterByDir implements FileFilter{
 @Override 
 public boolean accept(File pathname){
  return pathname.isDirectory();
 }
}
public class FileMethodDemo{
 public static void main(String[] args){
  File dir = new File("E:\\java");
  File[] files = dir.listFiles( new FileFilterByDir() );
  for(File file : files){
   System.out.println(file);
  }
 }
}

FileTest

简书作者:达叔小生
public class FileTest{
 public static void main(String[] args){
  File dir = new File("E:\\java");
  File[] files = dir.listFiles();
  // 遍历
  for(File file :  files){
   if(file.isDirectory()){

    File[] filess = file.listFiles();
    fot(File f : filess){
     System.out.println(f.getName());
    }
   }
   System.out.println(file.getName());
  }
 }
}

升华

File dir = new File("e:\\java");
listAll(dir);
// 创建一个方法
public static void listAll(File dir){
 System.out.println("dir:" + dir.getName());
 File[] files = dir.listFiles();
 for(File file : files){ 
  if(file.isDirectory()){
   listAll(file);
  }else{
   System.out.println("file:" + file.getName());
   } 
 }
}

File 类中的方法

// one
public static void main(String[] args){
 show();
}
public static void show(){
 show();
}
// java.lang.StackOverflowError
栈内存溢出
// two
public static void main(String[] args){
 show();
}
public static void show(){
 showdashu();
}
public static void showdashu(){
 show();
}

求和新大陆

public static void main(String[] args){
 // 总和
 int sum = getSum(4);
 System.out.println("sum="+sum);
}
public static int getSum(int num){
 // 如果求和数字,导入为1,则返回为1
 if(num == 1){
  return 1;
 }
 // 求和
 return num + getSum(num-1);
}
// 4
int getSum(4){
 if(4==1){
  return 1;
 }
 return 4 + getSum(4-1);
}
// 3
int getSum(3){
 if(3==1){
  return 1;
 }
 return 3 + getSum(3-1);
}
// 2
int getSum(2){
 if(2==1){
  return 1;
 }
 return 2 + getSum(2-1);
}
// 1 
int getSum(1){
 if(1==1){
  return 1;
 }
 return 1 + getSum(1-1);
}
// 注意
如果数字大,就会不断进栈,会导致栈溢出

队列

遍历子目录,如果有子目录就将目录存储到容器中,然后遍历容器,从容器中取出子目录,递归的方法,容易将栈溢出.如果在容器中目录中没有目录了,就可以取出来了.

队列结构,先进先出

// 泛型
class Queue<E>{
 // 构造队列对象
 private LinkedList<E> link;
 public Queue(){
  link = new LinkedList<E>();
 }
 // 添加元素
 public void myAdd(E obj){
  //第一个
  link.addFirst(obj);
 }
 // 获取
 public E myGet(){
  // 最后
  return link.removeLast();
 }
// 进行判断
 public boolean isNull(){
  return link.isEmpty();
 }
}
File dir = new File("e:\\java");
Queue<File> queue = new Queue<File>();
// 遍历目录
File[] files = dir.listFiles();
for(File file : files){
 // 判断有子目录,就存储到队列中
 if(file.isDirectory()){
  queue.myAdd(file);
}else{
 System.out.println(file.getName());
}
}
System.out.println(queue.isNull());
// 遍历
while(!queue.isNull()){
 // 遍历子目录
 File subDir = queue.myGet();
 File[] subFiles = subDir.listFiles();
 for(File subFile : subFiles){
  if(subFile.isDirectory()){
   // 继续将子目录存储到队列中
   queue.myAdd(subFile);
   }else{
    System.out.println(subFile.getName());
   }
  }
 }
}

IO流-数据存储操作

输入输出流-IO流操作:输出output,输入input

java.io 为通过数据流,序列化和文件系统提供系统输入和输出的

java.io
类 OutputStream
java.lang.Object
-> java.io.OutputStream
实现的接口:
Closeable,Flushable
知道的子类
ByteArrayOutputStream,FileOutputStream,FilterOutputStream,ObjectOutputStream,OutputStream,FiledOutputStream
public abstract class OutputStream
extends Object
implements Closeable, Flushable

抽象类OutputStream表示为输出字节流的所有类的超类,构造方法OutputSteam(),操作字节

OutputStream为输出字节流的超类,是操作字节数据的,具有输出字节流的基本功能哦~

public abstract class OutputStream
extends Object
implements Closeable, Flushable
输出流是把这些字节发送到某个接收器中

方法:

字段说明
close()返回类型void,是用来关闭此输出流并且释放与此流有关的所有系统资源
flush()返回类型为void,是用来刷新此输出流并且强制写出所有缓冲的输出字节
write(byte[] b)返回类型为void,是将b.length个字节从指定的byte数组中写入此输出流
write(byte[] b, int off, int len)返回类型为void,是将指定byte数组中从offlen个字节写入输出流
write(int b)返回类型为abstract void,是将指定的字节写入此输出流

从类java.lang.Object 继承的方法有:

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, 

FileOutputStream
往文件写

简书作者:达叔小生
public class FileOutputStreamDemo{
 public static void main(String[] args){
  // 创建文件夹
  File dir = new File("hello");
  // 健壮性
  if(!dir.exists()){
   dir.mkdir();
  }
  // 创建文件
  File file = new File(dir,"hello.txt");
  // 用于创建操作文件的字节输出流对象
  // 输出流创建文件,不存在就创建新的,存在就删掉进行覆盖
  FileOutputStream fos = new FileOutputStream(file);
  // 调用父类的write
 byte[] data = "dashucoding".getBytes();
 fos.write(data)
 // 关闭流
 fos.close();
 }
}

升级:

构造方法:

字段说明
FileOutputStream(File file)创建一个指定File的对象,用来向文件中写入数据的输出流
FileOutputStream(File file, boolean append)用来向指定的File的文件写入数据的文件输出流,继续写数据的,用来续写的
public FileOutputStream(File file, boolean append) throws FileNotFoundException

参数:
file:为文件,是要用来写入的数据文件
append:true时,就将字节写入到文件的末尾中,从末尾开始写入

public class FileOutputStreamDemo{
 // 定义常量
 private static final String LINE_SEPARATOR = System.getProperty("line.separator");

 public static void main(String[] args){
  // FileOutputStream(File file, boolean append)
  File file = new File("hello\\hello.txt");
  FileOutputStream fos = new FileOutputStream(file,true);
  // 换行
  String str = LINE_SEPARATOR + "dashu";
  
  // fos.write("dashucoding".getBytes());
  fos.write(str.getBytes());
  // fos.write("\r\n hahahadashucoding".getBytes());
  fos.close();
 }
}

有时候IO流也会出现异常现象,字节输出流
异常:java.io.FileNotFoundExceptionjava.lang.NullPointerException

public class FileOutputStreamDemo{
 File file = new File("hello\\hello.txt");
 // 异常
 FileOutputStream fos = null;
 try {
 fos = new FileOutputStream(file);
 fos.write("dashucoding".getBytes());
 // 捕捉
 }catch (IOException e){
  System.out.println(e.toString());
 }finally{
 // 健壮性
 if(fos != null){
 
  try{
  fos.close();
 }catch(IOException e){
  throw new RuntimeException("");
 }
 }
 } 
}

IO流输入流读取数据

java.io
类 InputStream
java.lang.Object
-> java.io.InputStream
public abstract class InputStream extends Object implements Closeable

为抽象类,表示为字节输入流-> java.io.InputStream 字节输入流的超类

方法:

字段说明
available()返回类型为Int,此方法用来返回此输入流下一个方法调用可以不受阻塞地从此输入流读取的估计字节数
close()返回类型为void,为关闭此输入流并释放与该有关的所有系统资源
mark(int readLimit)返回类型为 void,此输入流标记的当前位置
markSupported()返回类型为boolean, 用来测试输入流是否支持markreset方法.
read()返回类型为abstract int,从输入流中读取数据
read(byte[] b)返回类型为Int,从输入流中读取一定数量的字节
read(byte[] b, int off, int len)返回类型为int, 将输入流中最多len个数据字节读入byte数组
reset()返回类型为void, 将此流重新定位到最后一次对此输入流调用mark方法时的位置
skip(long n)返回类型为Long,用来跳过和丢弃此输入流数据的n个字节

read

public abstract int read() throws IOException
返回为下一个数据字节
抛出定位IOException

FileInputStream用来从文件系统中的某个文件中获取输入字节,读取字节流,返回0到255范围的int字节.

java.io
类 FileInputStream
java.lang.Object
-> java.io.InputStream
-> java.io.FileInputStream
public class FileInputStream extends InputStream

构造方法

FileInputStream(File file)
FileInputStream(FileDescriptor Obj)
FileInputStream(String name)

读取文件:InputStream为字节输入流的超类,使用方法可以为int read()或者int read(byte[]),用于文件的读取,FileInputStream为字节输入流对象

public class FileInputStreamDemo{
 public static void main(String[] args) throws IOException {
  // 创建文件,读取文件中的数据
  File file = new File("hello\\hello.txt");
  // 创建一个字节输入流对象
 FileInputStream fis = new FileInputStream(file);
 // 读取数据
 int char = fis.read();
 System.out.println(char);
 // 关闭资源
 fis.close();
 }
}

使用read(),一次读取一个字节

int c1=fis.read();
// (char)c1
int c2=fis.read();
// (char)c2
一直返回到-1为止

升级:

简书作者:达叔小生
int char = 0;
while( (char=fis.read()) != -1){
 System.out.println("char="+(char)char);
}

读取数据read(byte[] b)

read
public int read(byted[] b) throws IOException
从输入流中读取一定数量的字节
参数b为缓冲区
String(byte[] bytes)
String(byte[] bytes, int offset, int length)

如果不好好是使用read(byte[])方法会导致抛出异常:

java.lang.StringIndexOutOfBoundsException

升级:

File file = new File("hello\\hello.txt");
FileInputStream fis = new FileInputStream(file);
byte[] buff = new byte[1024];
int len = 0;
while( (len = fis.read(buff)) != -1){
 System.out.println(new String(buff,0,len));
}

进行复制文件

// file.txt
FileInputStream fis = new FileInputStream("file.txt");
// copy_file.txt
FileOutputStream fos = new FileOutputStream("copy_file.txt");

一次读取一个字节然后写入到复制文件中去

简书作者:达叔小生
public class CopyFileDemo{
 public static void main(String[] args) throws IOException{
  File srcFile  = new File("file.txt");
  File desFile = new File("copy_file.txt");
  //  字节流输入流,输出流
 FileInputStream fis = new FileInputStream(srcFile);
 FileOutputStream fos = new FileOutputStream(desFile);
 // 输入流
 int ch = 0;
 while( (ch=fis.read()) != -1){
  fos.write(ch)
 }
 // 关闭资源
 fos.close();
 fis.close();
}

升级:

方法:

字段说明
close()返回类型为void, 关闭此输出流并释放与此流有关的所有资源
flush()返回类型为void, 刷新此输出流,并写出所有缓冲的输出字节
简书作者:达叔小生
write(byte[] b)
write(byte[] b, int off, int len)
write(int b)
public class CopyFileByBufferDemo{
 public static void main(String[] args) throws IOException {
  File srcFile = new File("file.txt");
  File desFile = new File("copy_file.txt");
 FileInputStream fis = new FileInputStream(srcFile);
 FileOutputStream fos = new FileOutputStream(desFile);
 // 缓冲区 
byte[] buff = new byte[1024];
 int len = 0;
 while( (len=fis.read(buff) != -1){
  fos.write(buff,0,len);
 }
 fos.close();
 fis.close();
 }
}

available() 方法:

public int available() throws IOException
抛出IO错误
public class ByteStreamDemo{
 public static void main(String[] args) throws IOException {
  // 字节输入流 available()
 FileInputStream fis = new FileInputStream("hello.txt");
 // 可以打印出文件的大小
 System.out.println(fis.available());
 fis.close();
 } 
}

那么就可以:

简书作者:达叔小生
byte[] buff = new byte[fis.available()]; 
// 但是建议不使用,只可以去获取相关文件的大小
fis.read(buff);
String str = new String(buff);
System.out.println(str);

往后余生,唯独有你
简书作者:达叔小生
90后帅气小伙,良好的开发习惯;独立思考的能力;主动并且善于沟通
简书博客: https://www.jianshu.com/u/c785ece603d1

结语

  • 下面我将继续对 其他知识 深入讲解 ,有兴趣可以继续关注
  • 小礼物走一走 or 点赞
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值