操作文件

·1·
  操作文件
输入输出是指应用程序与外部设备及其他计算机进行数据交流的操作,如读写硬盘数据、向显示器
输出数据、通过网络读取其他节点的数据等。任何一种编程语言必须拥有输入输出的处理方式,Java 语
言也不例外。
20.1  文件操作
在正式了解 Java 中如何处理输入/输出之前,要先了解一下在 Java 中如何进行文件和目录的管理。
文件是用来保存数据的,目录是管理文件的特殊机制,同类文件保存在同一目录下可以简化文件管理。
因此,掌握文件和目录的操作对于编程员是十分重要的。
20.1.1   文件类 java.io.File
在 Java 语言中,文件和目录的管理是由 java.io.File 类来实现。File 类也属于 java.io 包,但它不是
InputStream 或者 OutputStream 的子类,因此不负责数据的输入和输出,而是专门管理磁盘的文件和目录。
每个 File 类的对象表示一个磁盘文件或目录,其对象属性中包含了文件或目录的相关信息,如名称、
长度、所含文件个数等,调用它的方法则可以完成对文件或目录的常用管理操作,例如,创建、删除等
操作。
1.创建 File 类对象
每个 File 类的对象都对应了系统的一个磁盘文件或目录,所以创建 File 类对象时需指明它所对应的
文件或目录名。File 类提供 3 种格式以不同的参数形式灵活地接收文件和目录名信息。
  File  对象名  = new File(String path);
  File  对象名  = new File(String Path,String name);
  File  对象名  = new File(File dir,String name)。
说明:参数 path 指明了新创建的 File 对象对应的磁盘文件或目录名及其路径名, path 参数也可以对
应磁盘上的某个目录;参数 name 表示文件或目录名;参数 dir 为另一个已经存在的代表某磁盘目录的
File 对象,表示文件或目录的路径。
2.文件或目录的属性 
经常使用 File 类的下列方法获取文件本身的一些信息: 
  public String getName()   获取文件或目录的名字。
  public boolean canRead()   获取文件的可读属性,如果为可读文件,返回 true。
  public boolean canWrite()  获取文件的可写属性,如果为可写文件,返回 true。
  public boolean exists()   判断文件或目录是否存在,如果存在返回 true,否则返回 false。
  public long length()   获取文件的长度(单位是字节)。 
2
  public String getAbsolutePath()   获取文件的绝对路径。“c:/file/hello.txt”
  public String getParent()   获取文件的父目录。“c:/file”    
  public boolean isFile()   判断否是为文件,如果对象代表有效文件,则返回 true。
  public boolean isDirectroy()  判断否是为目录,如果对象代表有效目录,则返回 true。
  public boolean isHidden()   判断文件是否是隐藏文件。
  public  long  lastModified()   获取文件最后修改的时间(时间是从 1970 年午夜至文件最后修改时
刻的毫秒数)。
  public String[] list()   用字符串形式返回目录下的全部文件。
  public File[] listFiles()   用 File 对象形式返回目录下的全部文件。
在下面的例子中,我们使用上述的一些方法,获取某些文件信息。 
【例 20.1】获取文件或目录的基本信息。
import java.io.File;
import java.util.Date;
public class GetFileInfos{  
public static void println(String s){
System.out.println(s);
}
public static void main(String[] args){
//用文件路径新建一个文件对象。路径可以是绝对路径也可以是相对路径
File file = new File("D:/work/newTemp.txt");       
println("文件名:  " + file.getName());             //获取文件的名字,不包括路径
println("文件路径:  " + file.getPath());            //获取文件的绝对路径
println("绝对路径:  " + file.getAbsolutePath());    //获取文件的绝对路径
println("父目录:  " + file.getParent());            //获取抽象路径名的父抽象路径名
println("文件是否存在:  " + file.exists());
println("是否可读:  " + file.canRead());
println("是否可写:  " + file.canWrite());
println("是否是隐藏文件:  " + file.isHidden());
println("是否是普通文件:  " + file.isFile());
println("是否是目录:  " + file.isDirectory());
println("文件路径是否是绝对路径:  " + file.isAbsolute());
println("文件路径的 URI: " + file.toURI());
println("文件最后修改时间:  " + new Date(file.lastModified()));
println("文件大小:  " + file.length() + "bytes");
println("是否可执行:"+file.canExecute());
}
}
在这个程序示例中,因为要对文件进行操作,所以首先导入 java.io.File 类。在构造 File 对象时,将
文件的路径作为参数传递进来,在本程序中为“D:/work/newTemp.txt”。然后调用 File 对象所提供的各
个方法来获得文件对象的信息。 
·3·
20.1.2   创建一个文件
在 Java 中使用 File.createNewFile()方法来创建一个文件,并返回一个 boolean 值:如果文件创建成
功,就返回 true;如果文件已经存在,或者操作失败,则返回 false。
import java.io.File;
import java.io.IOException;
public class CreateFileExample{
public static void main(String[] args){
try{
File file = new File(“c:\\newfile.txt”);
if(file.createNewFile()){
System.out.println(“文件创建成功!”);
}else{
System.out.println(“文件已经存在”);
}
}catch(IOException e){
e.printStackTrace();
}

}
20.1.3   构建文件路径
在 Java 中构建文件路径有两种方式:
1)  检查操作系统并手工创建文件分隔符(不推荐)
2)  使用 File.separator 来自动创建文件分隔符(推荐)
使用 File.separator 可以自动检查自己的操作系统并显示正确的文件分隔符。比如,在 Windows 系统
中使用的文件分隔符为“\”,在*nix 中为“/”。
下面是使用 File.separator 构建文件路径的示例:
import java.io.File;
import java.io.IOException;
public class FilePathExample{
public static void main(String[] args){
try{
String filename = "testing.txt";
String finalfile = "";
String workingDir = System.getProperty("user.dir");  //获取当前的工作目录
finalfile = workingDir + File.separator + filename;
System.out.println("最终路径是:" + finalfile);
File file = new File(finalfile);
if(file.createNewFile()){
System.out.println("创建文件成功!");
}else{ 
4
System.out.println("文件已经存在!");
}
}catch(IOException e){
e.printStackTrace();
}

}
20.1.4   删除文件
要删除一个文件,只需要调用 File.delete()方法即可。这个方法将返回一个 boolean 值来指明删除操
作的状态:true 是删除成功;false 是删除失败。
import java.io.File;
public class DeleteFileExample {
public static void main(String[] args){
File file = new File("D:/mynewfile.txt");
if(file.delete()){
System.out.println(file.getName() + "已经被删除了.");
}else{
System.out.println("删除操作失败!");
}
}
}
20.1.5   删除带有指定扩展名的文件
在 Java 中,我们可以实现 FilenameFilter 接口,重写 accept(File  dir,  String  name)方法,来执行文件
过滤功能。
在下面这个示例程序中,我们使用 FilenameFilter 来列出“D:\\folder”目录下所有以.txt 作为文件扩
展名的文件。然后删除它。
首先创建文件过滤器类,指定其只过滤(返回)以.txt 结尾的文件。
//文件过滤器类
import java.io.File;
import java.io.FilenameFilter;
public class GenericExtFilter implements FilenameFilter{
private String ext;
public GenericExtFilter(String ext){
this.ext = ext;
}
@Override
public boolean accept(File dir, String name) {
return (name.endsWith(ext)); 
·5·
}
}
接下来,在列出指定目录下的文件时,应用该文件过滤器。
import java.io.File;
public class FileChecker {
private static final String FILE_DIR = "D:\\folder";
private static final String FILE_TEXT_EXT = ".txt";
public static void main(String[] args){
new FileChecker().deleteFile(FILE_DIR, FILE_TEXT_EXT);
}
public void deleteFile(String folder, String ext){
GenericExtFilter filter = new GenericExtFilter(ext);
File dir = new File(folder);
//列出所有以.txt 为扩展名的文件
String[] allFiles = dir.list(filter);
if(allFiles.length == 0){
return;
}
File fileDelete;
for(String file:allFiles){
String temp = new StringBuffer(FILE_DIR).append(File.separator).append(file).toString();
fileDelete = new File(temp);
boolean isdeleted = fileDelete.delete();
System.out.println("file:" + temp + "已经被删除了:" + isdeleted);
}
dir.delete();   //最后删除目录
}
}
20.1.6   重命名文件
Java 使用 renameTo()方法重命名一个文件。不过,这个方法是平台依赖的:有可能在*nix 平台下能
成功地重命名一个文件,而在 Windows 平台下会失败。因此,应该总是检查返回值(true 意味着重命名
成功,false 则是失败),以确定文件重命名是否成功。
import java.io.File;
public class RenameFileExample {
public static void main(String[] args){
File oldfile = new File("D:\\oldfile.txt");
File newfile = new File("D:\\newfile.txt"); 
6
if(oldfile.renameTo(newfile)){
System.out.println("文件重命名成功。");
}else{
System.out.println("文件重命名失败。");
}
}
}
20.1.7   拷贝文件
在 Java 中,没有直接拷贝文件的方法,我们必须手工实现。要实现文件拷贝功能,我们只需使用
FileInputStream 将文件转换为字节流,并使用 FileOutputStream 将字节写入到另一个文件即可。
整个过程很简单,不过不明白为什么 Java 不把这个方法包含在 java.io.File 类中。
import java.io.*;
public class CopyFileExample {
public static void main(String[] args){
InputStream in = null;
OutputStream out = null;
try{
File afile = new File("D:\\Afile.txt");
File bfile = new File("D:\\Bfile.txt");
in = new FileInputStream(afile);
out = new FileOutputStream(bfile);
byte[] buffer = new byte[1024];
int length;
//拷贝文件
while((length = in.read(buffer)) > 0){
out.write(buffer,0,length);
}
in.close();
out.close();
System.out.println("文件拷贝成功.");
}catch(IOException e){
e.printStackTrace();
}
}

·7·
20.1.8   移动文件
在 Java 中,没有包含任何用来移动文件的方法,不过我们可以通过以下两种途径来实现:
1)File.renameTo()
2)拷贝一个新的文件,然后删除原来的文件
在下面的这两个示例程序中,将“D:\\folderA\\Afile.txt”从一个目录移动另一个目录,并带有相同
的文件名“D:\\folderB\\Afile.txt”。
示例 1:File.renameTo()方法
import java.io.File;
public class MoveFileExample {
public static void main(String[] args){
File afile =new File("D:\\folderA\\Afile.txt");
try{
if(afile.renameTo(new File("D:\\folderB\\" + afile.getName()))){
System.out.println("文件移动成功!");
}else{
System.out.println("文件移动失败!");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
示例 2:拷贝和删除
import java.io.*;
import java.io.File;
public class MoveFileExample {
public void moveFileByCopyAndDelete(){
InputStream inStream = null;
OutputStream outStream = null;
try{ 
File afile =new File("D:\\folderA\\Afile.txt");
File bfile =new File("D:\\folderB\\Afile.txt");
inStream = new FileInputStream(afile);
outStream = new FileOutputStream(bfile);
byte[] buffer = new byte[1024];
int length;
//拷贝
while ((length = inStream.read(buffer)) > 0){ 
outStream.write(buffer, 0, length); 

8
inStream.close();
outStream.close();
//删除原始文件
afile.delete();
System.out.println("文件拷贝成功!");
}catch(IOException e){
e.printStackTrace();
}
}
}
20.1.9   获取文件大小
在 Java 中,可以使用 File.length()方法来获得文件的大小。
import java.io.File;
public class FileSizeExample {
public static void main(String[] args) {
File file = new File("D:\\logfile.log");
if (file.exists()) {
double bytes = file.length();
double kilobytes = (bytes / 1024);
double megabytes = (kilobytes / 1024);
double gigabytes = (megabytes / 1024);
double terabytes = (gigabytes / 1024);
double petabytes = (terabytes / 1024);
double exabytes = (petabytes / 1024);
double zettabytes = (exabytes / 1024);
double yottabytes = (zettabytes / 1024);
System.out.println("bytes : " + bytes);
System.out.println("kilobytes : " + kilobytes);
System.out.println("megabytes : " + megabytes);
System.out.println("gigabytes : " + gigabytes);
System.out.println("terabytes : " + terabytes);
System.out.println("petabytes : " + petabytes);
System.out.println("exabytes : " + exabytes);
System.out.println("zettabytes : " + zettabytes);
System.out.println("yottabytes : " + yottabytes);
} else {
System.out.println("文件不存在!");

·9·
}
}
20.1.10   获取文件路径
在 Java 中,使用 File.getAbsolutePath()方法来获得一个文件的全路径名(路径+文件名)。如果只想
获得目录路径,可以配合使用 substring()和 lastIndexOf()方法。
在下面的示例中,创建了一个临时文件,并打印出其文件路径来。
import java.io.File;
import java.io.IOException;
public class AbsoluteFilePathExample {
public static void main(String[] args){
try{
File temp = File.createTempFile("i-am-a-temp-file", ".tmp" );
String absolutePath = temp.getAbsolutePath();
System.out.println("File path : " + absolutePath);
String filePath = absolutePath.substring(0,absolutePath.lastIndexOf(File.separator));
System.out.println("File path : " + filePath);
}catch(IOException e){ 
e.printStackTrace(); 
}
}
}
20.1.11   获取文件总行数
LineNumberReader 类是 BufferedReader 类的子类, 可以用来追踪当前处理的是哪一行。 它还能使我
们选择当前的行号,如果想要从另一行开始的话。
下面这个例子,我们为文件 myFile.txt 构造了一个 LineNumberReader 对象,并读取每一行,直到到
达文件的结尾。文件 myFile.txt 的内容如下:
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
第 9 行
第 10 行
使用类 LineNumberReader 类来处理文件的行数。代码如下: 
10
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class LineNumberReaderExample2 {
/**
* LineNumberReader  类使用示例
*/
public void readFromFile() {
File filename = new File("D:\\logfile.log");
LineNumberReader lineNumberReader = null;
try {
//构造 LineNumberReader 对象
lineNumberReader = new LineNumberReader(new FileReader(filename));
String line = null;
while ((line = lineNumberReader.readLine()) != null) {
System.out.println("#" + lineNumberReader.getLineNumber() + ": " + line);
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
//关闭 BufferedWriter
try {
if (lineNumberReader != null) {
lineNumberReader.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
/**
* LineNumberReader  设置行号和标签使用示例
*/
public void readMarkedLines() {
String line = null;
File filename = new File("D:\\logfile.log");
·11·
LineNumberReader lineNumberReader = null;
try {
lineNumberReader = new LineNumberReader(new FileReader("D: \\logfile.log"));
lineNumberReader.setLineNumber(5);//只影响行号的展现形式,而不具有其他的实质意义
while ((line = lineNumberReader.readLine()) != null) {
System.out.println(lineNumberReader.getLineNumber() + "#:" + line);
if (lineNumberReader.getLineNumber() == 7) {//当运行到第 5 行
//在当前位置打上一个书签
lineNumberReader.mark(200);
}
}
//与 mark()方法配合使用,翻到最近的书签
lineNumberReader.reset();
while ((line = lineNumberReader.readLine()) != null) {
System.out.println(lineNumberReader.getLineNumber() + "#:" + line);
if (lineNumberReader.getLineNumber() == 7) {//当运行到第 7 行
//在当前位置打上一个书签
lineNumberReader.mark(200);
}
}
}catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
//关闭 BufferedWriter
try {
if (lineNumberReader != null) {
lineNumberReader.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
20.1.12   获取磁盘空闲空间
在以前的版本中,Java 缺少检测一个分区上磁盘空闲空间的方法。不过从 JDK 1.6 开始,一些新的
方法,如 getTotalSpace()、getUsableSpace()和 getFreeSpace(),已经绑定以了 java.io.File 类中,以获取磁
盘或分区的详细信息。
请看下面的示例程序:
import java.io.File;
12
public class App {
public static void main(String[] args) {
File file = new File("c:");
long totalSpace = file.getTotalSpace();      //总磁盘大小有多少(字节)
long usableSpace = file.getUsableSpace();    //未分配的或空闲的磁盘空间(字节)
long freeSpace = file.getFreeSpace();        //未分配的或空闲的磁盘空间(字节)
System.out.println(" ===  分区详细信息  ===");
System.out.println(" ===  字节  ===");
System.out.println("总容量  : " + totalSpace + "  字节");
System.out.println("空闲容量  : " + usableSpace + "  字节");
System.out.println("空闲容量  : " + freeSpace + "  字节");
System.out.println(" ===  兆(M)字节  ===");
System.out.println("总容量  : " + totalSpace / 1024 / 1024 + " M");
System.out.println("空闲容量  : " + usableSpace / 1024 / 1024 + " M");
System.out.println("空闲容量  : " + freeSpace / 1024 / 1024 + " M");
}
}
编译并运行程序,会输出 C:盘的空间详细信息:
===  分区详细信息  ===
===  字节  ===
总容量  : 104855834624  字节
空闲容量  : 69451333632  字节
空闲容量  : 69451333632  字节
===  兆(M)字节  ===
总容量  : 99998 M
空闲容量  : 66233 M
空闲容量  : 66233 M
在上面的程序中,可以看到,getFreeSpace()和 getUsableSpace()方法都返回指定分区同样大小的磁
盘空间。不过这两者之间真正的区别还不清楚,甚至是在 Java 文档中也不是很清楚。
20.1.13  创建和删除临时文件
下面这个简单的示例程序中,演示了在 Java 中怎样创建临时文件。
临时文件是用来存储少量重要的和临时性的数据。当系统终止时,这些临时文件应该被删除掉.最好
的方法是使用 File.deleteOnExit()方法来完成它.
例如:
File temp = File.createTempFile(“temp”,”.tmp”);
temp.deleteOnExit();
在上面的这个代码片段中,创建了一个名为 temp.tmp 的临时文件,当程序终止或退出时,该临时文
件会被删除.
注:如果想要手工删除临时文件,可以使用 File.delete()方法.
下面这个简单的示例程序中,演示了在 Java 中怎样删除临时文件。
import java.io.File; 
·13·
import java.io.IOException;
public class DeleteTempFileExample {
public static void main(String[] args) {
try {
//创建一个临时文件
File temp = File.createTempFile("tempfile", ".tmp");
System.out.println("临时文件  : " + temp.getAbsolutePath());
//当程序退出时,删除临时文件
temp.deleteOnExit();
//如果使用下面这个方法,则是立即删除
//temp.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
}
20.1.14   创建文件夹
Java 带有两个创建文件夹(目录)的方法:
方法一:创建一个名为”directory1”的文件夹
new File(“c:\\directory1”).mkdir();
方法二:创建一个名为”directory2”的文件夹及其子文件夹”subdir2”和”sub-subdir2”
new File(“c:\\directory2\\subdir2\\sub-subdir2”).mkdirs();
两个方法都返回一个 boolean 值,表示操作状态:如果成功,则返回 true;如果失败,则返回 false。
下面这个简单的示例程序中,演示了在 Java 中怎样创建文件夹(目录)。
import java.io.File;
public class CreateDirectoryExample {
public static void main(String[] args) {
File file = new File("C:\\directory1");
if (file.mkdir()) {
System.out.println("文件夹已经创建!");
} else {
System.out.println("文件夹创建失败!");
}
File files = new File("C:\\directory2\\subdir2\\sub-subdir2");
if (files.mkdirs()) {
System.out.println("多个目录已经被创建!"); 
14
} else {
System.out.println("创建多个目录失败!");
}
}
}
编译并运行程序,输出结果如下:
文件夹已经创建!
多个目录已经被创建!
20.1.15   删除文件夹
在 Java 中,可以使用 File.delete()方法删除一个文件夹,但是要求该文件夹必须为空才能删除.
更经常地,我们可能需要执行递归删除目录,这意味着某个要被删除的目录及其子目录和文件同时
也要被删除。
在下面这个简单的示例程序中,我们删除一个名为”c:\\directory2”的文件夹,同时连其所有的子目录
和文件也同时删除。代码如下:
package cn.xuejava.file;
import java.io.File;
import java.io.IOException;
public class DeleteDirectoryExample {
private static final String SRC_FOLDER = "C:\\directory2";
public static void main(String[] args) {
File directory = new File(SRC_FOLDER);
//确保要删除的目录是存在的
if (!directory.exists()) {
System.out.println("您要删除的目录并不存在.");
System.exit(0);
} else {
try {
delete(directory);
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
}
System.out.println("Done");
}
public static void delete(File file) throws IOException {
·15·
if (file.isDirectory()) {
//如果目录是空的,就直接删除
if (file.list().length == 0) {
file.delete();
System.out.println("已经删除目录  : " + file.getAbsolutePath());
} else {
//列出所有的目录内容
String files[] = file.list();
for (String temp : files) {
//构造文件结构
File fileDelete = new File(file, temp);
//递归删除
delete(fileDelete);
}
//再次检查目录,如果为空就删除
if (file.list().length == 0) {
file.delete();
System.out.println("已经删除目录  : " + file.getAbsolutePath());
}
}
} else {
//如果是文件,就删除它
file.delete();
System.out.println("已经删除文件  : " + file.getAbsolutePath());
}
}
}
编译并运行程序,输出结果如下:
已经删除目录  : C:\directory2\subdir2\sub-subdir2
已经删除文件  : C:\directory2\subdir2\几个注意的地方.sql
已经删除目录  : C:\directory2\subdir2
已经删除目录  : C:\directory2
Done
20.1.16   遍历文件夹
在下面的示例程序中,将遍历给定的文件夹,并一个接一个地将所有的目录和文件的绝对路径和名
称都打印出来。
package cn.xuejava.file;
import java.io.File;
public class DisplayDirectoryAndFile {
public static void main(String args[]) { 
16
displayIt(new File("C:\\xuejava"));
}
public static void displayIt(File node) {
System.out.println(node.getAbsoluteFile());
if (node.isDirectory()) {
String[] subNote = node.list();
for (String filename : subNote) {
displayIt(new File(node, filename));  //递归
}
}
}
}
20.1.17   复制文件夹
在 下 面 的示 例 程序 中, 我 们 将文 件 夹 ”c:\\xuejava” 及 其 所 有 子目 录 和文 件 拷 贝到 一 个名
为”c:\\new-xuejava”的新文件夹中。
package cn.xuejava.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyDirectoryExample {
public static void main(String[] args) {
File srcFolder = new File("c:\\xuejava");
File destFolder = new File("c:\\new-xuejava");
//确保数据源存在
if (!srcFolder.exists()) {
System.out.println("您要拷贝的目录不存在.");
//然后退出
System.exit(0);
} else {
try {
copyFolder(srcFolder, destFolder);
} catch (IOException e) {
e.printStackTrace(); 
·17·
//如果出现错误,程序就退出
System.exit(0);
}
}
System.out.println("Done");
}
public static void copyFolder(File src, File dest)
throws IOException {
if (src.isDirectory()) {
//如果目标目录不存在,就先创建它
if (!dest.exists()) {
dest.mkdir();
System.out.println("将" + src + "复制到" + dest);
}
//列出所有的目录内容
String files[] = src.list();
for (String file : files) {
//构造源和目标文件结构
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//递归拷贝
copyFolder(srcFile, destFile);
}
} else {
//如果要拷贝的是文件,就直接复制
//使用字节流,以支持所有的文件类型
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
//以字节的形式拷贝文件内容
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
System.out.println("文件从" + src + "拷贝到" + dest);
}
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值