Java数据流教学课件_第1页
Java数据流教学课件_第2页
Java数据流教学课件_第3页
Java数据流教学课件_第4页
Java数据流教学课件_第5页
已阅读5页,还剩47页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第11章Java数据流

[内容提要]

大部分程序都需要数据的输入和输出,

从键盘读取数据,

向文件写入数据或从文件获取数据,

将数据通过打印机打印出来,

通过网络进行信息交换

本章介绍Java标准程序库中各种处理I/O操作的类

的用途及使用方法。

第1节输入/输出概念

一、流的概述

Java使用流(stream)来执行输入输出(I/O)

的功能)流是一种数据的源头和目的之

间的通信途径。

用于读入数据称为输入流(inputstream),

用于写出数据称为输出流(outputstream)o

当像用流时需要使用java.io包,因此在涉及数

据流操作的程序中都要先导入java.io包:

importjava.io.*;

二、I/O类层次结构

Java提供超过60个不同的流类型,这些流

类包含在上面提到的java.io包中,

四个基本的抽象类:

Inputstream、Outputstream、Reader和

Writero

你不能创建这四个类型的对象,但是其他

的方法的返回值可以是他们

InputStrearn

File

Outputstream

RandomAccessFile

Reader

StreaniTokemzer

Writer

图11-1定义在java,io包中的流结构

三、标准输入输出

在System类中有三个静态域System,in、

System,out和System,err。

可以在标准位置使用这三个系统流进行I/O操作O

publicstaticInputstreamin

读取字符数据的标准输入流。

publicstaticPrintstreamout

显示或打印输出信息的标准输出流

publicstaticPrintstreamerr

输出错误信息的标准错误流。

importjava.io.“一八,入,入]、、,一

publicclasslODemo{例11-1:标准输入输出举例

publicstaticvoidmain(Stringargs[])throwsIOException{

intb;

intcount=0;

//循环利用Sys比m.in钱收.输入存入b,在用Systern.out.输出b

〃如果遇到文件结束则终止循环

while((b=System.in.read())!=-1){

count4-F;

System.out.print((char)b);

}

Sysrem.out.println();

System,out.printin(rrprogramendrr);

!)

程序运行如下:

输入:a,b,c,d输出:a,b,c,d

输入:AZ(注:输入复合键CTRL-Z)输出:programend

第2节文件的顺序访问

一、字节流

字节流是用来读写8位的数据,由于不会对数据

作任何转换,因此可以用来处理二进制的数据。

(一)、Outputstream

(二)、Inputstream

(三)、FilelnputStream和FileOutputStream

(四)、ByteArraylnputStream^ByteArrayOutputStream

(五)、BufferedlnputStream^BufferedOutputStream

Inputstream输入流输出流的类继承关系

FilelnputStream

Outputstream

StringBufiferlnputStream

ByteArraylnputStreamFileOutputStream

SequencelnputStreamByteArrayOutputStream

PipedlnputStreamPipedOutputStream

FilterlnputStreamFilterOutputStream

BufferedlnputStreamBuflferedOutputStream

LineNumberlnputStreamPrintstream

DatalnputStreamDataOutputStream

PushbacklnputStream

(—0、Outputstream

Outputstream为所有的字节流输出流的父类,因

尼所有源自于它的类也会继承下列的方法:

voidwrite(intb):写入一个字节的数据。

voidwrite(byte[]buttfer):讲数组buffer的数据写

入流。

voidwrite(byte[]9intoffsetintlen):从buffer[offset]

开始,写入len个字节的数据。

voidflush():强制将buffer内的数据写入流。

voidclose():关闭流。

(二)、Inputstream

InputStream为所有的字节输入流的父类,因此

所宥痈于它的类也会继承下列的方法:

intread。:读入一个字节的数据,如果已达到文

件的末端,返回值为-L

intread(byte[]buffer):读出buffer大小的数据,

返回值为实际所读由的字节。

intread(byte[]bufferJntoffsetjntlen):臀读出的

数据从buffer[offset]开始,写入len个字节至

bufferf,返回值为实际所读出的字节数目。

intavailable():返回流内可供读取的字节数目。

longskip(longn):跳过n个字节的数据,返回值

为实像所述过的数据数。

voidclose():关闭流。

(三)、FilelnputStream^FileOutputStream

FilelnputStream用来读取一个文件,FileOutPutStream用

来修数据写入文件。

常用的构造函数如下:

FileInputStream(Stringname):打开文件name用来读取

数据。

FileInputStream(Filefile):打开文件行le用来读取数据。

FileOutputStream(Stringname):打开文件name用来写入

数据。

FileOutputStream(Filefile):打开文件行le用来写入数据。

FileOutputStream(Stringname,Booleanappend):孑丁开文

件name用来写入数据,若append为true,贝I写入的数据

会加到原有文件后面,否则,覆盖原有的文件。

将FileExam.java复制为FileExam.java.bako

1)程序首先打开FileExam.java文件,

2)使用read。将其内容逐字节读取出来(如果

返回值为则表明已到达文件尾端),

3)再使用write。将读出的字节逐一写入另一个

文件FileExam.java.bak中。

4)若文件无法打开(例如FileExam.java不存在)

或无法生成(FileExam.java.bak),会抛出

FileNotFoundException异常,若读写出错,

则会抛出lOException异常。

5)最后,我们在finally中关闭文件。

importjava..io.*;

publicclassFllelO(例例

pijJblicstaticvoidm.a.in(StringargsC]){・2

FilelnpiAtLSt-reaiiLinFile=null;

FileOu.tputLStreanaou.tFile=null;FilelO.java

try£//打开"FilaExaia.3ava"由次读取数据

inFile=neuFilelnpucStreaia(,TFileExaixi.iaT?a,r);

//4T5FFrrFileExam.java.bakrr用本与_A数据.

ou.t.F±le=newFileOxitpucStizeaiii(,rFi±i=!E:":;iiu.java.ba.kr,);

inndate;

while((date=inFile.read())•=一[){//从原文件1立取字干

//■次向目标文件耳人一个字干

o\itFile.write(date);

1)

cat.cli(FlieNotFoiAiiclExcepcione)(//处理立件不存在诘;况

System.out;,printIn(e.gemessage());

}

cacch(IOExceptione){//处理工。号常

Syscem.out.println(e.getMessage());

)

fInal1丫{//亳后的清理工作

//关闭、源文件

if(inFile•=nnll)<

3丫{inFile.close();}

catcH(IOExceptione){}

)

if(ont.File!=nu[[){//关闭目*示文件

trY(o\j.tFile.closeQ;}

catLCti(IOExcep11one)()

>}))

(J)、ByteArraylnputStream^

ByteArrayOutputStream

1)使用这两个流类可以将数据转换到一个数据类型为字

节类型的数组(bytearray)中,

2)ByteArraylnputStream^ByteArrayOutputStream^f-

没有牵涉到真正的文件,他们使用内存(一个流缓冲

区)作为I/O流的源头及目的。

3)ByteArrayInputstream用来从一个流缓冲区(字节数

组)中读入数据,

4)ByteArrayOutputStream用来将数据转换至一个流缓

冲区中

5)由于流对象的内容存放在内存中,所以可提供较快的

操作。

常用的构造函数如下:

ByteArrayInputStream(byte[]buffer):生成一个手节数组的

输入流,并指定一个字节数组buffer为此输入流的流缓冲区。

ByteArrayOutputStream():生成一个字节数组的输出流,其

缓冲区的默认初始大小为32字节,若有需要,缓冲区的大小

会随之增加。

ByteArrayOutputStream(intsize):同上,但分配size字节的初

始大小给此缓冲区。

ByteArrayOutputStream的一些常用方法:

intsize():返回此流缓冲区的大小。

byte[]toByteArray():生成一个新的字节数组,并将流的内

容复制到此字节数组。

StringtoString():I导流的内容转换为String对象。

下面程序读入文件data.in,将其内容写入内存中(一个字节数

组),接着转换为String对象,并将1该String对象内的令牌

解析出来。

importjava.io.*;

importjava.util.*;

publicclassByteI0(例11・3BytelO.java

publicstaticvoidmain(String[]args){

FileinFile=newFile("data,in");//田明源文件

FileinputscrearninData=newFilelnputStreamfinFile);

ByteArrayOutputStreamdataArray=newByteArrayOutputStreaii();

intdata;

while((data=inData.read())!=-1){

dataArray.vrite(data);

)

inData.close();

StringdataStr=dalaArray.coString。;〃将字节数.组转换成字符串

〃解析String对象内的令牌

StringTokenizertokens=newStrmgTokeiuzer(dataStr);

while(tokens.hasMoreTokens()){

Systeia.out.printin(tokens,nextToken());

}}

catch(IOExcep11one){

Systeiu.out.printin(e.getMessage());

}))

若输入数据(data.in中的数据)如下:

Aa00001926995

Bb00002779296

则程序输出如下:

Aa

00001

92

69

95

Bb

00002

77

92

96

(五)、BufferedlnputStream^

BufferedOutputStream

有时候我们在处理来自输入流的数据时,希望能够

重设流并回到较靠前的位置。

这需要使用缓冲来实现,通过使用

BufferedlnputStream^:,可以利用mark和reset方

法在缓冲的输入流中往回移动;

同时,通过使用BufferedOutputStream类,可以先

将输出写到内存缓冲区,再使用flush方法将数据

写入磁盘,而不必每输出-一个字节就向磁盘中写

一次数据。

1.BufferedlnputStream^:的构造函数和方法

•BufferedInputStream(InputStreamin):构造一个

BufferedlnputStream。

•BufferedInputStream(InputStreamin,intsize):构造一个

具有给定的缓冲区大力、BufferedlnputStreamo

•intavailable():得到可以从这个输入流读取的字节数。

•voidclose():关闭流。

•voidmark(intreadlimit):在这个输入流的当前位置做标记。

•booleanmarkSupported():检查这个输入流是否支持mark

和reset方法。

•intread():读取数据的下一个字节。

•intread(byte[]b,intoff,intlen):从这个字节输入流的给

定偏移量处开始读取字节,存储到给定的字节数组。

•voidreset():将缓冲区重新设置到加标记的位置。

•longskip(longn):跳过n个字节的数据。

2.BufferedOutputStream类的构造函数和方法:

•BufferedOutputStream(OutputStreamout):构造一个

BufferedOutputStream。

•BufferedOutputStream(OutputStreamout,intsize):构

造一个具有给定的缓冲区大小的

BufferedOutputStream。

•voidflush():刷新这个流。

•voidwrite(byte[]b,intoff,intlen):将给定的字节数组

写到这个缓冲输出流。

•voidwrite(intb):将给定的字节写到这个缓冲输出流。

下面我们通过一个例子来演示BufferedlnputStream类的

作用,程序读取并显示字节数组中的字符,当遇

至十%,字符时,如果和下一个,%,字符之间的字符

没有空格,则两个,%,之间的字符不显示:

importjava.io.*;

classbufinstrearns{

publicstaticvoidmain(Sttmaargs[])tiirowslOExcept.ion{

〃定义数据诲

bytedata口="Thisisatestofbuffervorreams.与匚口因口它11七二二”・9已七3¥七23();

BYteArraylnputStreamin=newByteArraylnput.Streaik(data);

BufferedlnputStreambufinstream=newBufferedlnput.Stream(in);

intcharacter;booleanflag=false;

while((character=bufinstream.read())•=-1){

switch(character){

caseT':例U・4

if(flag){〃第二个

flag=false;

}else{//第一个bufinstreams.java

flag=true;

bufinstream.mark(100);//力口标)己

break;

case,1:运行结果:

if(flag)(//3

flagI

SystJThisisatestofbuffer#Streams

〃将4

bufirf

)else

Syst.em.out.print((char)character);

break;

default:

if(!flag)System.out..print((char)character);

)1))

二、字符流

尽管字节流更快更高效,但是人们读起来十分困

难(因为是二进制)。

接下来我们讲述文本格式的输入输出,即字符流。

字符流主要是用来支持Unicode的文字内容,绝

大多数在字节流中所提供的类,都有相对应的

字符流的类。

ReaderWriter

BufferedReaderPrintWriter

BufferedWriter

InputStreamReader

OutputStreamWriter

FileReader

FileWriter

()、Reader和Writer

Reader是所有输入字符流的基类,Writer

是所有输出字符流的基类。

你可以使用从这两个类派生出的类来读写

字符流,这两个类常用的方法与

Inputstream>Outputstream相类似,区

别在于参数内的byte[]需要改为char

(二)、InputStreamReader和

OutputStreamWriter

为了从键盘读取按键,常常从System.iii构

造一个InputStreamReader流)然后使用

InputStreamReader^:的read方法读取用

户输入的内容。

而OutputStreamWriter与

InputStreamReader相对)支持输出流。

1.InputStreamReader^:的构造函数和方法:

•InputStreamReader(InputStreamin):构造一个

InputStreamReader。

•InputStreamReader(InputStreamin,Stringenc):

使用命名的字符编玛构造一个InputStreamReader。

•voidclose():关闭流。

•StringgetEncoding():得到字符编码的名称。

•intread():读取一个字符。

•intread(char[]cbuf,intoff,intlen):将字符读到

数组工

•booleanready():如果这个流已准备好,返回

True。

2.OutputStreamWriter类的构造函数和方法:

•OutputStreamWriter(OutputStreamout):构造一个

OutputStreamWritero

•OutputStreamyVriter(OutputStreamout,Stringenc):使

用命名的字符编码构造一个OutputStreamWriter。

•voidclose():关闭流。

•voidflush():刷新流。

•StringgetEncoding():得到这个流使用的字符编码的名称。

•voidwrite(char[]cbuf,intoff,intlen):写字符数组的一部

分。

•voidwrite(intc):写一个字符。

•voidwrite(Stringstr,intoff,intlen):写一个字符串的一部

分。

下面的程序利用InputStreamReader从键盘接受输入,再将输

入的字符显示出来:

inputstreamreader.java

importjava.io.*;

classinputstreamreader{

publicstaticvoidmam(Stringargs[]){例11-5

try1、

intcharacter;

InputstreaioP.eaderinstreaiaread=newInputStLeanF'.eader(System,in);

/Inputs(口reainReader以字符形式序取输入

while((character=instreamread.read())1=-1){

Ystem.out.print((char)character);

catch(lOExcepnone)()

J

System,out.print(rrBye,r);

犷……八….一•

程序运行结果如下:

输入:a,bqd输出:a9b9c9d

输入:1,2,3,4输出:1,2,3,4

输入:AZ输出:Bye

(三)、FileReader

你可以使用FileReader类创建一个字符流来读取

一个文件,FileReader类只具有女

InputStreamReader继承的功能,但是它有自

己的构造函数:

•FileReader(Filefile):构造一个FileReader。

•FileReader(FileDescriptorfd):从一个文件描

述符构造一个FileReader。

•FileReader(Stringfilename):从一个文件名构

造一个FileReader。

在下面的例子中,我们打开一个文件file.txt(内容

为:"Hellofromfile”),将文件的内容读到缓冲

区,然后显示数据:

fileread.java

importjava.io.*;例11-6

publicclassfileread{

publicstaticvoidmam(Stringargs[])throwsException

FileReaderfileread=newFileReadertxtH);

chardata[]=newchar[1024];

intcharsread=fileread.read(data);

System.out.printin(newString(data,0,charsread));

fileread,close();

)}

程序运行结果如下:

Hellofromfile

(四)、FileWriter

FileWriter与FileReader对应,用来将1字符缓冲区中的数

据写到文件中。这个类也只定义了构造函数,此外只

具宥灰OutputStreamWriter继承的功能。

•FileWriter(Filefile):从File对象构造一个FileWriter。

•FileWriter(FileDescriptorfd):从文件描述符构造一

个FileWriter。

•FileWriter(Stringfilename):从文件名构造一个

FileWritero

•FileWriter(Stringfilename,booleanappend):构造一进

行附加的FileWriter。

在下面例子中,我们分别采用三种方式:逐字符地写数

据、一次写入所有数据、分批写数据,使用FileWriter:

filewrite.java

importjava.io.*;例11-7

publicclassfilewrite{

publicstaticvoidmain(String[]args)throwsExceptionf

,,1

chardata口={'T»zh,,s/'/a'z

11111

•zo*,1f•,1'z*e'z'x'z,1.1);

FileWriterfilewriterl=newFilelJritertxtrr);

〃逐字符地写数据

for(intloop_index=0;loop_index<data.length;loop_index-H-){

fileuriterl.write(data[1oop_index]);

}一

FileWriterfilevriterZ=newFileUnter(rrfile2.;

〃一次写入所有敏据

fileuriter2.write(data);

FileUriterfileuriter3=newFileUriter(file3.txt^);

门分批写人数据程序执行后:

filevriter3.write(data,5

filewriterl.close();gel.txt和file2.txt的内容为:

fileuriter2.close();Thisisastringoftext.

filewriter3.close();

))me3.txt的内容为:isastrin

(五)、CharArrayReader^CharArrayWriter

1.CharArrayReader类的构造函数和方法如下:

•CharArrayReader(char[]buf):从给定的字符数组构造一个

CharArrayReader。

•CharArrayReader(char[]buf,intoffset,intlength):同上。

•voidclose():关闭流。

•voidmark(intreadAheadLimit):在流中的当前位置加标记。

•booleanmarkSupported():如臬这个流支持mark操作,那么

返回True。

•intread():读取一个字符。

•intread(char[]b,intoff,intlen):4寻字符读人数组的一部分。

•booleanready():检查这个流是否已经准备好被读取。

•voidreset():将流重设到最近的标记。

•longskip(longn):跳过n个字符。

•CharArrayWriter():构造一个CharArrayWriter。

•CharArrayWriter(intinitialSize):构造一个具有给定初始大小

的CharArrayWritero

•voidclose():关闭流。

•voidflush():刷新流。

•voidreset():重设流。

•intsize():得到缓冲区的当前大小。

•char[]toCharArray():得到输入数据的副本。

•StringtoString():4寻输入数据转换为字符串。

•voidwrite(char[]c,intoff,intlen):将字符写到缓冲区中。

•voidwrite(intc):羽1一个字符写到缓冲区中。

•voidwrite(Stringstr,intoff,intlen):4寻字符串的一部分写到缓

冲区中。

•voidwriteTo(Writerout):4等缓冲区的内容写到另一个字符流

中。

chararrayreader.java

importjava.io.*;例

publicclasschararrayreader{11-8

publicstaticvoidmain(Stringargs[])throwslOException{

chardata[]={*T1'h111',1s1'lull's'/'Ja',

1/叫

,、tJI,

CharArrayReaderchararrayreader=newCharArrayReader(data);

intcharacter;

while((character=chararrayreader.read()),=-1){

}}.}System.out.print—((char—)character);

程序运行结果为:

Thisisastringoftext.

第3节文件的随机访问

前面所提及的流都是顺序的I/O流,无法随

机的读写文件的某个位置,如果需要对

文件进行随机的访问,必须使用

RandomAccessFile类)其常用的构造函

数如下:

•RandomAccessFile(Filefile,Stringmode):构造一个随机访

问文件流,行能为被访问的文作好象,mode是用来指定存

取的模式,mode可改为r(读)、w(写)或rw(读写)。

•RandomAccessFile(Stringname.Stringmode):构造一个随

机访问文件流,以彳更访商由字符串name指定名字的文件,

mode参数使用同上。

•RandomAccessFile类提供的用来读取某种基本数据类型的

数据或字符串的方法如下:

•booleanreadBoolean()

•bytereadByte()

•charreadChar()

•doublereadDouble()

•floatreadFloat()

•intreadlnt()

•longreadLong()

•shortreadShort()

•StringreadLineQ

•RandomAccessFile类提供的用来向文件中写入

某种基本类型的数据或字符串的方法如下:

•voidwriteByte(byteb)

•voidwriteBytes(Strings)

•voidwriteChar(charc)

•voidwriteChars(Strings)

•voidwriteDouble(doubled)

•voidwriteFloat(floatf)

•voidwritelnt(inti)

•voidwriteLong(long1)

•voidwriteShort(shorts)

­和目前文件位置有关的方法:

•voidseek(longpos):将文件指针移到

pos(不可为负)的位置)这是相对于文

彳牛的初始位置的值(初始值为0)。

•longgetFilePointer():得至U目前文件指

针的位置(相对于文件初始位置)。

•longlengthQ:得至文件的长度。

第4节目录和文件管理

File类是一个和流无关的类。

File对象可以用来生成与文件(及其所在的路径)

或目录结构相关的对象,

由于不同的系统可能会有不同的目录结构表示法,

使用File类可以达到与系统无关的目的(使用抽

象的路径表示法)。

类java.io.File提供了获得文件基本信息及操作文

件的一些方法。

File类的构造函数:

File(Stringpath):将一个代表路径的字符串转换为抽象的

路径表示法。

File(Stringparent,Stringchild):parent代表目录,child

代表文件(不可为空)。

File(Fileparent,Stringchild):同上。

例如:

FilemyFile;

myFile=newFile("行le.txt");

或

myFile=newFile("/","file,txt");

或

FilemyDir=newFile("/");

myFile=newFile(myDir,wfile.txf?);

使用何种构造函数经常由其他被访问的文

件对象来决定。

例如,

当在应用程序中只用到一个文件时,那么

使用第一种构造函数最为实用;

但是如果使用了一个共同目录下的几个文

件,则使用第二种或第三种构造函数会

更方便。

File类一些常用的方法

•booleanexists():若该文件或目录存在,返回True。

•booleanisDirectory():若为目录则返回True。

•File[]listFiles():得前该对象所代表的目录下的File对象数组。

•String[]list():同上。

•longlength。:得到和该对象相关的文件大小,若不存在,返回

Oo

•StringtoString():得到抽象路径表示法。

•StringgetParent():得到抽象路径表示法的目录部分。

•StringgetName():得到抽象路径表示法的最后一个部分。

•booleanrenameTo(FilenewName):^当前File对象所代表的路

径名改为newName所代表的路径名。若成功,返回true。

•booleanmkdir():生成一个新的目录。若成功,返回True。

•booleanmkdirs():生成一个新的目录,包含子目录。若成功,

返回true。

•booleandelete():删除目前File对象代表的文件或目录,目录需

为空。删除成功,返回true。

importjava.io.*;

classfile(

publicstaticvoidnain(5tring[]args){

Filefl=newFile(rftile.t>:tff);例11・9

System,out.printin("Tiefileisexist?rr+fl.exists());

5ysteia.out.println(,rTlietilecanwrite?r,+fl.canUrite());

System,out.printin(r,Tliefilecanread?rr+fl.canRead());

System,out.printin(nTliefile1程序运行结果如下:

System,out.printin(n,HiefileiThefileisexist?true

System,out.printin(rrThefile1:Thefilecanwrite?true

rr1

System,out.printin(Thefile:Thefilecanread?true

Systeia.out.printin("Thefile'sThefileisafile?true

})Thefileisadirectory?false

The行Ie'snameis:file.txt

Thefile!sallpathis:C:\Java\file.txt

Thefile'slengthis15

第5节其他常用的流处理

一、管道流

管道(pipe)提供一种线程之间的通信方法,可用

于IPCQnter-ProcessCommunication进程间通

信)或是ITC(Inter・ThreadCommunication线

程间通信),但不能够在不同主机间进行通信。

一个输入管道是用来接收一个输出管道所写出的

数据,因此,一个线程会负责送出

(PipedOutputStream对象)数据,而另一个

线程序要负责接收(PipedlnputStream对象)

这些数据,PipedlnputStream和

PipedOutputStream对象总是成对出现的。并

且由于管道的数据流是单向的

(一)、创建一组管道通信可以按照下面步骤进

行(使用无参数的构造函数)

建立输入流:

PipedlnputStreampipedinputstream=

newPipedIn

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论