[C#基础]字符编码与二进制

参考链接:

http://baike.baidu.com/link?url=2pZNZUhdXpLZqvjzWdoCJjnOq-ncGt0jQveoZjvLq0HtxLKjLsrEvYA7t_TUaRxvh3aYWt0NFs4PQD2IBevgUa#7

http://www.cnblogs.com/laozuan/archive/2012/04/24/2467888.html

http://www.xuanyusong.com/archives/1919


字符编码的重要性:

世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。

因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。


基础知识:

1字节=8位,可以表示256个字符,从8个0到8个1

c#数据类型占用的字节数:

bool -> System.Boolean (布尔型,其值为 true 或者 false)

byte -> System.Byte (字节型,占 1 字节,表示 8 位正整数,范围 0 ~ 255)

sbyte -> System.SByte (带符号字节型,占 1 字节,表示 8 位整数,范围 -128 ~ 127)

char -> System.Char (字符型,占2字节,表示 1 个 Unicode 字符)

short -> System.Int16 (短整型,占 2 字节,表示 16 位整数,范围 -32,768 ~ 32,767)

ushort -> System.UInt16 (无符号短整型,占 2 字节,表示 16 位正整数,范围 0 ~ 65,535)

uint -> System.UInt32 (无符号整型,占 4 字节,表示 32 位正整数,范围 0 ~ 4,294,967,295)

int -> System.Int32 (整型,占 4 字节,表示 32 位整数,范围 -2,147,483,648 到 2,147,483,647)

float -> System.Single (单精度浮点型,占 4 个字节)

ulong -> System.UInt64 (无符号长整型,占 8 字节,表示 64 位正整数,范围 0 ~ 大约 10 的 20 次方)

long -> System.Int64 (长整型,占 8 字节,表示 64 位整数,范围大约 -(10 的 19) 次方 到 10 的 19 次方)

double -> System.Double (双精度浮点型,占8 个字节) 

0.
a.二进制,逢二进一,主要用在加减法的运算
例:1011 + 11 = 1110


b.0x开头,表示十六进制(是数字0,不是字母o)
例:0x100F


1.& 与
类似于"and",两个二进制数,均为1时结果为1,否则为0
例:0000 1001 & 0000 0101 = 0000 0001 


2.| 或
类似于"or",两个二进制数,只要有1结果为1,否则为0
例:0000 1001 | 0000 0101 = 0000 1101 


与、或运算通常用于将某些位清零,或者保留某些位
例:a & 0000 1111 表示将高四位清零,保留低四位


3.<< 左移
左移运算是将一个二进制位的操作数按指定移动的位数向左移位,移出位被丢弃,右边的空位一律补0


4.>> 右移
右移运算是将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,左边的空位一律补0,
或者补符号位,这由不同的机器而定


常见字符编码:

1. ASCII码

ASCII码一共规定了128个字符的编码,只占用了一个字节的后面7位,最前面的1位统一规定为0。

缺点:英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。


2.Unicode(相当于UTF-16)

Unicode是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,可以解决乱码问题。一个Unicode字符由两个字节组成。

缺点:Unicode固然统一了编码方式,但是它的效率不高,比如UCS-4(Unicode的标准之一)规定用4个字节存储一个符号,那么每个英文字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。


3.UTF-8

为了提高Unicode的编码效率,于是就出现了UTF-8编码。UTF-8可以根据不同的符号自动选择编码的长短。比如英文字母可以只用1个字节就够了。

UTF-8就是在互联网上使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一。


4.GBK

GBK采用双字节表示,解决汉字编码的问题。


c#中二进制文件的读写:

BinaryWriter类:https://msdn.microsoft.com/zh-cn/library/system.io.binarywriter.aspx

BinaryReader类:https://msdn.microsoft.com/zh-cn/library/system.io.binaryreader.aspx

Array.Copy:从指定的源索引开始,复制 Array 中的一系列元素,将它们粘贴到另一Array 中(从指定的目标索引开始)。

public static void Copy(
	Array sourceArray,
	int sourceIndex,
	Array destinationArray,
	int destinationIndex,
	int length
)

using UnityEngine;
using System.Collections;
using System.IO;
using System.Text;
using UnityEditor;

public class TestByte : MonoBehaviour {

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1)) WriteByte();
        if (Input.GetKeyDown(KeyCode.Alpha2)) ReadByte();
    }

	void WriteByte() 
	{
        string path = Application.dataPath + @"/binary.txt";

        if (File.Exists(path))
            File.Delete(path);
        FileStream fs = new FileStream(path,FileMode.Create);
        BinaryWriter bw = new BinaryWriter(fs);

        bw.Write("宏哥");
        bw.Write((short)1995);
        bw.Write((int)2015);
        bw.Write((float)530);
        bw.Write(true);

        bw.Close();
        fs.Close();

        AssetDatabase.Refresh();
	}

    void ReadByte()
    {
        string path = Application.dataPath + @"/binary.txt";

        FileStream fs = new FileStream(path, FileMode.Open);
        BinaryReader br = new BinaryReader(fs);

        print(br.ReadString());
        print(br.ReadInt16());
        print(br.ReadInt32());
        print(br.ReadSingle());
        print(br.ReadBoolean());

        br.Close();
        fs.Close();
    }
}



二进制文件:


输出:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            TestMemoryStream();
            TestBinaryReaderWriter();
            Console.ReadLine(); 
        }

        static void TestMemoryStream()
        {
            //如果使用文件流,则信息会被写进文件中
            //而使用内存流,则信息会被写进内存中,不会产生额外的文件
            MemoryStream ms = new MemoryStream();
            //将待写入的数据从字符串转换为字节数组 
            byte[] testBytes = Encoding.UTF8.GetBytes("测试数据");

            PrintInfo(ms);
        
            ms.Write(testBytes, 0, testBytes.Length);
            PrintInfo(ms);

            //SeekOrigin的三种取值:
            //1.Begin 指定流的开头 2.Current 指定流内的当前位置 3.End 指定流的结尾
            //将position重定位为开头
            ms.Seek(0, SeekOrigin.Begin);
            byte[] bytes = new byte[testBytes.Length];
            ms.Read(bytes, 0, bytes.Length);
            Console.WriteLine("bytes:{0}", Encoding.UTF8.GetString(bytes, 0, bytes.Length));
            PrintInfo(ms);

            byte[] buffer = ms.GetBuffer();
            Console.WriteLine("buffer:{0}", Encoding.UTF8.GetString(buffer, 0, buffer.Length));
            PrintInfo(ms);     
        }

        static void PrintInfo(MemoryStream ms)
        {
            Console.WriteLine("Capacity:{0}", ms.Capacity);
            Console.WriteLine("Length:{0}", ms.Length);
            Console.WriteLine("Position:{0}", ms.Position);
            Console.WriteLine();
        }

        static void TestBinaryReaderWriter()
        {
            MemoryStream ms = new MemoryStream();
            BinaryReader br = new BinaryReader(ms);
            BinaryWriter bw = new BinaryWriter(ms);

            bw.Write("helloworld");
            ms.Seek(0, SeekOrigin.Begin);
            string s = br.ReadString();
            Console.WriteLine("content:{0}",s);

            //字符串的长度是可变的,因此无法确定字符串的字节数
            //当使用BinaryWriter.Write写入字符串时,会用第一位来存储字符串的长度
            ms.Seek(0, SeekOrigin.Begin);
            byte[] bytes = ms.ToArray();
            for (int i = 0; i < bytes.Length;i++ )
            {
                Console.WriteLine("content:{0}", bytes[i]);
            }
        }
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值