java字符流

前言
输入流:把数据(键盘输入、鼠标、扫描仪等等外设设备)读入到内存(程序)中

输出流:把内存(程序)中的数据输出到外设或其他地方,从文件角度简单总结就是,输入流就是读数据,输出流就是写数据。

在这个过程中,始终把内存作为参考点。

在JAVA语言中,定义了专门的类用来表示输入和输出,这些类放在java.io包中。按数据传输单位划分,可以分为字节流和字符流。

本文重点介绍字符流

Reader:输入流、继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符16位
在这里插入图片描述

Writer:输出流、继承自Writer的流都是程序用于向外输出数据的,且数据单位都是字符(16位)
在这里插入图片描述

一、输入流

1.1 Reader

public abstract class Reader extends Object implements Readable, Closeable

用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。

protected Reader()  创建一个新的字符流 reader,其重要部分将同步其自身的 reader。 
	
protected Reader(Object lock)  创建一个新的字符流 reader,其重要部分将同步给定的对象。参数:lock - 要同步的对象。 

方法摘要

关闭方法

void close()

字符输入方法

//试图将字符读入指定的字符缓冲区。缓冲区可照原样用作字符的存储库:所做的唯一改变是 put 操作的结果。不对缓冲区执行翻转或重绕操作。
//返回:添加到缓冲区的字符数量,如果此字符源位于缓冲区末端,则返回 -1
int  read(CharBuffer target)
//读取单个字符,返回:作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1
int  read() 
//将字符读入数组。返回每次所读取进入字符数组字符的个数,如果已到达流末尾,则返回 -1 
int read(char[] cbuf)	
//将字符读入数组的某一部分。返回每次所读取进入字符数组字符的个数,如果已到达流末尾,则返回 -1
int read(char[] cbuf, int off, int len)
//参数:cbuf - 目标缓冲区
//参数:off - 开始存储字符处的偏移量
//参数:len - 要读取的最多字符数

案例

Reader reader = new BufferedReader(new FileReader("D:/hello.txt"));
char[] c = new char[5];
int number = 0;
while((number=reader.read(c, 0,  c.length))!=-1){
	     System.out.println(number);
	     System.out.println(new String(c,0,number));
}
5
必定是基
5
本的精髓的
2
数据

标记方法

//当且仅当此流支持此 mark 操作时,返回 true。
boolean markSupported()   
//标记流中的当前位置。对 reset() 的后续调用将尝试将该流重新定位到此点。
//参数:readAheadLimit - 在仍保留该标记的情况下,对可读取字符数量的限制。
//在读取达到或超过此限制的字符后,尝试重置流可能会失败。限制值大于输入缓冲区的大小将导致分配一个新缓冲
//区,其大小不小于该限制值。因此应该小心使用较大的值。
void mark(int readAheadLimit)
void reset() //将流重置到最新的标记。

其他方法

long skip(long n) //跳过字符
//	判断此流是否已准备好被读取。如果缓冲区不为空,或者底层字符流已准备就绪,则缓冲的字符流准备就绪。
//如果保证下一个 read() 不阻塞输入,则返回 True,否则返回 false。注意,返回 false 并不保证阻塞下一次读取
boolean ready()
1.2 StringReader

public class StringReader extends Reader 其源为一个字符串的字符流。

StringReader(String s) 创建一个新字符串 reader 
1.3 PipedReader

public class PipedReader extends Reader 传送的字符输入流。

PipedReader()   创建尚未连接的 PipedReader。 
	
PipedReader(int pipeSize)   创建一个尚未连接的 PipedReader,并对管道缓冲区使用指定的管道大小。 
	
PipedReader(PipedWriter src)   创建连接到传送 writer src 的 PipedReader。 
	
PipedReader(PipedWriter src, int pipeSize)   创建一个 PipedReader,使其连接到管道 writer src,并对管道缓冲区使用指定的管道大小 

非继承方法

void connect(PipedWriter src) 使此传送 reader 连接到传送 writer src。 
1.4 InputStreamReader

public class InputStreamReader extends Reader

这是java.io包中用于处理字符流的基本类,用来在字节流和字符流之间搭一座“桥”。这里字节流的编码规范与具体的平台有关,
可以在构造流对象时指定规范,也可以使用当前平台的缺省规范InputStreamReader 是字节流通向字符流的桥梁:(前提是我们要读的字节是字符串,不然会乱码)它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例

如:BufferedReader in= new BufferedReader(new InputStreamReader(System.in));将字节流转换成字符流

构造方法

InputStreamReader(InputStream in)  创建一个使用默认字符集的 InputStreamReader。 
	
InputStreamReader(InputStream in, Charset cs)   创建使用给定字符集的 InputStreamReader。 
	
InputStreamReader(InputStream in, CharsetDecoder dec)  创建使用给定字符集解码器的 
	
InputStreamReader InputStreamReader(InputStream in, String charsetName)  创建使用指定字符集的 InputStreamReader。 

非继承方法

String getEncoding() 返回此流使用的字符编码的名称。 
1.5 FileReader

public class FileReader extends InputStreamReader

用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在
FileInputStream 上构造一个 InputStreamReader。
FileReader 用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream。

构造方法

FileReader(File file)  在给定从中读取数据的 File 的情况下创建一个新 FileReader。 
	
FileReader(FileDescriptor fd)   在给定从中读取数据的 

FileDescriptor 的情况下创建一个新 FileReader。 

FileReader(String fileName)   在给定从中读取数据的文件名的情况下创建一个新 FileReader 
	
1.6 CharArrayReader

public class CharArrayReader extends Reader 此类实现一个可用作字符输入流的字符缓冲区。

构造方法

CharArrayReader(char[] buf)   根据指定的 char 数组创建一个 CharArrayReader。 
	
CharArrayReader(char[] buf, int offset, int length)  根据指定的 char 数组创建一个 CharArrayReader 

非继承方法没有

1.7 BufferedReader

public class BufferedReader extends Reader

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如,

BufferedReader in= new BufferedReader(new FileReader("foo.in"));

将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。通过用合适的 BufferedReader 替代每个 DataInputStream,可以对将 DataInputStream 用于文字输入的程序进行本地化。

构造方法

BufferedReader(Reader in)创建一个使用默认大小输入缓冲区的缓冲字符输入流 
	
BufferedReader(Reader in, int sz)创建一个使用指定大小输入缓冲区的缓冲字符输入流 

非继承方法

String  readLine() 

//读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。 

//返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null 

D:/hello.txt:必定是基本的精髓的数据

BufferedReader reader = new BufferedReader(new FileReader("D:/hello.txt"));

String str="";

while((str = reader.readLine())!=null){

  System.out.println(str);

}
必定是基本的精髓的数据
1.8 FilterReader

public abstract class FilterReader extends Reader

用于读取已过滤的字符流的抽象类。抽象类 FilterReader 自身提供了一些将所有请求传递给所包含的流的默认方法。FilterReader 的子类应重写

这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

构造方法

protected FilterReader(Reader in) 创建一个新的 filtered reader。 

非继承方法没有

1.9 LineNumberReader

public class LineNumberReader extends BufferedReader

跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。

默认情况下,行编号从 0 开始。该行号随数据读取在每个行结束符处递增,并且可以通过调用 setLineNumber(int) 更改行号。但要注意的是,setLineNumber(int) 不会实际更改流中的当前位置;它只更改将由 getLineNumber() 返回的值。可认为行在遇到以下符号之一时结束:换行符(’\n’)、回车符(’\r’)、回车后紧跟换行符。

构造方法

LineNumberReader(Reader in)  使用默认输入缓冲区的大小创建新的行编号 reader。 

LineNumberReader(Reader in, int sz )创建新的行编号 reader,将字符读入给定大小的缓ib冲区 

非继承方法

int getLineNumber() 获得当前行号。 

void setLineNumber(int lineNumber) 设置当前行号。 

String readLine() 读取文本行。 
1.10 PushbackReader

public class PushbackReader extends FilterReader

作用:剔除不需要的字符

构造方法

PushbackReader(Reader in)  创建具有单字符推回缓冲区的新推回 reader。 
	
PushbackReader(Reader in, int size) 创建具有给定大小推回缓冲区的新推回 reader 

非继承方法

void unread(char[] cbuf) //推回一个字符数组,方法是将其复制到推回缓冲区前面。 
	
void unread(char[] cbuf, int off, int len) //推回字符数组的某一部分,方法是将其复制到推回缓冲区的前面。 
	
void unread(int c) //推回单个字符:将其复制到推回缓冲区的前面。 
String  str="www.hello.wc";

CharArrayReader  in = new  CharArrayReader(str.toCharArray());

PushbackReader. back = new PushbackReader(in);

int c;

while((c=in.read())!=-1){
  if((char)c=='.'){
  back.unread((char)c);//back.unread(c);
  back.read();
}else{
  System.out.print((char)c);//wwwhellowc
}}

二、输出流

2.1 Writer

public abstract class Writer extends Object implements Appendable, Closeable, Flushable

写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。但是,多数子类将

重写此处定义的一些方法,以提供更高的效率和/或其他功能

构造方法

protected  Writer()   创建一个新的字符流 writer,其关键部分将同步 writer 自身。 

protected Writer(Object lock)    创建一个新的字符流 writer,其关键部分将同步给定的对象。 

方法摘要

Writer append(char c) 
	
Writer append(CharSequence csq) 

Writer append(CharSequence csq, int start, int end) 

abstract void close() 

abstract void flush() 

void write(char[] cbuf) 

abstract void write(char[] cbuf, int off, int len) 

void write(int c) 

void write(String str) 

void write(String str, int off, int len) 

刷新流

void flush()  // 刷新该流的缓冲。 

为什么关闭流之前要flush()?

flush()这个函数是清空的意思,用于清空缓冲区的数据流,进行流的操作时,数据先被读到内存中,然后再用数据写到文件

中,那么当你数据读完时,我们如果这时调用close()方法关闭读写流,这时就可能造成数据丢失,为什么呢,因为,读入数

据完成时不代表写入数据完成,一部分数据可能会留在缓存区中,为了理解这个问题,我们举一个例子:

比如,在农村,几乎每家都有抽水机,抽水机的作用是什么呢,就是把水井里的水抽到水缸中,这时我们就会用水管连接抽水

机和水缸(水管就好比是缓冲区),当我们想把水井中的水都抽到水缸中时,我们就让抽水机工作抽水,如果我们发现水井里的

水刚好抽完时,我们就会关掉抽水机的开关停止抽水,那么这时,管道里就会遗留一部分水,抽水就是读数据,水缸进水就是

写数据,水管充当缓存区的角色,不知道这样是不是具象化了呢

那么这样一来我们如果中途调用close()方法,输出区也还是有数据的,就像水缸里有水,只是在缓冲区遗留了一部分,这时

如果我们先调用flush()方法,就会强制把数据输出,缓存区就清空了,最后再关闭读写流调用close()就完成了

关闭方法

void close()  关闭此流,但要先刷新它。 

字符输出方法

void write(char[] cbuf)  // 写入字符数组。 
void write(char[] cbuf, int off, int len)   //写入字符数组的某一部分。 
void write(int c )   //写入单个字符。 
void write(String str)   // 写入字符串。
void write(String str, int off, int len)    //写入字符串的某一部分。  
FileOutputStream fos = new FileOutputStream("D:/hello.txt");

OutputStreamWritero sw = new OutputStreamWriter(fos);

BufferedWriter bw = new BufferedWriter(osw);

bw.write("abc");

bw.write("\n");

bw.write("def");

bw.flush()

bw.close();

如果在linux下查看如上代码写出的文本文件没有问题,abc和def之间是有换行的,

如果是在windows下用记事本看是在同一行。但是在windows下用NotePad++,abc和def之间是有换行的

原因就是linux以\n换行,windows记事本中以\r\n换行。

字符输出追加方法

Writer append(CharSequence csq)    //将指定字符序列添加到此 writer。 
Writer append(char c )   //将指定字符添加到此 writer。 
Writer append(CharSequence csq, int start, int end)   // 将指定字符序列的子序列添加到此 writer.Appendable。
2.2 StringWriter

public class StringWriter extends Writer

一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。

关闭 StringWriter 无效。此类中的方法在关闭该流后仍可被调用,而不会产生任何 IOException。

构造方法

StringWriter()  使用默认初始字符串缓冲区大小创建一个新字符串writer 

StringWriter(int initialSize)  使用指定初始字符串缓冲区大小创建一个新字符串 writer。

非继承方法

StringBuffer getBuffer() 返回该字符串缓冲区本身。 
StringBuffer getBuffer() 返回该字符串缓冲区本身。
String toString() 以字符串的形式返回该缓冲区的当前值。
StringWriter bw = new StringWriter();

bw.write("http://www.google.com");

bw.write("\n");

bw.write("http://www.baidu.com");

System.out.println(bw.toString());

System.out.println(bw.getBuffer().toString());

http://www.google.com
http://www.baidu.com
http://www.google.com
http://www.baidu.com
2.3 PipedWriter

public class PipedWriter extends Writer 传送的字符输出流。

构造方法

PipedWriter()  创建一个尚未连接到传送 reader 的传送 writer 

PipedWriter(PipedReader snk)  创建传送 writer,使其连接到指定的传送 reader 

非继承方法

void connect(PipedReader snk) 将此传送 writer 连接到接收方。 
2.4 OutputStreamWriter

public class OutputStreamWriter extends Writer 用于将写入的字符编码成字节后写入一个字节流

这是java.io包中用于处理字符流的基本类,用来在字节流和字符流之间搭一座“桥”。这里字节流的编码规范与具体

的平台有关,可以在构造流对象时指定规范,也可以使用当前平台的缺省规范

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的

字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字

节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给

write() 方法的字符没有缓冲。

为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:

Writer out = new BufferedWriter(new OutputStreamWriter(System.out));

代理对 是一个字符,它由两个 char 值序列表示:高 代理项的范围为 ‘\uD800’ 到 ‘\uDBFF’,后跟范围为 ‘\uDC00’

到 ‘\uDFFF’ 的低 代理项。

错误代理元素 指的是后面不跟低代理项的高代理项,或前面没有高代理项的低代理项。

此类总是使用字符集的默认替代序列 替代错误代理元素和不可映射的字符序列。如果需要更多地控制编码过程,则应

该使用 CharsetEncoder 类。

构造方法

OutputStreamWriter(OutputStream out)创建使用默认字符编码的 OutputStreamWriter。 
	
OutputStreamWriter(OutputStream out, Charset cs)创建使用给定字符集的 OutputStreamWriter。 

OutputStreamWriter(OutputStream out, CharsetEncoder enc) 创建使用给定字符集编码器的OutputStreamWriter。 

OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的 OutputStreamWriter 

非继承方法

String getEncoding() 返回此流使用的字符编码的名称。 
2.5 FileWriter

public class FileWriter extends OutputStreamWriter

用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些

值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。

文件是否可用或是否可以被创建取决于底层平台。特别是某些平台一次只允许一个 FileWriter(或其他文件写入对

象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。

FileWriter 用于写入字符流。要写入原始字节流,请考虑使用 FileOutputStream。

构造方法

FileWriter(File file)     根据给定的 File 对象构造一个 FileWriter 对象 

FileWriter(FileDescriptor fd)    构造与某个文件描述符相关联的 FileWriter 对象。 

FileWriter(String fileName)    根据给定的文件名构造一个 FileWriter 对象。 

FileWriter(File file, boolean append)   根据给定的 File 对象构造一个 FileWriter 对象。 

FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 

FileWriter 对象,如果为 true,则将字节写入文件末尾处,而不是写入文件开始处 

非继承方法没有

2.6 CharArrayWriter

public class CharArrayWriter extends Writer

此类实现一个可用作 Writer 的字符缓冲区。缓冲区会随向流中写入数据而自动增长。可使用 toCharArray() 和

toString() 获取数据。

注:在此类上调用 close() 无效,并且在关闭该流后可以调用此类中的各个方法,而不会产生任何 IOException。

构造方法

CharArrayWriter()   创建一个新的 CharArrayWriter。 

CharArrayWriter(int initialSize)  创建一个具有指定初始大小的新 CharArrayWriter。 

非继承方法

char[] toCharArray() 返回输入数据的副本。 

String toString() 将输入数据转换为字符串。 

void writeTo(Writer out) 将缓冲区的内容写入另一个字符流。 
2.7 PrintWriter

public class PrintWriter extends Writer

向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字

节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。

与 PrintStream 类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能

完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。此类中的

方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用 checkError() 是否出现错误。

构造方法

//使用指定文件创建不具有自动行刷新的新 PrintWriter。 
PrintWriter(File file)  
//创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter 
PrintWriter(File file, String csn)   

// 创建具有指定文件名称且不带自动行刷新的新 
PrintWriter(String fileName) 

// 创建具有指定文件名称和字符集且不带自动行刷新的新 
PrintWriter PrintWriter(String fileName, String csn) 

// 创建不带自动行刷新的新 PrintWriter。 
PrintWriter PrintWriter(Writer out)  

//根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。 
PrintWriter(OutputStream out)  

//通过现有的 OutputStream 创建新的 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush)   

//创建新 PrintWriter,如果为 true,则 println、printf 或 format 方法将刷新(flush)输出缓冲区,默认false 
PrintWriter(Writer out, boolean autoFlush  

print基本类型

void print(char c) 
void print(int i) 
void print(long l) 
void print(float f) 
void print(double d) 
void print(boolean b) 

println基本类型

void println(char x) 
void println(int x)
void println(long x) 
void println(float x)
void println(double x) 
void println(boolean x) 

print引用类型

void print(char[] s) 
void print(Object obj) 
void print(String s) 

println引用类型

void println() 
void println(Object x) 
void println(String x)
void println(char[] x) 

格式化输出

PrintWriter format(Locale l, String format, Object... args)    使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。 
	
PrintWriter format(String format, Object... args)   使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。 

字符追加输出

PrintWriter append(char c)   将指定字符添加到此 writer。 

PrintWriter append(CharSequence csq) 
将指定的字符序列添加到此 writer。此方法调用 out.append(csq) 的行为与调用下列方法完全相同:out.write(csq.toString()) 

PrintWriter append(CharSequence csq, int start, int end)    将指定字符序列的子序列添加到此 writer。 

错误状态

protected void setError()    指示已发生错误。 

boolean checkError()   如果流没有关闭,则刷新流且检查其错误状态。 

protected void clearError()   清除此流的错误状态。 

案例

PrintWriter bw = new PrintWriter(new FileWriter("D:/hello.txt")); 
	
bw.println("abc"); 

bw.flush();

bw.close(); 

每次输入前,文本几乎清空,然后添加"abc"

2.8 FilterWriter

public abstract class FilterWriter extends Writer

用于写入已过滤的字符流的抽象类。抽象类 FilterWriter 自身提供了一些将所有请求传递给所包含的流的默认方

法。FilterWriter 的子类应重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

构造方法

protected FilterWriter(Writer out)  创建一个新的 filtered writer。 

非继承方法没有

2.8 BufferedWriter

public class BufferedWriter extends Writer

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有

平台都使用新行符 (’\n’) 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。

通常 Writer 将其输出立即发送到底层字符或字节流。除非要求提示输出,否则建议用 BufferedWriter 包装所有其

write() 操作可能开销很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如,

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(“foo.out”)));

将缓冲 PrintWriter 对文件的输出。如果没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后立即写

入到文件,而这是极其低效的。

构造方法

BufferedWriter(Writer out   )创建一个使用默认大小输出缓冲区的缓冲字符输出流。 

BufferedWriter(Writer out, int sz) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 

非继承方法

void newLine() 写入一个行分隔符。 

public void newLine() throws IOException {write(lineSeparator);} 
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值