`
holdbelief
  • 浏览: 705967 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

第十四课时:输入/输出2

阅读更多


3、使用 Channel
Channel 类似于传统的流对象, 但与传统的流不同的是, Channel 有两个主要的区别:
  • Channel 可以直接将指定文件的部分或全部映射成 Buffer
  • 程序不能直接访问 Channel 中的数据, 包括读取, 写入都不行, Channel 只能与 Buffer 进行交互, 也就是说, 要从 Channel 中取得数据, 必须先用 Buffer 从 Channel 中取出一些数据, 然后让程序从 Buffer 中去除这些数据; 如果要将程序中的数据写入 Channel, 一样先让程序将数据放入 Buffer 中, 程序再将 Buffer 里的输入写入 Channel 中
Channel 是一个接口, 位于 java.nio.channels 包下,系统为该接口提供了 DatagramChannel, FileChannel, Pipe.SinkChannel, Pipe.SourceChannel, SelectableChannel, ServerSocketChannel, SocketChannel 等实现类.
所有的 Channel 都不应该通过构造起来直接创建, 而是通过传统的节点流 InputStream, OutputStream 的 getChannel 方法来返回对应的 Channel, 不同的节点流获得的 Channel 不一样, 例如 FileInputStream, FileOutputStream 的 getChannel 方法返回的是 FileChannel, 而 PipedInputStream 和 PipedOutputStream 的 getChannel 方法返回的是 Pipe.SinkChannel, Pipe.SourceChannel.
Channel 常用的三类方法是: map, read 和 write, 其中 map 方法用于将 Channel 对应的部分或全部数据映射成 ByteBuffer; 而 read 或 write 方法都有一些冲在形式, 这些方法用于从 Buffer 中读取数据或向 Buffer 里写入数据.
其 map 方法的方法签名为: MappedByteBuffer map(FileChannel.MapMode mode, long position, long size): 第一个参数执行映射式的模式, 分别有只读, 读写等模式, 第二三个参数用于控制将 Channel 的哪些数据映射成 ByteBuffer.
下面程序示范了直接将 FileChannel 的全部数据映射成 ByteBuffer 的效果:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;


public class FileChannelTest {

/**
* @param args
*/
public static void main(String[] args) {
FileChannel inChannel = null;
FileChannel outChannel = null;
try
{
File f = new File("D:\\Java课程\\14\\NewIOProject\\src\\FileChannelTest.java");
// 创建 FileInputStream, 以该文件输入流创建 FileChannel
inChannel = new FileInputStream(f).getChannel();
// 将 FileChannel 里的全部数据映射成 ByteBuffer
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
// 使用 GBK 的字符集来创建编码器
Charset charset = Charset.forName("GBK");
// 以文件输出流创建 FileBuffer, 用以控制输出
outChannel = new FileOutputStream("a.txt").getChannel();
// 直接将 Buffer 里的数据全部输出
outChannel.write(buffer);
// 再次调用 buffer 的 clear() 方法, 复原 limti, position 的位置
buffer.clear();
// 创建解码器(CharsetDecoder)对象
CharsetDecoder decoder = charset.newDecoder();
// 使用解码器将 ByteBuffer 转换成 CharBuffer
CharBuffer charBuffer = decoder.decode(buffer);
// CharBuffer 的 toString 方法可以获取对应的字符串
System.out.println(charBuffer);
}
catch (IOException e) 
{
e.printStackTrace();
}
finally
{
try
{
if (inChannel != null)
{
inChannel.close();
}
if (outChannel != null)
{
outChannel.close();
}
}
catch (Exception e) 
{
e.printStackTrace();
}
}
}

}

不仅 InputStream, OutputStream 包含了 getChannel 方法, 在 RandomAccessFile 中也包含了一个 getChannel 方法, 由 RandomAccessFile 返回的 FileChannel 的只读还是读写的 Channel 则取决于 RandomAccessFile 打开文件的模式, 例如下面的程序将会把 a.txt 文件的内容复制出来, 追加到该文件的后面.

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.RandomAccessFile;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

 

 

public class RandomAccessFileChannelTest {

public static void main(String[] args) {

FileChannel randomChannel = null;

File fb = null;

FileChannel outChannel = null;

try

{

File f = new File("a.txt");

// 创建一个 RandomAccessFile 对象

RandomAccessFile raf = new RandomAccessFile(f, "rw");

// 获取 RandomAccessFile 对应的 Channel

randomChannel = raf.getChannel();

// 将 Channel 中所有的数据映射成 ByteBuffer

ByteBuffer buffer = randomChannel.map(FileChannel.MapMode.READ_ONLY, 0, raf.length());

// 把 Channel 的记录指针移动到最后

randomChannel.position(f.length());

// 将 buffer 中所有数据输出

randomChannel.write(buffer);

fb = new File("b.txt");

outChannel = new FileOutputStream(fb).getChannel();

outChannel.write(buffer);

}

catch (Exception e)

{

e.printStackTrace();

}

finally

{

try

{

if (randomChannel != null)

{

randomChannel.close();

}

if (outChannel != null)

{

outChannel.close();

}

}

catch (Exception e) 

{

e.printStackTrace();

}

}

}

}

如果担心 Channel 对应的文件过大, 使用 map 方法一次将所有文件内容映射到内存中因其性能下降,也可以使用 Channel 和 Buffer 传统的多次取数的方式:
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;


public class ReadFile {
public static void main(String[] args) {
FileChannel fcin = null;
try
{
// 创建文件输入流
FileInputStream fis = new FileInputStream("D:\\Java课程\\14\\NewIOProject\\src\\ReadFile.java");
// 创建一个 FileChannel
fcin = fis.getChannel();
// 定义一个 ByteBuffer 对象, 用于重复取数
ByteBuffer bbuffer = ByteBuffer.allocate(1024);
// 将 FileChannel 中数据放入 ByteBuffer 中
while ( fcin.read(bbuffer) != -1 )
{
// 锁定 Buffer 的空白区
bbuffer.flip();
// 创建 Charset 对象
Charset charset = Charset.forName("gb2312");
// 创建解码器 (CharsetDecoder) 对象
CharsetDecoder decoder = charset.newDecoder();
// 将 ByteBuffer 的内容转码
CharBuffer cbuffer = decoder.decode(bbuffer);
System.out.println(cbuffer.toString());
// 将 buffer 初始化, 为下一次取数据做准备
bbuffer.clear();
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (fcin != null)
{
fcin.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}

4、编码集和 Charset
Charset 里提供了一个 availableCharset() 静态方法来获取当前 JDK 所支持的所有字符集, 所以程序可以使用如下程序来获取该 JDK 所支持的全部字符集.
import java.nio.charset.Charset; import java.util.SortedMap; public class CharsetTest { public static void main(String[] args) { // 获取全部字符集 SortedMap<String, Charset> map = Charset.availableCharsets(); for ( String alias : map.keySet() ) { // 输出字符记得别名和对应的 Charset 对象 System.out.println(alias + "-------->" + map.get(alias) ); } } }

运行结果:
Big5-------->Big5
Big5-HKSCS-------->Big5-HKSCS
EUC-JP-------->EUC-JP
EUC-KR-------->EUC-KR
GB18030-------->GB18030
GB2312-------->GB2312
GBK-------->GBK
IBM-Thai-------->IBM-Thai
IBM00858-------->IBM00858
IBM01140-------->IBM01140
IBM01141-------->IBM01141
IBM01142-------->IBM01142
IBM01143-------->IBM01143
IBM01144-------->IBM01144
IBM01145-------->IBM01145
IBM01146-------->IBM01146
IBM01147-------->IBM01147
IBM01148-------->IBM01148
IBM01149-------->IBM01149
IBM037-------->IBM037
IBM1026-------->IBM1026
IBM1047-------->IBM1047
IBM273-------->IBM273
IBM277-------->IBM277
IBM278-------->IBM278
IBM280-------->IBM280
IBM284-------->IBM284
IBM285-------->IBM285
IBM297-------->IBM297
IBM420-------->IBM420
IBM424-------->IBM424
IBM437-------->IBM437
IBM500-------->IBM500
IBM775-------->IBM775
IBM850-------->IBM850
IBM852-------->IBM852
IBM855-------->IBM855
IBM857-------->IBM857
IBM860-------->IBM860
IBM861-------->IBM861
IBM862-------->IBM862
IBM863-------->IBM863
IBM864-------->IBM864
IBM865-------->IBM865
IBM866-------->IBM866
IBM868-------->IBM868
IBM869-------->IBM869
IBM870-------->IBM870
IBM871-------->IBM871
IBM918-------->IBM918
ISO-2022-CN-------->ISO-2022-CN
ISO-2022-JP-------->ISO-2022-JP
ISO-2022-JP-2-------->ISO-2022-JP-2
ISO-2022-KR-------->ISO-2022-KR
ISO-8859-1-------->ISO-8859-1
ISO-8859-13-------->ISO-8859-13
ISO-8859-15-------->ISO-8859-15
ISO-8859-2-------->ISO-8859-2
ISO-8859-3-------->ISO-8859-3
ISO-8859-4-------->ISO-8859-4
ISO-8859-5-------->ISO-8859-5
ISO-8859-6-------->ISO-8859-6
ISO-8859-7-------->ISO-8859-7
ISO-8859-8-------->ISO-8859-8
ISO-8859-9-------->ISO-8859-9
JIS_X0201-------->JIS_X0201
JIS_X0212-1990-------->JIS_X0212-1990
KOI8-R-------->KOI8-R
KOI8-U-------->KOI8-U
Shift_JIS-------->Shift_JIS
TIS-620-------->TIS-620
US-ASCII-------->US-ASCII
UTF-16-------->UTF-16
UTF-16BE-------->UTF-16BE
UTF-16LE-------->UTF-16LE
UTF-32-------->UTF-32
UTF-32BE-------->UTF-32BE
UTF-32LE-------->UTF-32LE
UTF-8-------->UTF-8
windows-1250-------->windows-1250
windows-1251-------->windows-1251
windows-1252-------->windows-1252
windows-1253-------->windows-1253
windows-1254-------->windows-1254
windows-1255-------->windows-1255
windows-1256-------->windows-1256
windows-1257-------->windows-1257
windows-1258-------->windows-1258
windows-31j-------->windows-31j
x-Big5-Solaris-------->x-Big5-Solaris
x-euc-jp-linux-------->x-euc-jp-linux
x-EUC-TW-------->x-EUC-TW
x-eucJP-Open-------->x-eucJP-Open
x-IBM1006-------->x-IBM1006
x-IBM1025-------->x-IBM1025
x-IBM1046-------->x-IBM1046
x-IBM1097-------->x-IBM1097
x-IBM1098-------->x-IBM1098
x-IBM1112-------->x-IBM1112
x-IBM1122-------->x-IBM1122
x-IBM1123-------->x-IBM1123
x-IBM1124-------->x-IBM1124
x-IBM1381-------->x-IBM1381
x-IBM1383-------->x-IBM1383
x-IBM33722-------->x-IBM33722
x-IBM737-------->x-IBM737
x-IBM834-------->x-IBM834
x-IBM856-------->x-IBM856
x-IBM874-------->x-IBM874
x-IBM875-------->x-IBM875
x-IBM921-------->x-IBM921
x-IBM922-------->x-IBM922
x-IBM930-------->x-IBM930
x-IBM933-------->x-IBM933
x-IBM935-------->x-IBM935
x-IBM937-------->x-IBM937
x-IBM939-------->x-IBM939
x-IBM942-------->x-IBM942
x-IBM942C-------->x-IBM942C
x-IBM943-------->x-IBM943
x-IBM943C-------->x-IBM943C
x-IBM948-------->x-IBM948
x-IBM949-------->x-IBM949
x-IBM949C-------->x-IBM949C
x-IBM950-------->x-IBM950
x-IBM964-------->x-IBM964
x-IBM970-------->x-IBM970
x-ISCII91-------->x-ISCII91
x-ISO-2022-CN-CNS-------->x-ISO-2022-CN-CNS
x-ISO-2022-CN-GB-------->x-ISO-2022-CN-GB
x-iso-8859-11-------->x-iso-8859-11
x-JIS0208-------->x-JIS0208
x-JISAutoDetect-------->x-JISAutoDetect
x-Johab-------->x-Johab
x-MacArabic-------->x-MacArabic
x-MacCentralEurope-------->x-MacCentralEurope
x-MacCroatian-------->x-MacCroatian
x-MacCyrillic-------->x-MacCyrillic
x-MacDingbat-------->x-MacDingbat
x-MacGreek-------->x-MacGreek
x-MacHebrew-------->x-MacHebrew
x-MacIceland-------->x-MacIceland
x-MacRoman-------->x-MacRoman
x-MacRomania-------->x-MacRomania
x-MacSymbol-------->x-MacSymbol
x-MacThai-------->x-MacThai
x-MacTurkish-------->x-MacTurkish
x-MacUkraine-------->x-MacUkraine
x-MS932_0213-------->x-MS932_0213
x-MS950-HKSCS-------->x-MS950-HKSCS
x-mswin-936-------->x-mswin-936
x-PCK-------->x-PCK
x-SJIS_0213-------->x-SJIS_0213
x-UTF-16LE-BOM-------->x-UTF-16LE-BOM
X-UTF-32BE-BOM-------->X-UTF-32BE-BOM
X-UTF-32LE-BOM-------->X-UTF-32LE-BOM
x-windows-50220-------->x-windows-50220
x-windows-50221-------->x-windows-50221
x-windows-874-------->x-windows-874
x-windows-949-------->x-windows-949
x-windows-950-------->x-windows-950
x-windows-iso2022jp-------->x-windows-iso2022jp

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics