版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1.1系统技术栈介绍——文件操作System.IO命名空间File类和FileInfo类Directory类和DirectoryInfo类FileStream类流和文件流StreamReader类和StreamWriter类Path类BufferedStream类序列化与反序列化知识回顾String类高效的StringBuilder类DateTime类Random类学习目标通过本节学习可以:重点学习File类和FileInfo类重点学习FileStream类重点学习StreamReader类和StreamWriter类掌握Directory类和DirectoryInfo类掌握Path类掌握BufferedStream类掌握序列化与反序列化了解流和文件流了解System.IO命名空间01流和文件流流和文件流在计算机中,无论是文本、图片、音频还是视频,所有的文件都是以二进制(字节)形式存储的。为此,C#专门针对文件的输入输出操作提供了一系列的流,统称为文件流。文件流是程序中最常用的流,根据数据的传输方向可将其分为输入流和输出流。为了方便理解,可以把输入流和输出流比作两根“水管”,如下图所示。集合概述流和文件流上图中,输入流被看作是一个输入管道,输出流被看作是一个输出管道,数据通过输入流从源设备输入到程序中,通过输出流从程序中输出到目标设备中,从而实现数据的传输。由此可见,文件流中的输入输出都是相对于程序而言的。流和文件流02System.IO命名空间System.io命名空间在C#中,文件操作类都位于System.IO命名空间中,因此在使用这些类时需要引入System.IO命名空间。该命名空间中包含了很多类,为了方便初学者更好地学习,接下来通过一个图例来介绍System.IO命名空间中的常用类,如下图所示。System.IO命名空间System.io命名空间上图中列举了一些常用的类,这些类大致可分为操作目录的类、操作文件的类、操作文件路径的类等。其中,Directory和DirectoryInfo属于操作目录的类,FileStream、File和FileInfo属于操作文件的类,StreamReader、StreamWriter类属于操作文本文件的类,Path类属于操作文件路径的类。System.IO命名空间03File类和FileInfo类File类File类是一个静态类,它提供了许多静态方法,用于处理文件,使用这些方法可以对文件进行创建、移动、查询和删除等操作,接下来介绍File类中的一些常用静态方法,如下表所示。方法说明FileStreamCreate(stringpath)根据传入的路径创建一个文件,如果文件不存在,则创建文件,如果存在且不是只读的,则覆盖其内容。voidDelete(stringpath)如果文件存在,则删除指定的文件,如果指定的文件不存在也不引发异常。boolExists(stringpath)判断指定文件是否存在,若存在则返回ture,否则返回false。voidMove(stringsourceFileName,stringdestFileName)将指定的文件移动到新位置,可以在新位置为文件指定不同的名称。FileStreamOpen(stringpath,FileModemode)打开指定路径上的文件并返回FileStream对象。voidCopy(stringsourceFileName,stringdestFileName)将现有的文件内容复制到新文件中,可以指定是否允许覆盖同名的文件。File类File类接下来通过一个案例来演示如何调用这些方法,具体代码如下所示。namespaceProgram01{classProgram{staticvoidMain(string[]args){File.Create("Data.txt");
Console.WriteLine("文件创建成功");if(File.Exists("Data.txt")){
Console.WriteLine("Data.txt文件存在");}else{Console.WriteLine("Data.txt文件不存在");}Console.ReadKey();}}}File类创建文件判断文件是否存在File类相对路径是指当前文件相对于与其他文件(或文件夹)之间的路径关系。例如,如果在路径D:\workspace\a\b\下有程序文件b.cs和文本文件a.txt,那么相对于b.cs文件,a.txt文件与它就是在同一文件目录下,在b.cs文件中调用a.txt文件时,直接写文件名即可。相对路径使用符号“/”表示,具体使用方式如下:在斜杠前面加一个点“./”表示上一级目录;在斜杠前面加两个点“../”表示当前文件的根目录。绝对路径是指文件在磁盘上的完整路径,例如b.cs程序调用a.txt时填写D:\workspace\a\b\a.txt,在程序中使用绝对路径时需要注意该路径的位置,当该位置发生改变时可能会导致异常。多学一招FileInfo类FileInfo类与File类比较类似,它们都可以对磁盘上的文件进行操作。不同的是FileInfo类是实例类,所有的方法都只能在实例化对象后才能调用。创建FileInfo类的对象时必须传递一个文件路径作为参数,具体代码如下:FileInfoaFile=newFileInfo(@"C:\Data.txt");上述代码表示使用FileInfo类创建一个对象,将文件路径作为参数,而路径中@符号表示不解析转义字符,如果没有@前缀就需要用“\\”替代“\”。通过前面的学习可知,“\”是一个转义字符,在程序中要表示一个“\”就需要使用“\\”。例如下面这行代码:FileInfoaFile=newFileInfo("C:\\Data.txt");FileInfo类FileInfo类FileInfo类中除了有许多与File类相似的方法外,同时也有它特有的属性,如下表所示。属性说明Directory该属性用于检索一个DirectoryInfo对象,表示当前文件所在的目录。DirectoryName该属性用于返回文件目录,而且这个属性是只读的。IsReadOnly该属性用于判断文件是否是只读的。Length该属性用于获取文件的大小(以字节为单位),并返回long值。FileInfo类Fileinfo类接下来通过一个案例来学习FileInfo类中的方法与其特有属性的使用,具体代码如下所示。staticvoidMain(string[]args){FileInfoaFile=newFileInfo("Data.txt");aFile.Create();
Console.WriteLine("文件创建成功");if(aFile.Exists){
Console.WriteLine("Data.txt文件存在");}else{Console.WriteLine("Data.txt文件不存在");}Console.WriteLine("文件当前目录为:"+aFile.Directory);Console.WriteLine("文件大小为:"+aFile.Length);Console.ReadKey();}FileInfo类实例化FileInfo类创建文件判断文件是否存在思考题简述File类和FileInfo类的异同。04Directory类和DirectoryInfo类Directory类Directory类是一个静态类,不可实例化,并且提供了许多静态方法用于对文件的存放目录进行操作,例如创建、删除、查询和移动目录等。Directory类操作文件目录的常用方法如下表所示。属性说明DirectoryInfoCreateDirectory(stringpath)创建指定路径的所有目录和子目录voidDelete(stringpath)删除指定路径的空目录boolExists(stringpath)判断指定路径目录是否存在,若存在,则返回ture,否则,返回false。DirectoryInfoGetParent()查找指定路径的父目录,包括相对路径和绝对路径voidMove(stringsourceDirName,stringdestDirName)将文件或目录及其内容移动到新位置。Directory类Directory类接下来通过一个简单的案例来学习这些方法的使用,具体代码如下所示。staticvoidMain(string[]args){
Directory.CreateDirectory(@"D:\workspace\Chapter09\Program");
if(Directory.Exists(@"D:\workspace\Chapter09\Program")){Console.WriteLine("文件存在");}else{Console.WriteLine("文件不存在");}Directory.Delete(@"D:\workspace\Chapter09\Program");Console.WriteLine("删除成功");Console.ReadKey();}Directory类创建多级目录判断目录是否存在删除没有内容的目录Directoryinfo类DirectoryInfo是一个非静态类,可以进行实例化。该类的功能与Directory类相似,也可以对文件的目录进行创建、删除、查询、移动等操作。实现对目录操作的常见方法与属性如下表所示。属性或方法说明Parent属性,获取指定子目录的父目录Root属性,获取路径的根目录Name属性,获取当前DirectoryInfo对象的名称Exists属性,判断指定目录是否存在Create()方法,创建目录GetDirectories(stringpath)方法,获取当前目录的子目录CreateSubdirectory(stringpath)方法,在指定路径中创建一个或多个子目录GetFiles()方法,获取当前目录的文件列表Delete()方法,删除指定的目录及其内容GetFileSystemInfos()方法,获取当前目录的子目录和文件列表MoveTo(stringdestDirName)方法,将指定目录及其内容移到新位置DirectoryInfo类Directoryinfo类接下来通过一个案例来演示一下这些属性与方法的使用,具体代码如下所示。staticvoidMain(string[]args){stringpath=@"D:\workspace\Chapter09\Program04\bin\Debug\Test";DirectoryInfodi=newDirectoryInfo(path);di.Create();Console.WriteLine("当前目录名称为:"+di.Name);Console.WriteLine("父目录名为:"+di.Parent);Console.WriteLine("根目录为:"+di.Root);stringpath1=@"D:\workspace\Chapter09\Program04\bin\Debug";DirectoryInfodi1=newDirectoryInfo(path1);DirectoryInfo类创建一个DirectoryInfo对象创建目录Directoryinfo类运行结果如右图所示:DirectoryInfo类//遍历目录下的所有文件,并找出包含P字符的文件名FileInfo[]files1=di1.GetFiles("*P*");foreach(variteminfiles1){Console.WriteLine("包含P字符的文件名称为:"+item.Name);}Console.ReadKey();}获取当前目录包含P字符的文件列表思考题简述Directory类和DirectoryInfo类的异同。05Filestream类Filestream类简介FileStream类表示在磁盘或网络路径上指向文件的流,并提供了在文件中读写字节和字节数组的方法,通过这些方法FileStream对象可以读取诸如图像、声音、视频、文本文件等,也就是说FileStream能够处理各种数据文件。FileStream类有很多重载的构造方法,其中最常用的是带有三个参数的构造方法,具体如下:FileStream(stringpath,FileModemode,FileAccessaccess);FileStream类简介Filestream类简介FileStream类还有一些常用的方法,如下表所示。方法说明intReadByte()从文件中读取一个字节,并将读取位置提升一个字节。voidFlush()清除此流的缓冲区,使得所有缓冲的数据都写入到文件中。voidWriteByte(bytevalue)将一个字节写入文件流的当前位置。voidWrite(byte[]array,intoffset,intcount)从缓冲区读取数据将字节块写入该流。intRead(byte[]array,intoffset,intcount)从流中读取字节块并将该数据写入给定缓冲区中。longSeek(longoffset,SeekOriginorigin)将该流的当前位置设置为给定值。FileStream类简介Filestream类读取文件FileStream类除了可以以字节的方式读取文件外,还可以对文件任意位置进行读取,在FileStream类的内部有一个文件指针用于维护文件的位置,该指针指向文件进行下一次读写操作的位置。大多数情况下,当打开文件时,指针就指向文件的开始位置,如果想修改指针的位置可以使用FileStream对象的Seek()方法,示例代码如下:FileStreamaFile=File.OpenRead("Data.txt");aFile.Seek(8,SeekOrigin.Current);FileStream类读取文件Filestream类读取文件为了让学生更好的学习FileStream类,接下来通过一个案例来演示FileStream类对文件的访问操作,具体代码如下所示。staticvoidMain(string[]args){byte[]byteData=newbyte[1024];char[]charData=newchar[1024];using(FileStreamaFile=newFileStream("Data.txt",FileMode.Open)){aFile.Seek(0,SeekOrigin.Begin);aFile.Read(byteData,0,1024);}Decoderd=Encoding.Default.GetDecoder();d.GetChars(byteData,0,byteData.Length,charData,0);Console.WriteLine(charData);//输出解码后的字符串
Console.ReadKey();}}FileStream类读取文件设置当前流的位置从流中读取字节块到byteData数组中将字节数组和内部缓冲区中的字节解码为字符数组Filestream类写入文件接下来通过一个案例来演示FileStream类向文件写入数据,具体代码如下所示。classProgram{staticvoidMain(string[]args){byte[]byteData;//定义一个字节数组
char[]charData;//定义一个字符数组
try{//创建FileStream流对象,并使用using关键字包含执行代码
using(FileStreamaFile=newFileStream("Data.txt",FileMode.Create)){//写一段字符串并使用ToCharArray()方法转换为字符存储到字符数组中
charData="HelloworldbyC#".ToCharArray();byteData=newbyte[charData.Length];......}}catch(IOExceptionex){//处理相关异常
......}......FileStream类写入文件Filestream类写入文件classProgram{staticvoidMain(string[]args){......
try{using(FileStreamaFile=newFileStream("Data.txt",FileMode.Create)){......Encodere=Encoding.Default.GetEncoder();//使用Encoder类将字符数组转换为字节数组e.GetBytes(charData,0,charData.Length,byteData,0,true);aFile.Seek(0,SeekOrigin.Begin);//文件指针指向文件开始位置aFile.Write(byteData,0,byteData.Length);//开始将字节数组中的数据写入文件}}catch(IOExceptionex){//处理相关异常
Console.WriteLine("文件操作异常");Console.WriteLine(ex.ToString());Console.ReadKey();return;}Console.ReadKey();}}FileStream类写入文件实例:复制文件接下来将调用FileStream类的Read()和Write()方法来实现复制一个文件的操作,具体代码如下所示。staticvoidMain(string[]args){stringsource="a.txt";stringtarget="b.txt";
using(FileStreamfsRead=newFileStream(source,FileMode.Open)){using(FileStreamfsWrite=newFileStream(target,FileMode.Create)){byte[]bytes=newbyte[1024];//创建缓冲区
//循环读取文件流
while(true){intr=fsRead.Read(bytes,0,bytes.Length);if(r<=0){break;}fsWrite.Write(bytes,0,bytes.Length);//写入文件
......}实例:复制文件实例:复制文件程序运行成功后,在该项目的根目录中打开a.txt文件和b.txt文件进行对比结果如下图所示。由运行结果可知,a.txt文件内容与b.txt文件内容一致,因此说明文件复制成功了。实例:复制文件思考题简述使用FileStream类进行文件的读写操作。06StreamReader类和StreamWriter类StreamWriter类StreamWriter类用于将字符和字符串写入到文件中,它实际上是先转换为FileStream对象,然后向文件中写入数据,所以在创建对象时可以通过FileStream类的对象来创建StreamWriter类的对象,同时也可以直接创建StreamWriter类对象。当FileStream类的对象存在时,可以通过该对象来创建StreamWriter类的对象,具体代码如下:FileStreamaFile=newFileStream("Data.txt",FileMode.CreateNew);StreamWritersw=newStreamWriter(aFile);StreamWriter类StreamWriter类除了前面的方式以外,还可以通过指定文件来创建StreamWriter类的对象,具体代码如下:StreamWritersw=newStreamWriter("Data.txt");上述代码表示创建一个StreamWriter流对象,并向Data.txt文件中写入数据。如果Data.txt文件不存在,则创建该文件。接下来通过一个案例来学习StreamWriter类的使用方法,具体代码如下所示。StreamWriter类StreamWriter类staticvoidMain(string[]args){try{//创建文件流对象,如果文件不存在则创建Data.txt文件
StreamWritersw=newStreamWriter("Data.txt");
sw.WriteLine(“深圳市信息职业技术学院");sw.Close();//关闭当前流对象
Console.ReadKey();}catch(IOExceptionex){Console.WriteLine("文件操作异常");Console.WriteLine(ex.ToString());return;}}StreamWriter类向文件中写入一段文字StreamWriter类运行结果如下图所示。由上图中的运行结果可知,文件Data.txt中成功写入了一段文字。StreamWriter类StreamWriter类接下来通过一个案例来学习如何使用StreamWriter类的对象对文件进行追加内容的操作,具体代码如下所示。try{//对Program09项目中的Data.txt进行追加操作
stringpath=@"D:\workspace\Chapter09\Program09\bin\Debug\Data.txt";StreamWritersw=newStreamWriter(path,true);sw.WriteLine("网址:");
sw.Close();//关闭当前流对象Console.ReadKey();}catch(IOExceptionex){Console.WriteLine("文件操作异常");Console.WriteLine(ex.ToString());return;}StreamWriter类向文件中追加一段文字StreamWriter类程序执行成功之后,打开Program09项目根目录下的Data.txt文件,该文件中的最初内容与追加内容后的对比如下图所示。由上图中的运行结果可知,文件Data.txt中的内容已经追加了“网址:”。StreamWriter类Streamreader类当FileStream类的对象存在时,可以通过该对象来创建StreamReader类的对象,具体代码如下:FileStreamaFile=newFileStream("Data.txt",FileMode.Open);StreamReadersr=newStreamReader(aFile);StreamReader类与StreamWriter类一样,可以通过具体文件路径的字符串来创建StreamReader类的对象,具体代码如下:StreamReadersr=newStreamReader("Data.txt");StreamReader类Streamreader类接下来通过一个案例来演示StreamReader类的用法,将Program09项目的根目录下的Data.txt文件拷贝到该程序的根目录下,具体代码如下所示。stringline;stringpath=@"D:\workspace\Chapter09\Program10\bin\Debug\Data.txt";try{
FileStreamaFile=newFileStream(path,FileMode.Open);StreamReadersr=newStreamReader(aFile);
line=sr.ReadLine();
while(line!=null){
Console.WriteLine(line);line=sr.ReadLine();}sr.Close();
}......StreamReader类打开路径为path的文件创建读取流对象读取文件中的第一行如果文件不为空,则继续读取文件并输出至控制台当文件读取完毕后,关闭当前流对象Streamreader类运行结果如下图所示。需要注意的是,程序在运行过程中可能会出现异常,因此使用try…catch语句来捕获异常,并将异常的类型设置为IOException,说明捕获的是文件操作中的异常。StreamReader类实例:读写文件接下来通过一个文件读写的案例来学习StreamReader类和StreamWriter类的使用,具体代码如下所示。StreamWritersw=newStreamWriter("Data.txt",true,Encoding.Default);sw.WriteLine("工业管理软件系统--SMOM");sw.Close();//关闭StreamWriter文件流
StreamReadersr=newStreamReader("Data.txt",Encoding.Default);//逐行读取数据,如果未读取到数据则返回nullwhile((temp=sr.ReadLine())!=null){Console.WriteLine(temp);}sr.Close();//关闭StreamReader文件流
sr.Dispose();//释放StreamReader对象
sw.Dispose();//释放StreamWriter对象
Console.ReadKey();实例:读写文件实例:读写文件运行结果如下图所示。由上图中的运行结果可知,Data.txt文件已读写成功并将文件中的信息输出到控制台。实例:读写文件思考题如何使用StreamReader类和StreamWriter类读取和写入文件?07Path类PATH类C#中提供了Path类(静态类)。Path类中包含了一系列用于对文件路径进行操作的方法,具体如下表所示。方法说明stringCombine(paramsstring[]paths)将字符串或字符串数组组合成一个路径stringGetDirectoryName(stringpath)返回指定路径字符串的目录信息stringGetExtension(stringpath)返回指定路径字符串的扩展名stringGetFileName(stringpath)返回指定路径字符串的文件名和扩展名stringGetFullPath(stringpath)返回指定路径字符串的绝对路径boolHasExtension(stringpath)确定路径是否包括文件扩展名stringGetPathRoot(stringpath)获取指定路径的根目录信息stringGetTempPath()返回当前用户的临时文件夹的路径stringGetTempFileName()创建磁盘上唯一命名的零字节的临时文件并返回该文件的完整路径stringChangeExtension(stringpath,stringextension)更改路径字符串的扩展名Path类PATH类接下来通过具体案例来演示Path类中常用方法的使用,具体代码如下所示。stringpath=@"D:\workspace\Chapter09\Program12\Data.txt";//修改文件的扩展名
stringstr=Path.ChangeExtension(path,"exe");Console.WriteLine("修改文件扩展名后:"+str);stringpath1=Path.Combine(@"E:\4.办公\9.项目\20.教育板块\5.深信息校企合作\工业管理软件系统开发课件\C#基础demo\Chapter09\Program10\bin\Debug\",@"\Data.txt");Console.WriteLine("拼接后的路径:"+path1);
stringpath2=Path.GetDirectoryName(path);Console.WriteLine("返回的目录信息为:"+path2);Path类拼接路径获取文件或文件夹的路径Path类//获取扩展名
stringext=Path.GetExtension(path);Console.WriteLine("获取扩展名为:"+ext);//获取文件名
Console.WriteLine("包含扩展名:"+Path.GetFileName(path));Console.WriteLine("不包含扩展名:"+Path.GetFileNameWithoutExtension(path));//由相对路径获取绝对路径
stringstr1=Path.GetFullPath("Data.txt");Console.WriteLine("全路径名字:"+str1);Console.ReadLine();Path类Path类运行结果如下图所示。Path类08BufferedStream类Bufferedstream类BufferedStream提供了几个常用的操作方法,Read()方法、Write()方法和Flush()方法,具体分析如下:1. Read()方法Read()方法用于读取缓冲区中的数据,具体语法格式如下:2. Write()方法Write()方法用于将字节复制到缓冲流,并在缓冲流内的当前位置继续写入字节,具体语法格式如下:publicoverrideintRead(byte[]array,intoffset,intcount);publicoverrideintWrite(byte[]array,intoffset,intcount);BufferedStream类BufferedStream类3.Flush()方法Flush()方法用于清除当前流中的所有缓冲区,使得所有缓冲的数据都被写入到存储设备中,具体语法格式如下:
publicoverridevoidFlush()接下来通过一个案例来演示将一个文件中的内容写入到另一个文件中。首先在解决方案Chapter09中创建一个项目名为Program13的控制台应用程序,然后在该项目的根目录下分别创建一个Data1.txt文件与Data2.txt文件,在Data1.txt文件中输入“工业管理软件系统--SMOM”,具体代码如下所示。BufferedStream类BufferedStream类staticvoidMain(string[]args){inti;FileStreammyStream1,myStream2;BufferedStreammyBStream1,myBStream2;byte[]myByte=newbyte[1024];//定义字节数组
Console.WriteLine("读写前");Print("Data2.txt");myStream1=File.OpenRead("Data1.txt");
myStream2=File.OpenWrite("Data2.txt");myBStream1=newBufferedStream(myStream1);//实例化缓冲流对象
myBStream2=newBufferedStream(myStream2);//开始读取myBStream1流对象中的内容,返回读取的字节数
i=myBStream1.Read(myByte,0,1024);while(i>0){myBStream2.Write(myByte,0,i);
i=myStream1.Read(myByte,0,1024);}......BufferedStream类以读的方式打开Data1.txt以写的方式打开Data2.txt开始读取myBStream1流对象中的内容,返回读取的字节数向myBStream2流对象中写入内容BufferedStream类staticvoidMain(string[]args){......myBStream2.Flush();
myStream1.Close();myStream2.Close();
Console.WriteLine("读写后");Print("Data2.txt");Console.ReadKey();}//输出文件内容的方法
publicstaticvoidPrint(stringpath){using(StreamReadersr=newStreamReader(path,Encoding.Default)){stringcontent=sr.ReadToEnd();Console.WriteLine("文件{0}内容为:{1}",path,content);}......BufferedStream类清空当前流的缓冲空间关闭当前流对象BufferedStream类运行结果如下图所示。注意:由于缓冲流在内存的缓冲区中直接读取数据,而不是从磁盘中直接
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024离婚双方的共同债权债务处理合同
- 2024苗木种植与园林苗木种植基地规划与建设劳务分包协议3篇
- 2024版活动场地使用合同范本
- 2025年度生态农业园承包合同格式规范4篇
- 2024镍矿国际贸易法律事务咨询服务合同3篇
- 2025年度新能源车辆代理记账与补贴申请合同4篇
- 2025年度文化产业发展总经理聘用协议3篇
- 《蒸汽锅炉维护与管理》课件
- 2025年度个人二手房交易反担保合同规范4篇
- 2025年度博物馆展览馆日常保洁与文物保护合同4篇
- GB/T 31888-2015中小学生校服
- 质量检查考核办法
- 不动产登记实务培训教程课件
- 不锈钢制作合同范本(3篇)
- 云南省普通初中学生成长记录-基本素质发展初一-初三
- 2023年系统性硬化病诊断及诊疗指南
- 外科医师手术技能评分标准
- 《英语教师职业技能训练简明教程》全册配套优质教学课件
- 采购控制程序
- 六年级上册数学简便计算题200题专项练习
- 冀教版八年级上册Unit 1 单词短语句型复习预习单
评论
0/150
提交评论