Java 语言被定义为基于Unicode。一个字符实体由二个字节表示(如果是用UCS-2)。但众多文件和数据流都是基于其它字符编码并以byte传输,操作文件内容就成了一个问题。

操作一个文件首先要对文件内容进行解码,文件内容是二进制数据(也可以认为是字节流),我们要把内容解码为JAVA可以理解的一个个字符(Unicode)。

修改完成后还要按输出编码把文件内容编码成对应的二进制内容,再输出到对应地点。

读取文件内容后要用CharBuffer做decode,才能获取字符内容CharBuffer。

在写文件之前要用CharsetEncoder做encode,才能获取对应字符编码的二进制内容ByteBuffer。

现在我们将分析这个例子程序 UseCharsets.java。这个程序非常简单 ― 它从一个文件中读取一些文本,并将该文本写入另一个文件。但是它把该数据当作文本数据,并使用 CharBuffer 来将该数句读入一个 CharsetDecoder 中。同样,它使用 CharsetEncoder 来写回该数据。

示例程序

在打开相应的文件、将输入数据读入名为 inputData 的 ByteBuffer 之后,我们的程序必须创建 ISO-8859-1 (Latin1) 字符集的一个实例:

Charset latin1 = Charset.forName( "ISO-8859-1" );

然后,创建一个解码器(用于读取)和一个编码器 (用于写入):

CharsetDecoder decoder = latin1.newDecoder();
CharsetEncoder encoder = latin1.newEncoder();

为了将字节数据解码为一组字符,我们把 ByteBuffer 传递给 CharsetDecoder,结果得到一个 CharBuffer

CharBuffer cb = decoder.decode( inputData );

如果想要处理字符,我们可以在程序的此处进行。但是我们只想无改变地将它写回,所以没有什么要做的。

要写回数据,我们必须使用 CharsetEncoder 将它转换回字节:

ByteBuffer outputData = encoder.encode( cb );

在转换完成之后,我们就可以将数据写到文件中了。

处理文本的正确方式

我们将假设字符以 ISO-8859-1(Latin1) 字符集(这是 ASCII 的标准扩展)的形式储存在磁盘上。尽管我们必须为使用 Unicode 做好准备,但是也必须认识到不同的文件是以不同的格式储存的,而 ASCII 无疑是非常普遍的一种格式。事实上,每种 Java 实现都要求对以下字符编码提供完全的支持:

  • US-ASCII
  • ISO-8859-1
  • UTF-8
  • UTF-16BE
  • UTF-16LE
  • UTF-16
public class UseCharsets
{
static public void main( String args[] ) throws Exception {
String inputFile = "samplein.txt";
String outputFile = "sampleout.txt"; RandomAccessFile inf = new RandomAccessFile( inputFile, "r" );
RandomAccessFile outf = new RandomAccessFile( outputFile, "rw" );
long inputLength = new File( inputFile ).length(); FileChannel inc = inf.getChannel();
FileChannel outc = outf.getChannel(); MappedByteBuffer inputData =
inc.map( FileChannel.MapMode.READ_ONLY, 0, inputLength );
//创建 ISO-8859-1 (Latin1) 字符集的一个实例 Charset latin1 = Charset.forName( "ISO-8859-1" ); //创建一个解码器(用于读取)和一个编码器 (用于写入)
CharsetDecoder decoder = latin1.newDecoder();
CharsetEncoder encoder = latin1.newEncoder(); //为了将字节数据解码为一组字符,我们把 ByteBuffer 传递给 CharsetDecoder,结果得到一个 CharBuffer
CharBuffer cb = decoder.decode( inputData ); // Process char data here
//写回数据,我们必须使用 CharsetEncoder 将它转换回字节:
ByteBuffer outputData = encoder.encode( cb ); outc.write( outputData ); inf.close();
outf.close();
}
}

原文件samplein.txt的内容如下:


运行结果:将一个文件中读取一些文本,并将该文本写入另一个文件

【Java NIO的深入研究5】字符集Charset的更多相关文章

  1. JAVA NIO简介-- Buffer、Channel、Charset 、直接缓冲区、分散和聚集、文件锁

    IO  是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. Java标准io回顾 在Java1.4之前的I/O系统中,提供 ...

  2. 【Java NIO的深入研究】 ServerSocketChannel

    Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样.ServerSocketChannel类在 jav ...

  3. 【Java NIO的深入研究6】JAVA NIO之Scatter/Gather

    Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道)中读取或者写入到Channel的操作. 分散(s ...

  4. 【Java NIO的深入研究2】RandomAccessFile的使用

    RandomAccessFile RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须 ...

  5. 【Java NIO的深入研究1】缓冲区

    缓冲区 传统的流和通道的对比 流 通道 慢 快 处理简单 处理复杂 单字节的传输 一块数据的传输 - Java.io.*已经重新写过 - 是对流的模拟 单向的 双向的 可直接访问 必须通过Buffer ...

  6. 海纳百川而来的一篇相当全面的Java NIO教程

    目录 零.NIO包 一.Java NIO Channel通道 Channel的实现(Channel Implementations) Channel的基础示例(Basic Channel Exampl ...

  7. 我的Java开发学习之旅------>Java NIO 报java.nio.charset.MalformedInputException: Input length = 1异常

    今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常, ...

  8. java.nio分析软件包(三)---Charset理解力

    前面的分析后,2一个基本的封装类型.现在我们就来揭开Java.nio魔法知识的最后一块,CharsetEncoding类,他的主要功能是实现字节Unicode之间的转换转码. 让我们来看看他同样的封装 ...

  9. springcloud采坑--Zuul上传文件报java.nio.charset.IllegalCharsetNameException: UTF-8;boundary=sqgzzmMxl1UPdIp0IAYnQgUIAr9yNewVAzKIX

    报错日志: 2018-12-17 10:01:19,688 ERROR [io.undertow.request] (default task-3) UT005023: Exception handl ...

随机推荐

  1. Qt多个信号连接到一个槽,在槽中识别信号的发送者方法(实验 可行)

    Qt是通过信号和槽的机制进行事件传递的,当有多个不同类型.或相同类型的物件的发送信号都通过一个槽来处理的时候,需要在槽中识别出这些信号然后做相应的处理. 例如: 在一个界面中有16个按钮(QPushB ...

  2. mkdir命令的-p和-m

    mkdir命令是常用的命令,用来建立空目录,它还有2个常用参数: -m, --mode=模式 设定权限 (类似 chmod),而不是 rwxrwxrwx 减 umask -p, --parents 需 ...

  3. 最简短的openvpn的设置方式

    这种方式对于测试能否连接到远程系统,十分的有用.尤其是国内复杂的网络环境下,检测一下,到底是服务器的原因,还是网络因素造成的,这是一个快捷的方式. 需要注意的是:这种方法是用明文连接.所有的加密措施都 ...

  4. 【转】Java检测字符串是否有乱码

    package cn.cnnic.ops.learn; import java.util.regex.Matcher;import java.util.regex.Pattern; public cl ...

  5. 修改mysql root账户登录密码

    打开mysql.exe(如果你配置了path的话,打开cmd即可)键入: mysqladmin -u root -p password [你的新密码][回车] 然后会要求你输入你当前的密码,就修改成功 ...

  6. malloc和free函数详解

    一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...

  7. CentOS清除用户登录记录和命令历史方法

    清除登陆系统成功的记录 [root@localhost root]# echo > /var/log/wtmp //此文件默认打开时乱码,可查到ip等信息 [root@localhost roo ...

  8. 一款基于jquery实现的鼠标单击出现水波特效

    今天要为大家绍一款由jquery实现的鼠标单击出现水波特效.用鼠标猛点击页面,你可以看到页面不断出面水波纹效果.然后水波纹渐渐消失.效果非常不错.我们一起看下效果图: 在线预览   源码下载 实现的代 ...

  9. 未能加载文件或程序集Office,Version=11.0.0.0

    关于"未能加载文件或程序集“Office, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”或它的某一个 ...

  10. 【Unity笔记】检测当前的运行平台

    // 判断当前运行平台为Android平台时 if (Application.platform == RuntimePlatform.Android) { if (Input.GetKeyDown(K ...