黑马程序员技术交流社区

标题: 【阳哥笔记】极速秒杀Java基础之笔记系列—Day24( IO )! [打印本页]

作者: 阳哥忠粉    时间: 2015-6-7 22:44
标题: 【阳哥笔记】极速秒杀Java基础之笔记系列—Day24( IO )!


笔记总链接:http://bbs.itheima.com/thread-200600-1-1.html

8、IO

8.2 IO流

    8.2.11  IO包中的其他类

    需求:文件切割器。

    代码:
  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.util.Properties;

  6. public class SplitFileDemo{

  7.        private static final int SIZE = 1024*1024;
  8.       
  9.        public static void main(String[] args) throws IOException{
  10.             File file = new File("0.mp3" );
  11.             splitFile(file);
  12.       }

  13.        public static void splitFile(File file) throws IOException {
  14.              //用读取流关联源文件
  15.             FileInputStream fis = new FileInputStream(file);

  16.              //定义一个1M的缓冲区
  17.              byte[] buf = new byte[SIZE];
  18.       
  19.              //创建目的
  20.             FileOutputStream fos = null;
  21.             
  22.              int len = 0;
  23.              int count = 1;

  24.              //切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数,以方便于合并。
  25.              //这个信息为了进行描述,使用键值对的方式,用到了properties对象。

  26.             Properties prop = new Properties();

  27.             File dir = new File("c:\\partFiles" );
  28.              if(!dir.exists())
  29.                   dir.mkdirs();

  30.              while((len = fis.read(buf)) != -1){
  31.                   fos = new FileOutputStream(new File(dir,(count++) + ".part"));
  32.                   fos.write(buf,0,len);
  33.                   fos.close();
  34.             }
  35.             
  36.              //将被切割文件的信息保存到prop集合中
  37.             prop.setProperty( "partcount",count + "" );
  38.             prop.setProperty( "filename",file.getName());

  39.             fos = new FileOutputStream(new File(dir,count + ".properties" ));
  40.             
  41.              //将prop集合中的数据存储到文件中
  42.             prop.store(fos, "save file info");

  43.             fis.close();
  44.             fos.close();
  45.       }
  46. }
复制代码
   运行结果:






    需求:文件合并器。  

    代码:
  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.FilenameFilter;
  5. import java.io.IOException;
  6. import java.io.SequenceInputStream;
  7. import java.util.ArrayList;
  8. import java.util.Collections;
  9. import java.util.Enumeration;
  10. import java.util.Iterator;
  11. import java.util.Properties;

  12. public class MergeFile{
  13.        public static void main(String[] args) throws IOException {
  14.             File dir = new File("c:\\partFiles" );
  15.             mergeFile(dir);
  16.       }

  17.        public static void mergeFile(File dir) throws IOException {

  18.              //获取指定目录下的配置文件对象
  19.             File[] files = dir.listFiles( new SuffixFilter(".properties" ));
  20.             
  21.              if(files.length!=1)
  22.                    throw new RuntimeException(dir + ",该目录下没有properties扩展名的文件或者不唯一" );
  23.             
  24.              //记录配置文件对象
  25.             File confile = files[0];

  26.              //获取该文件中的信息
  27.             Properties prop = new Properties();
  28.             FileInputStream fis = new FileInputStream(confile);

  29.             prop.load(fis);

  30.             String filename = prop.getProperty( "filename");

  31.              int count = Integer.parseInt(prop.getProperty("partcount"));
  32.             
  33.              //获取该目录下的所有碎片文件
  34.             File[] partFiles = dir.listFiles( new SuffixFilter(".part" ));

  35.              if(partFiles.length != (count - 1)){
  36.                    throw new RuntimeException("碎片文件不符合要求,个数不对!应该是" + count + "个");
  37.             }
  38.             
  39.              //将碎片文件和流对象关联并存储到集合中
  40.             ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();

  41.              for(int x = 1; x <= partFiles.length; x++){
  42.                   al.add( new FileInputStream(partFiles[x-1]));
  43.             }

  44.              final Iterator<FileInputStream> it = al.iterator();
  45.             
  46.              //将多个流合并成一个序列流
  47.             Enumeration<FileInputStream> en = Collections.enumeration(al);

  48.             SequenceInputStream sis = new SequenceInputStream(en);

  49.             FileOutputStream fos = new FileOutputStream(new File(dir,filename));

  50.              byte[] buf = new byte[1024*1024];
  51.             
  52.              int len = 0;

  53.              while((len = sis.read(buf)) != -1){
  54.                   fos.write(buf,0,len);   
  55.             }

  56.             fos.close();
  57.             sis.close();
  58.       }
  59. }

  60. class SuffixFilter implements FilenameFilter{
  61.        private String suffix;

  62.        public SuffixFilter(String suffix){
  63.              super();
  64.              this.suffix = suffix;
  65.       }

  66.        public boolean accept(File dir,String name){
  67.              return name.endsWith(suffix);
  68.       }
  69. }
复制代码
    运行结果:




    操作对象
    ObjectInputStream与ObjectOutputStream


    P.S.
    被操作的对象需要实现Serializable。

    类通过实现java.io.Serializable接口以启用序列化功能,Serializable只是一个标记接口。

    示例1:
  1. import java.io.Serializable;

  2. class Person implements Serializable{
  3.        private String name;
  4.        private int age;

  5.        public Person(String name,int age){
  6.              this.name = name;
  7.              this.age = age;
  8.       }

  9.        public String getName(){
  10.              return name;
  11.       }

  12.        public void setName(String name){
  13.              this.name = name;
  14.       }

  15.        public int getAge(){
  16.              return age;
  17.       }

  18.        public void setAge(int age){
  19.              this.age = age;
  20.       }
  21. }
复制代码
    运行结果:



    示例2:
  1. import java.io.FileInputStream;
  2. import java.io.ObjectInputStream;

  3. public class ObjectStreamDemo{
  4.        public static void main(String[] args) throws Exception {
  5.             readObj();
  6.       }

  7.        public static void readObj() throws Exception {
  8.             ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object" ));
  9.             
  10.             Person p = (Person)ois.readObject();

  11.             System.out.println(p.getName() + ":" + p.getAge());

  12.             ois.close();
  13.       }
  14. }
复制代码
   运行结果:

    如果修改Person类中属性的修饰符为public,就会报如下异常。


   

    原因分析:

    Serializable:用于给被序列化的类加入ID号,用于判断类和对象是否是同一个版本。
    API解释如下:


    为Person类添加序列号属性。此时,再将Person类中属性修饰符修改为public,也不会出现任何异常。
  1. class Person implements Serializable{
  2.        private static final long serialVersionUID = 9527;

  3.        public String name ;
  4.        public int age ;

  5.        public Person(String name,int age){
  6.              this.name = name;
  7.              this.age = age;
  8.       }

  9.        public String getName(){
  10.              return name ;
  11.       }

  12.        public void setName(String name){
  13.              this.name = name;
  14.       }

  15.        public int getAge(){
  16.              return age ;
  17.       }

  18.        public void setAge(int age){
  19.              this.age = age;
  20.       }
  21. }
复制代码

    writeObject方法不能写入类及其所有超类型的瞬态和静态字段的值。

    示例3:  
  1. import java.io.Serializable;

  2. class Person implements Serializable{
  3.        private static final long serialVersionUID = 9527;

  4.        private transient String name;
  5.        private static int age;

  6.        public Person(String name,int age){
  7.              this.name = name;
  8.              this.age = age;
  9.       }

  10.        public String getName(){
  11.              return name;
  12.       }

  13.        public void setName(String name){
  14.              this.name = name;
  15.       }

  16.        public int getAge(){
  17.              return age;
  18.       }

  19.        public void setAge(int age){
  20.              this.age = age;
  21.       }
  22. }
复制代码
    运行结果:

    RandomAccessFile

    随机访问文件,自身具备读写的方法。
    通过skipBytes(int x),seek(int x)等方法来达到随机访问。

    特点:
    1. 该对象即能读,又能写。
    2. 该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素。
    3. 可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置。
    4. 其实该对象就是将字节输入流和输出流进行了封装。
    5. 该对象的源或者目的只能是文件。通过构造函数就可以看出。


    P.S.
    RandomAccessFile不是io体系中的子类。

    示例1:
  1. import java.io.IOException;
  2. import java.io.RandomAccessFile;

  3. public class RandomAccessFileDemo{
  4.        public static void main(String[] args) throws IOException {
  5.             writeFile();
  6.       }

  7.        //使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄
  8.        public static void writeFile() throws IOException {
  9.              //如果文件不存在,则创建,如果文件存在,不创建
  10.             RandomAccessFile raf = new RandomAccessFile("ranacc.txt" ,"rw" );
  11.             
  12.             raf.write( "张三".getBytes());
  13.              //使用write方法之写入最后一个字节
  14.             raf.write(97);
  15.              //使用writeInt方法写入四个字节(int类型)
  16.             raf.writeInt(97);
  17.             
  18.             raf.write( "小强".getBytes());
  19.             raf.writeInt(99);

  20.             raf.close();
  21.       }
  22. }
复制代码
    运行结果:



    示例2:  
  1. import java.io.IOException;
  2. import java.io.RandomAccessFile;

  3. public class RandomAccessFileDemo{
  4.        public static void main(String[] args) throws IOException {
  5.             readFile();
  6.       }

  7.        public static void readFile() throws IOException {
  8.             RandomAccessFile raf = new RandomAccessFile("ranacc.txt" ,"r" );
  9.             
  10.              //通过seek设置指针的位置
  11.             raf.seek(9); //随机的读取,只要指定指针的位置即可

  12.              byte[] buf = new byte[4];           
  13.             raf.read(buf);

  14.             String name = new String(buf);
  15.             System.out.println( "name=" + name);

  16.              int age = raf.readInt();
  17.             System.out.println( "age=" + age);

  18.             System.out.println( "pos:" + raf.getFilePointer());

  19.             raf.close();
  20.       }
  21. }
复制代码
    运行结果:

    示例3:  
  1. import java.io.IOException;
  2. import java.io.RandomAccessFile;

  3. public class RandomAccessFileDemo{
  4.        public static void main(String[] args) throws IOException {
  5.             randomWrite();
  6.       }

  7.        public static void randomWrite() throws IOException {
  8.             RandomAccessFile raf = new RandomAccessFile("ranacc.txt" ,"rw" );
  9.             
  10.              //往指定位置写入数据
  11.             raf.seek(3*8);
  12.             
  13.             raf.write( "哈哈".getBytes());
  14.             raf.writeInt(102);

  15.             raf.close();
  16.       }
  17. }
复制代码
     运行结果:



    管道流
    PipedInputStream和PipedOutputStream:输入输出可以直接进行连接,通过结合线程使用。


    示例1:
  1. import java.io.PipedInputStream;
  2. import java.io.PipedOutputStream;

  3. public class PipedStream{
  4.        public static void main(String[] args) throws Exception {
  5.             PipedInputStream input = new PipedInputStream();
  6.             PipedOutputStream output = new PipedOutputStream();

  7.             input.connect(output);

  8.              new Thread(new Input(input)).start();
  9.              new Thread(new Output(output)).start();
  10.       }
  11. }

  12. class Input implements Runnable{
  13.        private PipedInputStream in;
  14.       
  15.       Input(PipedInputStream in){
  16.              this.in = in;
  17.       }

  18.        public void run(){
  19.              try{
  20.                    byte[] buf = new byte[1024];
  21.                    int len = in.read(buf);

  22.                   String s = new String(buf,0,len);
  23.                   System.out.println( "s=" + s);
  24.                   in.close();
  25.             } catch(Exception e){
  26.                   e.printStackTrace();
  27.             }
  28.       }
  29. }

  30. class Output implements Runnable{
  31.        private PipedOutputStream out;
  32.       
  33.       Output(PipedOutputStream out){
  34.              this.out = out;
  35.       }

  36.        public void run(){
  37.              try{
  38.                   out.write( "hi,管道来了!" .getBytes());
  39.                   out.close();
  40.             } catch(Exception e){
  41.                   e.printStackTrace();
  42.             }
  43.       }
  44. }
复制代码
   运行结果:


    操作基本数据类型
    DataInputStream与DataOutputStream

    示例1:
  1. import java.io.DataOutputStream;
  2. import java.io.FileOutputStream;
  3. import java.io.IOException;

  4. public class DataStreamDemo{
  5.        public static void main(String[] args) throws IOException {
  6.             writeData();
  7.       }

  8.        public static void writeData() throws IOException {
  9.             DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt" ));
  10.       
  11.             dos.writeUTF( "您好");

  12.             dos.close();
  13.       }
  14. }
复制代码
   运行结果:





    示例2:
  1. import java.io.DataInputStream;
  2. import java.io.FileInputStream;
  3. import java.io.IOException;

  4. public class DataStreamDemo{
  5.        public static void main(String[] args) throws IOException {
  6.             readData();
  7.       }

  8.        public static void readData() throws IOException {
  9.             DataInputStream dis = new DataInputStream(new FileInputStream("data.txt" ));
  10.       
  11.             String str = dis.readUTF();
  12.             
  13.             System.out.println(str);

  14.             dis.close();
  15.       }
  16. }
复制代码
    运行结果:

    操作字节数组
    ByteArrayInputStream与ByteArrayOutputStream


    P.S.
    关闭字节数组输出输出流无效,因为它们没有调用底层资源,所有的操作都是在内存中完成的。

    示例1:
  1. import java.io.ByteArrayInputStream;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.IOException;

  4. public class ByteArrayStreamDemo{
  5.        public static void main(String[] args) throws IOException {
  6.             ByteArrayInputStream bis = new ByteArrayInputStream("abcdef" .getBytes());
  7.             ByteArrayOutputStream bos = new ByteArrayOutputStream();

  8.              int ch = 0;

  9.              while((ch = bis.read()) != -1){
  10.                   bos.write(ch);
  11.             }

  12.             System.out.println(bos.toString());
  13.       }
  14. }
复制代码
   运行结果:

    8.2.12  编码表

    编码表的由来
    计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。
    就将各个国家的文字用数字来表示,并一一对应,形成一张表,这就是编码表。

    常见的编码表
    ASCII:美国标准信息交换码,用一个字节的7位可以表示。
    ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示。
    GB2312:中国的中文编码表。
    GBK:中国的中文编码表升级,融合了更多的中文文字符号。
    Unicode:国际标准码,融合了多种文字。
    所有文字都用两个字节来表示,Java语言使用的就是unicode
    UTF-8:最多用三个字节来表示一个字符。
    ......

    示例1:
  1. import java.io.IOException;

  2. public class EncodeDemo{
  3.        public static void main(String[] args) throws IOException{
  4.              //字符串-->字节数组:编码
  5.              //字符数组-->字符串:解码
  6.             String str = "您好";

  7.              //编码
  8.              byte[] buf1 = str.getBytes("GBK" );
  9.             printBytes(buf1);

  10.              byte[] buf2 = str.getBytes("UTF-8" );
  11.             printBytes(buf2);

  12.              //解码
  13.             String s1 = new String(buf1);
  14.             System.out.println( "s1 = " + s1);

  15.             String s2 = new String(buf2,"UTF-8" );
  16.             System.out.println( "s2 = " + s2);
  17.       }

  18.        private static void printBytes(byte[] buf){
  19.              for(byte b : buf){
  20.                   System.out.print(b + " ");
  21.             }
  22.             System.out.println();
  23.       }
  24. }
复制代码
    运行结果:


    如果编码编错了,解不出来。
    如果编对了,解错了,有可能有救。

    示例2:
  1. import java.io.IOException;

  2. public class EncodeDemo{
  3.        public static void main(String[] args) throws IOException{
  4.             String str = "您好";
  5.             
  6.              byte[] buf = str.getBytes("gbk" );

  7.             String s1 = new String(buf,"iso8859-1" );

  8.             System.out.println( "s1 = " + s1);

  9.              byte[] buf2 = s1.getBytes("iso8859-1" );
  10.             String s2 = new String(buf2,"gbk" );

  11.             System.out.println(s2);
  12.       }

  13.        private static void printBytes(byte[] buf){
  14.              for(byte b : buf){
  15.                   System.out.println(b);
  16.             }
  17.       }
  18. }
复制代码
   运行结果:

    如果编对了,解错了,也可能没救了。

    示例3:
  1. import java.io.IOException;

  2. public class EncodeDemo{
  3.        public static void main(String[] args) throws IOException{
  4.             String str = "您好";
  5.             
  6.              byte[] buf = str.getBytes("gbk" );

  7.             String s1 = new String(buf,"UTF-8" );

  8.             System.out.println( "s1 = " + s1);

  9.              byte[] buf2 = s1.getBytes("UTF-8" );
  10.             
  11.             printBytes(buf2);

  12.             String s2 = new String(buf2,"gbk" );

  13.             System.out.println(s2);
  14.       }

  15.        private static void printBytes(byte[] buf){
  16.              for(byte b : buf){
  17.                   System.out.print(b + " ");
  18.             }
  19.             System.out.println();
  20.       }
  21. }
复制代码
    运行结果:

    原因分析:
    “您好”的gbk编码在UTF-8码表中查不到对应的字符,所以已经用“?”代替。
    “?”在UTF-8中的编码为-17 -65 -67
    故即使使用UTF-8码表进行解码,获取的字节也不是“您好”的gbk编码后的字节。
    所以再也不能成功解码了。

    P.S.
    “谢谢”的gbk编码在UTF-8码表中可以查到对应的字符,为“ππ”。
    因此,使用UTF-8码表对“ππ”进行解码,获取的字节也依然是“您好”的gbk编码后的字节。
    所以,不会出现“您好”发生的情况。

    实验:联通乱码问题。

    步骤:
    1. 新建一个1.txt文件。


    2. 输入联通,保存。


    3. 关闭,重新打开此文件,发现乱码。


    原因分析:
    “联通”经过gbk编码后成四个字节:11000001、10101010、11001101、10101000。
    正好符合UTF-8的编码规则。所以,记事本按照UTF-8进行了解码,从而出现了乱码现象。

    练习:
    在java中,字符串“abcd”与字符串“ab您好”的长度是一样,都是四个字符。
    但对应的字节数不同,一个汉字占两个字节。
    定义一个方法,按照最大的字节数来取子串。
    如:对于“ab你好”,如果取三个字节,那么子串就是ab与“你”字的半个。
    那么半个就要舍弃。如果取四个字节就是“ab你”,取五个字节还是“ab你”。

    代码:
  1. import java.io.IOException;

  2. public class Test{
  3.        public static void main(String[] args) throws IOException {
  4.             String str = "ab你好cd谢谢" ;

  5.              int len = str.getBytes("gbk" ).length;

  6.              for(int x = 1; x < len; x++){
  7.                   System.out.println( "截取的" + (x + 1) + "个节结果是:" + cutStringByByte(str,x+1));
  8.             }
  9.       }

  10.        public static String cutStringByByte(String str,int len) throws IOException {
  11.              byte[] buf = str.getBytes("gbk" );

  12.              int count = 0;
  13.              for(int x = len - 1; x >= 0; x--){
  14.                    //gbk编码的值两个字节值一般都为负,记录连续的负数个数,如果为奇数,则舍弃
  15.                    if(buf[x] < 0)
  16.                         count++;
  17.                    else
  18.                          break;
  19.             }

  20.              if(count % 2 == 0){
  21.                    return new String(buf,0,len,"gbk");
  22.             } else{
  23.                    return new String(buf,0,len-1,"gbk");
  24.             }
  25.       }
  26. }
复制代码
   运行结果:

    P.S.
    中文经过gbk编码后,也有两个字节不都为负数的情况,例如“琲”,字节值为-84、105。
    第一个字节值为负,第二个字节值为正。因此,上面的代码得出的结果依然正确。

    定义一个方法,按照最大的字节数来取子串,使用UTF-8编码的代码如下:

    代码:
  1. public class Test{
  2.        public static void main(String[] args) throws Exception {
  3.             String str = "ab你好cd谢谢" ;

  4.              int len = str.getBytes("utf-8" ).length;

  5.              for(int x = 1; x < len; x++){
  6.                   System.out.println( "截取的" + (x + 1) + "个节结果是:" + cutStringByByte(str,x+1));
  7.             }
  8.       }

  9.        public static String cutStringByByte(String str,int len) throws Exception {
  10.              byte[] buf = str.getBytes("utf-8" );

  11.              int count = 0;
  12.              for(int x = len - 1; x >= 0; x--){
  13.                    if(buf[x] < 0)
  14.                         count++;
  15.                    else
  16.                          break;
  17.             }

  18.              if(count % 3 == 0)
  19.                    return new String(buf,0,len,"utf-8");
  20.              else if (count % 3 == 1)
  21.                    return new String(buf,0,len-1,"utf-8");
  22.              else
  23.                    return new String(buf,0,len-2,"utf-8");
  24.       }
  25. }
复制代码
    运行结果:
   

~END~





作者: itheima_llt    时间: 2015-6-7 22:57
好快啊!顶一下!
作者: 灵界    时间: 2015-6-7 22:59
更新好快,支持
作者: cyd1058    时间: 2015-6-8 21:18
给力!!!!!!!!
作者: cyd1058    时间: 2015-6-8 21:20
更新很快!很赞!
作者: SouthKai    时间: 2015-6-8 21:55
阳哥给力啊,这么快!
作者: 流水0215    时间: 2015-6-9 09:21
阳哥辛苦了
作者: 新缘    时间: 2015-6-9 18:30
赞一个。
作者: 熊乾坤    时间: 2015-6-9 22:17
赞!赞!赞!赞!赞!赞!
作者: cyd1058    时间: 2015-6-9 22:46
更新很快!!辛苦了
作者: 魏海洲    时间: 2015-6-11 19:10
阳哥给力啊,这么快
作者: richaled    时间: 2015-6-13 10:07
给力,更新的很快
作者: libin159028    时间: 2015-6-15 00:14
z赞  好详细
作者: 魏海洲    时间: 2015-6-16 21:15

好快啊!顶一下!
作者: wenweishan2015    时间: 2015-6-17 01:08
赞一个!!!
作者: 新缘    时间: 2015-6-18 19:33
:):):):):):)
作者: 魏海洲    时间: 2015-6-22 21:33

好快啊!顶一下!
作者: 绝版坏银    时间: 2015-6-25 16:27
今天的好难记啊。- -。回想一遍朦朦胧胧,貌似什么都没记住
作者: wanghua1    时间: 2015-7-8 00:13
点个赞!!!
作者: 星痕-凌    时间: 2015-7-12 17:25
阳哥,太牛,好赞 !!!!!!!!!!!!!!!!赞
作者: 星痕-凌    时间: 2015-7-14 22:00
笔记比较仔细,很不错!!!!!!!!!!!!!!!!!!
作者: 星痕-凌    时间: 2015-7-16 22:07
还没学到,先下载下来,学到看!!!!!!!!!
作者: 星痕-凌    时间: 2015-7-18 21:04
很不错,努力学好!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: xyxlx111    时间: 2015-7-18 23:58
写的不错,顶一个
作者: heima_cy    时间: 2015-8-14 17:00
已经自学一个月了  感谢分享
作者: qq100511544    时间: 2015-8-18 00:39

作者: 七了个七    时间: 2015-8-18 09:10
赞赞赞呀
作者: pengbeilin    时间: 2015-8-18 11:36
斯国一~
作者: 风华正茂    时间: 2015-8-18 12:14
谢谢阳哥分享
作者: 漠陌    时间: 2015-8-18 12:43
感谢分享
作者: qq100511544    时间: 2015-8-22 09:28
马上学到 IO 流了~~貌似有点难啊~@@
作者: qq100511544    时间: 2015-8-23 00:17
阳哥威武!!
作者: chensheng06    时间: 2015-8-23 07:05
好贴   帮助查漏补缺
作者: a1ccwt    时间: 2015-8-23 08:13
写的好专业
作者: koibiki    时间: 2015-8-23 11:02
总结得很好
作者: Yan_Theo    时间: 2015-10-2 01:11
欢天喜地来盖楼。
作者: chenwt2015    时间: 2015-10-2 01:54
阳哥你真帅!
作者: Yan_Theo    时间: 2015-10-2 13:19
继续加油
作者: Smilexs    时间: 2015-10-3 10:58
学习了学习了。
作者: 如梦丶似幻    时间: 2015-10-3 22:16
前来学习~~~~~
作者: 101350    时间: 2015-10-21 19:31

作者: 爨oooo    时间: 2015-10-21 22:02
看不懂....
作者: 爨oooo    时间: 2015-10-21 22:59
顶一下~~留着以后看
作者: yqlbd    时间: 2015-11-21 22:26
先顶再看,谢谢。
作者: lktz    时间: 2016-2-16 01:39
标记一下
作者: 一真    时间: 2016-2-17 22:47
辛苦了,谢谢啦
作者: 13120298870    时间: 2016-5-13 23:17
阳哥!!!!!!!!!!
有没有mysql的讲解内容?????、
求MySQL 知识点。。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2