[转]C#的二进制文件操作及关于Encoding类与汉字编码转换的问题
1.数值应保存在二进制文件
//文本文件操作:创建/读取/拷贝/删除
using System;
using System.IO;
class Test
{
string path = @"f:/t.txt";
public static void Main()
{
//创建并写入(将覆盖已有文件)
if (!File.Exists(path))
{
//StreamWriter m=new
//StreamWriter(path,true,Encoding.Default,1);//ASCII,1 Encoding.Default:即//UTF-8编码 这样就可以指定编码方式
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("Hello");
}
}
//读取文件
using (StreamReader sr = File.OpenText(path))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
//删除/拷贝
try
{
File.Delete(path);
File.Copy(path, @"f:/tt.txt");
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
}
方式2:
//流文件(二进制)操作
private const string name = "Test.data";
public static void Main(String[] args)
{
//打开文件() ,或通过File创建立如:fs = File.Create(path, 1024)
FileStream fs = new FileStream(name, FileMode.CreateNew);
//转换为字节写入数据(可写入中文)
Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
//字节数组,字节偏移量,最多写入的字节数
BinaryWriter w = new BinaryWriter(fs);
//设置要写入的偏移量
fs.Position=fs.Length;
// fs.Write(info, 0, info.Length); 这个也可以
w.Close();
fs.Close();
//打开文件
fs = new FileStream(name, FileMode.Open, FileAccess.Read);
//读取
BinaryReader r = new BinaryReader(fs);
for (int i = 0; i < 11; i++)
{
Console.WriteLine(r.ReadInt32());
}
w.Close();
fs.Close();
在将一系列二进制数如方式1写入到file.txt(二进制)文件后,打开file.txt后显示的数据二进制数有些错误,有些正确。(与存入的不一样)向文件中写入的默认(也可以设置)都是使用UTF-8编码。打开file.txt是也是默认UTF-8编码。 若将其如方式2存入二进制文件,则显示的数据一致。若将二进制数(整数)保存为文本文件出错。二进制文件是直接写入文件的(磁盘)没有经过编码和读取时的解码。
2.关于Encoding
CLR中的Encoding是在System.Text命名空间下的,它是一个抽象类(abstract class), 所以不能被直接实例化,它主要有如下的派生类:ASCIIEnding,UnicodeEncoding,UTF32Encoding,UTF7Encoding,UTF8Encoding,你可以根据需要选择一个合适的Encoding来进行编码和解码。你也可以调用Encoding的静态属性ASCII,Unicode,UTF32,UTF7,UTF8,来构造一个Encoding。其中Unicode是表示16位Encoding。调用静态属性和实例化一个子类的效果是一样的,如下代码。
Encoding encodingUTF8 = Encoding.UTF8;
Encoding encodingUTF8 = new UTF8Encoding(true);
以下是这些类型的一些简单描述:
ASCII编码 将16位字符编码成ASCII码,只能转换值小于Ox0080的16字符,并且被转换成单字节,就是说一个字符对应一个字节。当字符都在ASCII范围(0X00~0X7F)内时,可以用这种编码,它的速度非常快,适合于英美地区的字符。这种编码非常有限,汉字会被转换成乱码。在CLR对应ASCIIEndoing。
UTF-16 每个字符编码成2个字节,它不会对字符产生任何影响,也不会涉及到压缩处理,性能非常好,因为CLR中的字符也是16位的Unicode。在CLR中对应UnicodeEncoding。
UTF-32 使用4个字节编码成一个字符。从内存角度上讲,它并不是一种高效能的编码方案,因为第个字符都是4个字节,特别占内存,所以很少用来做文件和网络流的编码解码。在CLR中对应UTF32Encoding。
UTF-8 值在Ox0080之下的字符压缩成一个字符,也就是ASCII码;值在0X0080---0X07FF之间的字符都转换成2个字符,适合用于欧洲和中东地区。0X0800以上被转换成3个字符,适合于东亚地区的字符。代理项被转换成4个字节。因此,它是一种非常流行的编码,适用于互联网。它在处理0X0800以上的字符效率不好UTF-16。在CLR中对应UTF8Encoding。
UTF-7 这咱编码通常用于旧的系统,那时的系统是用7位值表示。目前已经被Unicode协淘汰。在CLR中对应UTF7Encoding。
从性能角度上来讲,如果你的代码需要在多处调用一个Encoding,微软建议你使用静态成员的方式构造一个Encoding对象,而不是构造实例。它的内部实现是一个单例模式。
如果你知道某种编码的代码页(code page)或名字,那么你可以调用Encoding的静态方法GetEncoding(int codepage),GetEncoding(string name)来构造一个Encoding,比如我们常用的用于显示简体中文的gb2312,它的代码页是936,我们就可以这样定义:
Encoding encodingGB2312=Encoding.GetEncoding("gb2312");
Encoding encodingGB2312=Encoding.GetEncoding(936);
目前有几十种文字代码页,分别对应于不同的国家,不同的语言,它们只是对应Unicode字符集里的相一部分,比如说936,它只是对应于Unicode字符集里简体中文的那一部分,如果你想正确的显示繁体字,那么就要用中文繁体对应的代码页950。具体的代码页有哪些可以参考MSDN或园子里这篇文章,C#文字代码页,文字编码的代码页名称速查表。
Encoding对象有一个静态属性Default,它返回的也是一个Encoding对象,至于返回哪个语言的Encoding取决于你电脑里-->控制面板->区域和语言 里面的设置,也就是ANSI。如下图,我电脑里设置是Chinses(Simplified, PRC)也就是简体中文,那么对应的就是gb2312,所以下面代码会打印gb2312。如果你的代码在不止一个国家里使用,那么你最好不要Encoding.Default,这样会造成乱码,你最好用Encoding.UTF8。
3.汉字编码转换相关:
UNICODE是为了处理包括中文,日文等字符而提出的一种通用的字符集。最初的UNICODE为双字节字符集,即16位编码,能够包括65536个字符。但这样的容量并不能满足所有需要,因此,现在的UNICODE已经扩展到4个字节,能够容纳1,112,064 个字符,而这些在16位之后的扩展背称为增补字符。
UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案。
UTF-8 使用一至四个字节的序列对编码 Unicode 代码点进行编码。U+0000 至 U+007F 使用一个字节编码,U+0080 至 U+07FF 使用两个字节,U+0800 至 U+FFFF 使用三个字节,而 U+10000 至 U+10FFFF 使用四个字节。UTF-8 设计原理为:字节值 0x00 至 0x7F 始终表示代码点 U+0000 至 U+007F(Basic Latin 字符子集,它对应 ASCII 字符集)。这些字节值永远不会表示其他代码点,这一特性使 UTF-8 可以很方便地在软件中将特殊的含义赋予某些 ASCII 字符。
GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。当然也可以表示数字和字符(一个字节,与ASCII表示相同)。
要读取一个以GB2312编码的包含汉字、数字、字母的二进制文件。
String strName =Encoding.GetEncoding("gb2312").GetString(name,0,i) ;
// name是读取的二进制数组。
这样就能将二进制数组转换为汉字、数字或字母 同样:也可以将包含汉字、数字、字母的字符串转换为二进制数组保存到二进制文件。
String unicodeString = "备用43E";
Byte[] encodedBytes = Encoding.GetEncoding("gb2312").GetBytes(unicodeString); 当然也可以进行二进制数组与UNICODE,UTF-8等编码方式的转换
Byte[] encodedBytes = utf8.GetBytes(unicodeString);
String decodedString = utf8.GetString(encodedBytes); UnicodeEncoding unicode = new UnicodeEncoding();
Byte[] encodedBytes = unicode.GetBytes(unicodeString);
String decodedString = unicode.GetString(encodedBytes);
原文链接:C#的二进制文件操作及汉字编码转换
其它有价值的链接:
[转]C#的二进制文件操作及关于Encoding类与汉字编码转换的问题的更多相关文章
- 【转载】C#工具类:实现文件操作File的工具类
在应用程序的开发中,文件操作的使用基本上是必不可少的,FileStream类.StreamWriter类.Directory类.DirectoryInfo类等都是文件操作中时常涉及到的类,我们可以通过 ...
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- Android学习笔记之数据的Sdcard存储方法及操作sdcard的工具类
FileService.java也就是操作sdcard的工具类: ? 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 ...
- [WinForm]WinForm跨线程UI操作常用控件类大全
前言 在C#开发的WinForm窗体程序开发的时候,经常会使用多线程处理一些比较耗时之类的操作.不过会有一个问题:就是涉及到跨线程操作UI元素. 相信才开始接触的人一定会遇上这个问题. 为了解决这个问 ...
- php操作oracle的方法类集全
在网上开始找php中操作oracle的方法类~ 果然找到一个用php+oracle制作email表以及插入查询的教程,赶忙点开来看,从头到尾仔细的看了一遍,还没开始操作,便觉得收获很大了.地址在此:h ...
- 操作集合的工具类Collections
1 操作集合的工具类Collections Java提供了一个操作Set.List和Map等集合的工具类:Collections,该工具类里提供了大量方法对集合元素进行排序.查询和修改等操 ...
- C#反射技术的简单操作(读取和设置类的属性)
public class A { public int Property1 { get; set; } } static void Main(){ A aa = new A(); Type type ...
- Java操作字符串的工具类
操作字符串的工具类 import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStre ...
- Java操作图片的工具类
操作图片的工具类: import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.a ...
- .NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper
.NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper 參考演示样例代码,例如以下所看到的: /// <summary> /// MySql ...
随机推荐
- HTTP常见状态码详细解析
HTTP状态码(英语:HTTP Status Code)是用以表示网页服务器 超文本传输协议响应状态的3位数字代码. 它由 RFC 2616 规范定义的,并得到 RFC 2518.RFC 2817.R ...
- DP 详解
DP 概述 DP(Dynamic programming,全称动态规划),是一种基于分治,将原问题分解为简单子问题求解复杂问题的方法. 动态规划的耗时往往远少于朴素(爆搜)解法. 动态规划 and 递 ...
- 【JVM第3课】运行时数据区
运行时数据区结构图如下: 可分为 5 个区域,分别是方法区.堆区.虚拟机栈.本地方法栈.程序计数器.这里大概介绍一下各个模块的作用,会在后面的文章展开讲. 类加载子系统会把类信息加载到方法区,程序运行 ...
- 初识GO语言--流程控制
- ABC 364
ABC 364 E - Maximum Glutton 给定 \((a_i,b_i),X,Y\), 记 \(k\) 是第一个让 \(\sum_{i=1}^{k} a_i > X\) 或 \(\s ...
- ABP发布后通过外部URL调用不到方法
MVC要与Host项目发布保持同步,如果Host工程不保持同步就会导致调用不到新的方法,因为找不得新的dll.
- TIKZ——LaTeX基本绘图
TIKZ是LaTeX的一个绘图包,可以绘制其他软件很难画出来的图像. 基本用法 直线.垂足.矩形.椭圆 代码: \documentclass{article} \usepackage{tikz} \u ...
- [python] asyncio库常见问题与实践案例
本文详细介绍了在使用asyncio库编写异步程序时常见的错误和问题,并进一步通过实践案例进行分析和讨论,以便在项目中更有效地应用asyncio库.有关asyncio库的详细介绍,可参考:Python ...
- Java中private方法能重写吗?
问题:Java中private方法能重写吗? 下面是测试代码 public class A { private void print() { System.out.println("A&qu ...
- 如何使用建造者模式(Builder Pattern)创建不可变类
本文由 ImportNew - 唐小娟 翻译自 Journaldev.如需转载本文,请先参见文章末尾处的转载要求. ImportNew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的 Java ...