国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

JavaIO之FileInputStream&FileOutputStream源碼分析

2019-11-14 15:29:22
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
io java FileInputStream FileOutputStream

 

目錄[-]

  • 一、引子
  • 二、FileInputStream源碼分析
  • 三、FileOutputStream 源碼分析
  • 四、使用案例
  • 五、思考與小結(jié)

Writer      :BYSocket(泥沙磚瓦漿木匠)

微         博:BYSocket

豆         瓣:BYSocket

FaceBook:BYSocket

Twitter    :BYSocket

一、引子

文件,作為常見(jiàn)的數(shù)據(jù)源。關(guān)于操作文件的字節(jié)流就是 — FileInputStream & FileOutputStream。它們是Basic IO字節(jié)流中重要的實(shí)現(xiàn)類。

二、FileInputStream源碼分析

FileInputStream源碼如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/**
 * FileInputStream 從文件系統(tǒng)的文件中獲取輸入字節(jié)流。文件取決于主機(jī)系統(tǒng)。
 *  比如讀取圖片等的原始字節(jié)流。如果讀取字符流,考慮使用 FiLeReader。
 */
publicclassSFileInputStream extendsInputStream
{
    /* 文件描述符類---此處用于打開(kāi)文件的句柄 */
    PRivate final FileDescriptor fd;
  
    /* 引用文件的路徑 */
    private final String path;
  
    /* 文件通道,NIO部分 */
    private FileChannel channel = null;
  
    private final Object closeLock = new Object();
    private volatile boolean closed = false;
  
    private static final ThreadLocal<Boolean> runningFinalize =
        new ThreadLocal<>();
  
    private static boolean isRunningFinalize() {
        Boolean val;
        if ((val = runningFinalize.get()) != null)
            return val.booleanValue();
        return false;
    }
  
    /* 通過(guò)文件路徑名來(lái)創(chuàng)建FileInputStream */
    public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }
  
    /* 通過(guò)文件來(lái)創(chuàng)建FileInputStream */
    public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        fd = new FileDescriptor();
        fd.incrementAndGetUseCount();
        this.path = name;
        open(name);
    }
  
    /* 通過(guò)文件描述符類來(lái)創(chuàng)建FileInputStream */
    public FileInputStream(FileDescriptor fdObj) {
        SecurityManager security = System.getSecurityManager();
        if (fdObj == null) {
            throw new NullPointerException();
        }
        if (security != null) {
            security.checkRead(fdObj);
        }
        fd = fdObj;
        path = null;
        fd.incrementAndGetUseCount();
    }
  
    /* 打開(kāi)文件,為了下一步讀取文件內(nèi)容。native方法 */
    private native void open(String name) throws FileNotFoundException;
  
    /* 從此輸入流中讀取一個(gè)數(shù)據(jù)字節(jié) */
    public int read() throws IOException {
        Object traceContext = IoTrace.fileReadBegin(path);
        int b = 0;
        try {
            b = read0();
        } finally {
            IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
        }
        return b;
    }
  
    /* 從此輸入流中讀取一個(gè)數(shù)據(jù)字節(jié)。native方法 */
    private native int read0() throws IOException;
  
    /* 從此輸入流中讀取多個(gè)字節(jié)到byte數(shù)組中。native方法 */
    private native int readBytes(byte b[], int off, int len) throws IOException;
  
    /* 從此輸入流中讀取多個(gè)字節(jié)到byte數(shù)組中。 */
    public int read(byte b[]) throws IOException {
        Object traceContext = IoTrace.fileReadBegin(path);
        int bytesRead = 0;
        try {
            bytesRead = readBytes(b, 0, b.length);
        } finally {
            IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
        }
        return bytesRead;
    }
  
    /* 從此輸入流中讀取最多l(xiāng)en個(gè)字節(jié)到byte數(shù)組中。 */
    public int read(byte b[], int off, int len) throws IOException {
        Object traceContext = IoTrace.fileReadBegin(path);
        int bytesRead = 0;
        try {
            bytesRead = readBytes(b, off, len);
        } finally {
            IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
        }
        return bytesRead;
    }
  
      
    public native long skip(long n) throws IOException;
  
    /* 返回下一次對(duì)此輸入流調(diào)用的方法可以不受阻塞地從此輸入流讀?。ɑ蛱^(guò))的估計(jì)剩余字節(jié)數(shù)。 */
    public native int available() throws IOException;
  
    /* 關(guān)閉此文件輸入流并釋放與此流有關(guān)的所有系統(tǒng)資源。 */
    public void close() throws IOException {
        synchronized (closeLock) {
            if (closed) {
                return;
            }
            closed = true;
        }
        if (channel != null) {
           fd.decrementAndGetUseCount();
           channel.close();
        }
  
        int useCount = fd.decrementAndGetUseCount();
  
        if ((useCount <= 0) || !isRunningFinalize()) {
            close0();
        }
    }
  
    public final FileDescriptor getFD() throws IOException {
        if (fd != null) return fd;
        throw new IOException();
    }
  
    /* 獲取此文件輸入流的唯一FileChannel對(duì)象 */
    publicFileChannel getChannel() {
        synchronized(this) {
            if(channel == null) {
                channel = FileChannelImpl.open(fd, path, true, false, this);
                fd.incrementAndGetUseCount();
            }
            returnchannel;
        }
    }
  
    privatestaticnativevoidinitIDs();
  
    privatenativevoidclose0() throwsIOException;
  
    static{
        initIDs();
    }
  
    protected void finalize() throws IOException {
        if((fd != null) &&  (fd != FileDescriptor.in)) {
            runningFinalize.set(Boolean.TRUE);
            try{
                close();
            } finally{
                runningFinalize.set(Boolean.FALSE);
            }
        }
    }
}

1. 三個(gè)核心方法

三個(gè)核心方法,也就是Override(重寫(xiě))了抽象類InputStreamread方法。

int read() 方法,即

 

?
1
public int read() throws IOException

代碼實(shí)現(xiàn)中很簡(jiǎn)單,一個(gè)try中調(diào)用本地nativeread0()方法,直接從文件輸入流中讀取一個(gè)字節(jié)。IoTrace.fileReadEnd(),字面意思是防止文件沒(méi)有關(guān)閉讀的通道,導(dǎo)致讀文件失敗,一直開(kāi)著讀的通道,會(huì)造成內(nèi)存泄露。

 

int read(byte b[]) 方法,即

 

?
1
public int read(byte b[]) throws IOException

代碼實(shí)現(xiàn)也是比較簡(jiǎn)單的,也是一個(gè)try中調(diào)用本地nativereadBytes()方法,直接從文件輸入流中讀取最多b.length個(gè)字節(jié)到byte數(shù)組b中。

int read(byte b[], int off, int len) 方法,即

 

?
1
public int read(byte b[], int off, int len) throws IOException

代碼實(shí)現(xiàn)和 int read(byte b[])方法 一樣,直接從文件輸入流中讀取最多l(xiāng)en個(gè)字節(jié)到byte數(shù)組b中。

可是這里有個(gè)問(wèn):

Q: 為什么 int read(byte b[]) 方法需要自己獨(dú)立實(shí)現(xiàn)呢? 直接調(diào)用 int read(byte b[], int off, int len) 方法,即read(b , 0 , b.length),等價(jià)于read(b)?

A:待完善,希望路過(guò)大神回。。。。向下兼容?? Finally??

2. 值得一提的native方法

上面核心方法中為什么實(shí)現(xiàn)簡(jiǎn)單,因?yàn)楣ぷ髁慷荚?strong>native方法里面,即JVM里面實(shí)現(xiàn)了。native倒是不少一一列舉吧:

native void open(String name) // 打開(kāi)文件,為了下一步讀取文件內(nèi)容

native int read0() // 從文件輸入流中讀取一個(gè)字節(jié)

native int readBytes(byte b[], int off, int len) // 從文件輸入流中讀取,從off句柄開(kāi)始的len個(gè)字節(jié),并存儲(chǔ)至b字節(jié)數(shù)組內(nèi)。

native void close0() // 關(guān)閉該文件輸入流及涉及的資源,比如說(shuō)如果該文件輸入流的FileChannel對(duì)被獲取后,需要對(duì)FileChannel進(jìn)行close。

其他還有值得一提的就是,在jdk1.4中,新增了NIO包,優(yōu)化了一些IO處理的速度,所以在FileInputStream和FileOutputStream中新增了FileChannel getChannel()的方法。即獲取與該文件輸入流相關(guān)的 java.nio.channels.FileChannel對(duì)象。

 

三、FileOutputStream 源碼分析

FileOutputStream 源碼如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/**
 * 文件輸入流是用于將數(shù)據(jù)寫(xiě)入文件或者文件描述符類
 *  比如寫(xiě)入圖片等的原始字節(jié)流。如果寫(xiě)入字符流,考慮使用 FiLeWriter。
 */
publicclassSFileOutputStream extendsOutputStream
{
    /* 文件描述符類---此處用于打開(kāi)文件的句柄 */
    private final FileDescriptor fd;
  
    /* 引用文件的路徑 */
    private final String path;
  
    /* 如果為 true,則將字節(jié)寫(xiě)入文件末尾處,而不是寫(xiě)入文件開(kāi)始處 */
    private final boolean append;
  
    /* 關(guān)聯(lián)的FileChannel類,懶加載 */
    private FileChannel channel;
  
    private final Object closeLock = new Object();
    private volatile boolean closed = false;
    private static final ThreadLocal<Boolean> runningFinalize =
        new ThreadLocal<>();
  
    private static boolean isRunningFinalize() {
        Boolean val;
        if ((val = runningFinalize.get()) != null)
            return val.booleanValue();
        return false;
    }
  
    /* 通過(guò)文件名創(chuàng)建文件輸入流 */
    public FileOutputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null, false);
    }
  
    /* 通過(guò)文件名創(chuàng)建文件輸入流,并確定文件寫(xiě)入起始處模式 */
    public FileOutputStream(String name, boolean append)
        throws FileNotFoundException
    {
        this(name != null ? new File(name) : null, append);
    }
  
    /* 通過(guò)文件創(chuàng)建文件輸入流,默認(rèn)寫(xiě)入文件的開(kāi)始處 */
    public FileOutputStream(File file) throws FileNotFoundException {
        this(file, false);
    }
  
    /* 通過(guò)文件創(chuàng)建文件輸入流,并確定文件寫(xiě)入起始處  */
    public FileOutputStream(File file, boolean append)
        throws FileNotFoundException
    {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        this.fd = new FileDescriptor();
        this.append = append;
        this.path = name;
        fd.incrementAndGetUseCount();
        open(name, append);
    }
  
    /* 通過(guò)文件描述符類創(chuàng)建文件輸入流 */
    public FileOutputStream(FileDescriptor fdObj) {
        SecurityManager security = System.getSecurityManager();
        if (fdObj == null) {
            throw new NullPointerException();
        }
        if (security != null) {
            security.checkWrite(fdObj);
        }
        this.fd = fdObj;
        this.path = null;
        this.append = false;
  
        fd.incrementAndGetUseCount();
    }
  
    /* 打開(kāi)文件,并確定文件寫(xiě)入起始處模式 */
    private native void open(String name, boolean append)
        throws FileNotFoundException;
  
    /* 將指定的字節(jié)b寫(xiě)入到該文件輸入流,并指定文件寫(xiě)入起始處模式 */
    private native void write(int b, boolean append) throws IOException;
  
    /* 將指定的字節(jié)b寫(xiě)入到該文件輸入流 */
    public void write(int b) throws IOException {
        Object traceContext = IoTrace.fileWriteBegin(path);
        int bytesWritten = 0;
        try {
            write(b, append);
            bytesWritten = 1;
        } finally {
            IoTrace.fileWriteEnd(traceContext, bytesWritten);
        }
    }
  
    /* 將指定的字節(jié)數(shù)組寫(xiě)入該文件輸入流,并指定文件寫(xiě)入起始處模式 */
    private native void writeBytes(byte b[], int off, int len, boolean append)
        throws IOException;
  
    /* 將指定的字節(jié)數(shù)組b寫(xiě)入該文件輸入流 */
    public void write(byte b[]) throws IOException {
        Object traceContext = IoTrace.fileWriteBegin(path);
        int bytesWritten = 0;
        try {
            writeBytes(b, 0, b.length, append);
            bytesWritten = b.length;
        } finally {
            IoTrace.fileWriteEnd(traceContext, bytesWritten);
        }
    }
  
    /* 將指定len長(zhǎng)度的字節(jié)數(shù)組b寫(xiě)入該文件輸入流 */
    public void write(byte b[], int off, int len) throws IOException {
        Object traceContext = IoTrace.fileWriteBegin(path);
        int bytesWritten = 0;
        try {
            writeBytes(b, off, len, append);
            bytesWritten = len;
        } finally {
            IoTrace.fileWriteEnd(traceContext, bytesWritten);
        }
    }
  
    /* 關(guān)閉此文件輸出流并釋放與此流有關(guān)的所有系統(tǒng)資源 */
    publicvoidclose() throwsIOException {
        synchronized(closeLock) {
            if(closed) {
                return;
            }
            closed = true;
        }
  
        if(channel != null) {
            fd.decrementAndGetUseCount();
            channel.close();
        }
  
        intuseCount = fd.decrementAndGetUseCount();
  
        if((useCount <= 0) || !isRunningFinalize()) {
            close0();
        }
    }
  
     public final FileDescriptor getFD()  throws IOException {
        if(fd != null) returnfd;
        thrownewIOException();
     }
  
    publicFile Channel getChannel() {
        synchronized(this) {
            if(channel == null) {
                channel = FileChannelImpl.open(fd, path, false, true, append, this);
  
                fd.incrementAndGetUseCount();
            }
            returnchannel;
        }
    }
  
    protected void finalize() throws IOException {
        if(fd != null) {
            if(fd == FileDescriptor.out || fd == FileDescriptor.err) {
                flush();
            } else{
  
                runningFinalize.set(Boolean.TRUE);
                try{
                    close();
                } finally{
                    runningFinalize.set(Boolean.FALSE);
                }
            }
        }
    }
  
    private native void close0() throws IOException;
  
    private static native void initIDs();
  
    static{
        initIDs();
    }
  
}

 

 

1. 三個(gè)核心方法

三個(gè)核心方法,也就是Override(重寫(xiě))了抽象類OutputStreamwrite方法。

void write(int b) 方法,即

 

?
1
public void write(intb) throws IOException

 

代碼實(shí)現(xiàn)中很簡(jiǎn)單,一個(gè)try中調(diào)用本地nativewrite()方法,直接將指定的字節(jié)b寫(xiě)入文件輸出流。IoTrace.fileReadEnd()的意思和上面FileInputStream意思一致。

 

void write(byte b[]) 方法,即

 

?
1
public void write(byteb[]) throws IOException

 

代碼實(shí)現(xiàn)也是比較簡(jiǎn)單的,也是一個(gè)try中調(diào)用本地nativewriteBytes()方法,直接將指定的字節(jié)數(shù)組寫(xiě)入該文件輸入流。

void write(byte b[], int off, int len) 方法,即

 

?
1
public void write(byte b[], int off, int len) throws IOException

 

 


 

代碼實(shí)現(xiàn)和 void write(byte b[]) 方法 一樣,直接將指定的字節(jié)數(shù)組寫(xiě)入該文件輸入流。

 

2. 值得一提的native方法

上面核心方法中為什么實(shí)現(xiàn)簡(jiǎn)單,因?yàn)楣ぷ髁慷荚?strong>native方法里面,即JVM里面實(shí)現(xiàn)了。native倒是不少一一列舉吧:

native void open(String name) // 打開(kāi)文件,為了下一步讀取文件內(nèi)容

native void write(int b, boolean append) // 直接將指定的字節(jié)b寫(xiě)入文件輸出流

native native void writeBytes(byte b[], int off, int len, boolean append) // 直接將指定的字節(jié)數(shù)組寫(xiě)入該文件輸入流。

native void close0() // 關(guān)閉該文件輸入流及涉及的資源,比如說(shuō)如果該文件輸入流的FileChannel對(duì)被獲取后,需要對(duì)FileChannel進(jìn)行close。

 

相似之處

其實(shí)到這里,該想一想。兩個(gè)源碼實(shí)現(xiàn)很相似,而且native方法也很相似。其實(shí)不能說(shuō)“相似”,應(yīng)該以“對(duì)應(yīng)”來(lái)概括它們。

它們是一組,是一根吸管的兩個(gè)孔的關(guān)系:“一個(gè)Input一個(gè)Output”。

休息一下吧~ 看看小廣告:

開(kāi)源代碼都在我的gitHub上哦 — https://github.com/JeffLi1993 作者留言“請(qǐng)手賤,點(diǎn)項(xiàng)目star,支持支持拜托拜托”

四、使用案例

下面先看代碼:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
packageorg.javacore.io;
  
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
  
/*
 * Copyright [2015] [Jeff Lee]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
  
/**
 * @author Jeff Lee
 * @since 2015-10-8 20:06:03
 * FileInputStream&FileOutputStream使用案例
 */
public class FileIOStreamT {
    private static final String thisFilePath =
            "src"+ File.separator +
            "org"+ File.separator +
            "javacore"+ File.separator +
            "io"+ File.separator +
            "FileIOStreamT.java";
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建文件輸入流
        FileInputStream fileInputStream = new FileInputStream(thisFilePath);
        // 創(chuàng)建文件輸出流
        FileOutputStream fileOutputStream =  new FileOutputStream("data.txt");
          
        // 創(chuàng)建流的最大字節(jié)數(shù)組
        byte[] inOutBytes = new byte[fileInputStream.available()];
        // 將文件輸入流讀取,保存至inOutBytes數(shù)組
        fileInputStream.read(inOutBytes);
        // 將inOutBytes數(shù)組,寫(xiě)出到data.txt文件中
        fileOutputStream.write(inOutBytes);
          
        fileOutputStream.close();
        fileInputStream.close();
    }
}

 

運(yùn)行后,會(huì)發(fā)現(xiàn)根目錄中出現(xiàn)了一個(gè)“data.txt”文件,內(nèi)容為上面的代碼。

1. 簡(jiǎn)單地分析下源碼:

1、創(chuàng)建了FileInputStream,讀取該代碼文件為文件輸入流。

2、創(chuàng)建了FileOutputStream,作為文件輸出流,輸出至data.txt文件。

3、針對(duì)流的字節(jié)數(shù)組,一個(gè) read ,一個(gè)write,完成讀取和寫(xiě)入。

4、關(guān)閉流

2. 代碼調(diào)用的流程如圖所示:

iostream

3. 代碼雖簡(jiǎn)單,但是有點(diǎn)小問(wèn)題

FileInputStream.available() 是返回流中的估計(jì)剩余字節(jié)數(shù)。所以一般不會(huì)用此方法。

一般做法,比如創(chuàng)建一個(gè) byte數(shù)組,大小1K。然后read至其返回值不為-1,一直讀取即可。邊讀邊寫(xiě)。

五、思考與小結(jié)

FileInputStream & FileOutputStream 是一對(duì)來(lái)自 InputStream和OutputStream的實(shí)現(xiàn)類。用于本地文件讀寫(xiě)(二進(jìn)制格式按順序讀寫(xiě))。

本文小結(jié):

1、FileInputStream 源碼分析

2、FileOutputStream 資源分析

3、FileInputStream & FileOutputStream 使用案例

4、其源碼調(diào)用過(guò)程

歡迎點(diǎn)擊我的博客及GitHub — 博客提供rss訂閱哦!

———- http://www.bysocket.com/ ————- https://github.com/JeffLi1993 ———-

全能程序員交流QQ群290551701,群內(nèi)程序員都是來(lái)自,百度、阿里、京東、小米、去哪兒、餓了嗎、藍(lán)港等高級(jí)程序員 ,擁有豐富的經(jīng)驗(yàn)。加入我們,直線溝通技術(shù)大牛,最佳的學(xué)習(xí)環(huán)境,了解業(yè)內(nèi)的一手的資訊。如果你想結(jié)實(shí)大牛,那 就加入進(jìn)來(lái),讓大牛帶你超神!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南昌县| 黄骅市| 唐山市| 图片| 台南县| 若羌县| 炎陵县| 大田县| 浪卡子县| 奉化市| 遂平县| 武胜县| 丰原市| 泽州县| 凉城县| 阿拉善左旗| 扶绥县| 广安市| 武夷山市| 宝兴县| 赤峰市| 舒兰市| 长垣县| 阿鲁科尔沁旗| 江城| 成武县| 汉中市| 江华| 即墨市| 沁水县| 兴安盟| 手机| 洮南市| 桦甸市| 耿马| 广宁县| 界首市| 宝应县| 武山县| 韶关市| 汾阳市|