C#读写二进制文件

http://www.cnblogs.com/top5/archive/2011/02/07/1949675.html
本文要介绍的C#本地读写二进制文件,二进制文件指保存在物理磁盘的一个文件。

第一步:读写文件转成流对象。其实就是读写文件流 (FileStream对象,在System.IO命名空间中)。File、FileInfo、FileStream这三个类可以将打开文件,并变成文件 流。下面是引用微软对File、FileInfo、FileStream的介绍
System.IO.File类 提供用于创建、复制、删除、移动和打开文件的静态方法,并协助创建 FileStream 对象。
System.IO.FileInfo类 提供创建、复制、删除、移动和打开文件的实例方法,并且帮助创建 FileStream 对象。无法继承此类。
System.IO.FileStream类 公开以文件为主的 Stream,既支持同步读写操作,也支持异步读写操作。
我直接使用 FileStream,他继承于Stream

第二步:读写流。读写二进制文件用System.IO.BinaryReader和System.IO.BinaryWriter类;读写文本文件用System.IO.TextReader和System.IO.TextWriter类。下面是我的实体 (即要保持到文件的数据)
  /// <summary>
 /// 学生基本信息类
 /// </summary>
 public class Student
 {
  /// <summary>
  /// 学号变量
  /// </summary>
  private String _id;
  /// <summary>
  /// 姓名变量
  /// </summary>
  private String _name;
  /// <summary>
  /// 语文成绩变量
  /// </summary>
  private Double _score1;
  /// <summary>
  /// 数学成绩变量
  /// </summary>
  private Double _score2;
  /// <summary>
  /// 英语成绩变量
  /// </summary>
  private Double _score3;

/// <summary>
  /// 学号属性
  /// </summary>
  public String Id
  {
   get { return _id; }
   set { _id = value; }
  }
  /// <summary>
  /// 姓名属性
  /// </summary>
  public String Name
  {
   get { return _name; }
   set { _name = value; }
  }
  /// <summary>
  /// 语文成绩属性
  /// </summary>
  public Double Score1
  {
   get { return _score1; }
   set { _score1 = value; }
  }
  /// <summary>
  /// 数学成绩属性
  /// </summary>
  public Double Score2
  {
   get { return _score2; }
   set { _score2 = value; }
  }
  /// <summary>
  /// 英语成绩属性
  /// </summary>
  public Double Score3
  {
   get { return _score3; }
   set { _score3 = value; }
  }
 }
 下面是我的读方法,读取文件中的信息到参数List<Student> stu中

/// <summary>
  /// 读取信息方法
  /// </summary>
  /// <returns>读取是否成功</returns>
  public void ReadInfo(List<Student> stu)
  {
   Console.WriteLine("请输入文件读取路径:(键入回车为默认路径)");
   String filename = Console.ReadLine();
   FileStream fs;
   //默认路径
   if (filename == "")
   {
    fs = new FileStream("student.dll", FileMode.Open);
   }
   else
   {
    //如果文件不存在,就提示错误
    if (!File.Exists(filename))
    {
     Console.WriteLine("\n\t读取失败!\n错误原因:可能不存在此文件");
     return;
    }
    //否则创建文件
    fs = new FileStream(filename, FileMode.Open);
   }
   //使用二进制读取
   BinaryReader br = new BinaryReader(fs);
   Console.Write("读取信息将覆盖现有的信息,继续吗?y/n :");
   String command = Console.ReadLine();
   if (command == "y" || command == "Y")
   {
    for (int i = 0; i < stu.Count; i++)
    {
     stu.RemoveAt(i);
    }
    //从磁盘上读取信息
    try
    {
     while (true)
     {
      Student student = new Student();
      student.Id = br.ReadString();
      student.Name = br.ReadString();
      student.Score1 = br.ReadDouble();
      student.Score2 = br.ReadDouble();
      student.Score3 = br.ReadDouble();
      stu.Add(student);
      student = null;
     }
    }
    catch (Exception)
    {
     Console.WriteLine("\n\n读取结束!");
    }
   }
   br.Close();
   fs.Close();
  }

下面是我的写入方法,写入参数List<Student> stu中的数据

/// <summary>
  /// 写入信息方法
  /// </summary>
  /// <returns>写入是否成功</returns>
  public void WriteInfo(List<Student> stu)
  {
   Console.WriteLine("请输入文件保存路径:(键入回车为默认路径)");
   FileStream fs;
   String filename = Console.ReadLine();
   //默认路径
   if (filename == "")
   {
    fs = new FileStream("student.dll", FileMode.Create);
   }
   //手动输入路径
   else
   {
    //如果文件存在,就提示错误
    if (File.Exists(filename))
    {
     Console.WriteLine("\n\t保存失败!\n错误原因:可能存在相同文件");
     return;
    }
    //否则创建文件
    fs = new FileStream(filename, FileMode.Create);
   }
   //数据保存到磁盘中
   BinaryWriter bw = new BinaryWriter(fs);
   foreach (Student student in stu)
   {
    bw.Write((String)student.Id);
    bw.Write((String)student.Name);
    bw.Write((Double)student.Score1);
    bw.Write((Double)student.Score2);
    bw.Write((Double)student.Score3);
    bw.Flush();
   }
   bw.Close();
   fs.Close();
   Console.WriteLine("保存成功!");
  }
========

C#二进制文件比较程序

http://blog.csdn.net/foart/article/details/7031577
转:http://www.cnblogs.com/hbhbice/archive/2010/06/30/1768477.html

下面是CompareFile.cs

[csharp] view plain copy print?
using System;  
 using System.Collections.Generic;  
 using System.Text;  
 using System.IO;  
 using System.Windows.Forms;  
 using System.Data;  
   
 namespace CompareFile  
 {  
     public  class FileCompare  
     {  
         private FileStream fs1, fs2;  
         private DataTable _DiffTab1,_DiffTab2;  
   
         public DataTable DiffTab1  
         {  
             get {  
                 return _DiffTab1;  
             }  
         }  
   
         public DataTable DiffTab2  
         {  
             get  
             {  
                 return _DiffTab2;  
             }  
         }  
   
         public FileCompare(FileStream fs1, FileStream fs2)  
         {  
             this.fs1 = fs1;  
             this.fs2 = fs2;  
         }  
   
         public void CompareAllFile()  
         {  
             if (fs1 .Length !=fs2.Length )  
             {  
                 if (MessageBox.Show("两文件长度不等\r\n文件1长:" + fs1.Length.ToString() + "\r\n文件2长:" + fs2.Length.ToString() + "\r\n是否继续比较?", "文件比较结果") == DialogResult.Cancel )  
                 {  
                     return;  
                 }  
             }  
             BinaryReader br1 = new BinaryReader (fs1 );  
             BinaryReader br2 = new BinaryReader (fs2);  
             long min = fs1.Length >= fs2.Length ? fs2.Length : fs1.Length;  
             for (long i = 0; i <min   ; i++)  
             {  
                 if ( br1 .ReadByte ()!=br2 .ReadByte ())  
                 {  
                     if (MessageBox.Show("从0起,第" + (br1.BaseStream.Position - 1).ToString() + "个字节不匹配" + "是否继续搜寻?", "文件比较",MessageBoxButtons.OKCancel) == DialogResult.OK)  
                     {  
   
                     }  
                     else   
                     {  
                         br1.BaseStream.Seek((br1.BaseStream.Position / 50) * 50, 0);  
                         br2.BaseStream.Seek((br1.BaseStream.Position / 50) * 50, 0);  
                         if (br1 .BaseStream .Length - br1 .BaseStream .Position >50&&br2 .BaseStream .Length - br2 .BaseStream .Position >50)  
                         {  
                             _DiffTab1 = new DataTable();  
                             _DiffTab2 = new DataTable();  
                             DataColumn dc1 = new DataColumn("位置");  
                             DataColumn dc2 = new DataColumn("数值");  
                             DataColumn dc3 = new DataColumn("位置");  
                             DataColumn dc4 = new DataColumn("数值");  
                             _DiffTab1.Columns.Add(dc1);  
                             _DiffTab1.Columns.Add(dc2);  
                             _DiffTab2.Columns.Add(dc3);  
                             _DiffTab2.Columns.Add(dc4);  
                             for (int j = 0; j < 50; j++)  
                             {  
                                 DataRow dr1 = _DiffTab1.NewRow();  
                                 dr1[0] = br1.BaseStream.Position;  
                                 dr1[1] = br1.ReadByte();  
                                 DiffTab1.Rows.Add(dr1);  
                                 DataRow dr2 = _DiffTab2.NewRow();  
                                 dr2[0] = br2.BaseStream.Position;  
                                 dr2[1] = br2.ReadByte();  
                                 DiffTab2.Rows.Add(dr2);  
                             }  
                         }  
                         return;                                  
                     }    
   
                 }  
                 if (fs1.Position == min )  
                 {  
                     MessageBox.Show("到达两文件中较小文件的尾部");  
                 }  
             }                     
   
         }  
     }  
 }

Form1.cs
[csharp] view plain copy print?
using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.Drawing;  
using System.Text;  
using System.Windows.Forms;  
using System.IO;  
  
namespace CompareFile  
{  
    public partial class Form1 : Form  
    {  
        FileStream fs1;  
        FileStream fs2;  
  
        public Form1()  
        {  
            InitializeComponent();  
        }  
  
        private void 打开OToolStripMenuItem_Click(object sender, EventArgs e)  
        {  
            if (openFileDialog1 .ShowDialog ()== DialogResult .OK )  
            {  
                fs1 = (FileStream )openFileDialog1.OpenFile();  
            }  
        }  
  
        private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)  
        {  
            if (openFileDialog1.ShowDialog ()== DialogResult .OK )  
            {  
                fs2 = (FileStream )openFileDialog1.OpenFile();  
            }  
        }  
  
        private void 自定义CToolStripMenuItem_Click(object sender, EventArgs e)  
        {  
            if (fs1 != null && fs2 != null)  
            {  
                CompareFile.FileCompare fc = new CompareFile.FileCompare(fs1, fs2);  
                fc.CompareAllFile();  
                dataGridView1.DataSource = fc.DiffTab1;  
                dataGridView2.DataSource = fc.DiffTab2;  
            }  
            else  
            {  
                MessageBox.Show ("请先将两个文件打开,然后再进行比较!");  
            }  
  
        }  
  
        private void 另存为AToolStripMenuItem_Click(object sender, EventArgs e)  
        {  
            fs1.Close();  
            fs2.Close();  
  
        }    
    }  
}

Form1.Designer.cs(如果界面方面不清楚,参考以下代码。)

[csharp] view plain copy print?
namespace CompareFile  
{  
    partial class Form1  
    {  
        /// <summary>  
        /// 必需的设计器变量。  
        /// </summary>  
        private System.ComponentModel.IContainer components = null;  
  
        /// <summary>  
        /// 清理所有正在使用的资源。  
        /// </summary>  
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>  
        protected override void Dispose(bool disposing)  
        {  
            if (disposing && (components != null))  
            {  
                components.Dispose();  
            }  
            base.Dispose(disposing);  
        }  
 
        #region Windows 窗体设计器生成的代码  
  
        /// <summary>  
        /// 设计器支持所需的方法 - 不要  
        /// 使用代码编辑器修改此方法的内容。  
        /// </summary>  
        private void InitializeComponent()  
        {  
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));  
            this.menuStrip1 = new System.Windows.Forms.MenuStrip();  
            this.文件FToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.新建NToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.打开OToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.保存SToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator();  
            this.另存为AToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();  
            this.打印PToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.打印预览VToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();  
            this.退出XToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.编辑EToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.撤消UToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.重复RToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();  
            this.剪切TToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.复制CToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.粘贴PToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();  
            this.全选AToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.工具TToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.自定义CToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.选项OToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.帮助HToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.内容CToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.索引IToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.搜索SToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();  
            this.关于AToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();  
            this.splitContainer1 = new System.Windows.Forms.SplitContainer();  
            this.dataGridView1 = new System.Windows.Forms.DataGridView();  
            this.dataGridView2 = new System.Windows.Forms.DataGridView();  
            this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();  
            this.toolStrip1 = new System.Windows.Forms.ToolStrip();  
            this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();  
            this.menuStrip1.SuspendLayout();  
            this.splitContainer1.Panel1.SuspendLayout();  
            this.splitContainer1.Panel2.SuspendLayout();  
            this.splitContainer1.SuspendLayout();  
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();  
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).BeginInit();  
            this.toolStrip1.SuspendLayout();  
            this.SuspendLayout();  
            //   
            // menuStrip1  
            //   
            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {  
            this.文件FToolStripMenuItem,  
            this.编辑EToolStripMenuItem,  
            this.工具TToolStripMenuItem,  
            this.帮助HToolStripMenuItem});  
            this.menuStrip1.Location = new System.Drawing.Point(0, 0);  
            this.menuStrip1.Name = "menuStrip1";  
            this.menuStrip1.Size = new System.Drawing.Size(676, 24);  
            this.menuStrip1.TabIndex = 0;  
            this.menuStrip1.Text = "menuStrip1";  
            //   
            // 文件FToolStripMenuItem  
            //   
            this.文件FToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {  
            this.新建NToolStripMenuItem,  
            this.打开OToolStripMenuItem,  
            this.保存SToolStripMenuItem,  
            this.toolStripSeparator,  
            this.另存为AToolStripMenuItem,  
            this.toolStripSeparator1,  
            this.打印PToolStripMenuItem,  
            this.打印预览VToolStripMenuItem,  
            this.toolStripSeparator2,  
            this.退出XToolStripMenuItem});  
            this.文件FToolStripMenuItem.Name = "文件FToolStripMenuItem";  
            this.文件FToolStripMenuItem.Size = new System.Drawing.Size(59, 20);  
            this.文件FToolStripMenuItem.Text = "文件(&F)";  
            //   
            // 新建NToolStripMenuItem  
            //   
            this.新建NToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("新建NToolStripMenuItem.Image")));  
            this.新建NToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.新建NToolStripMenuItem.Name = "新建NToolStripMenuItem";  
            this.新建NToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));  
            this.新建NToolStripMenuItem.Size = new System.Drawing.Size(190, 22);  
            this.新建NToolStripMenuItem.Text = "新建(&N)";  
            //   
            // 打开OToolStripMenuItem  
            //   
            this.打开OToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("打开OToolStripMenuItem.Image")));  
            this.打开OToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.打开OToolStripMenuItem.Name = "打开OToolStripMenuItem";  
            this.打开OToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));  
            this.打开OToolStripMenuItem.Size = new System.Drawing.Size(190, 22);  
            this.打开OToolStripMenuItem.Text = "打开文件1(&O)";  
            this.打开OToolStripMenuItem.Click += new System.EventHandler(this.打开OToolStripMenuItem_Click);  
            //   
            // 保存SToolStripMenuItem  
            //   
            this.保存SToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.保存SToolStripMenuItem.Name = "保存SToolStripMenuItem";  
            this.保存SToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)));  
            this.保存SToolStripMenuItem.Size = new System.Drawing.Size(190, 22);  
            this.保存SToolStripMenuItem.Text = "打开文件2(&S)";  
            this.保存SToolStripMenuItem.Click += new System.EventHandler(this.保存SToolStripMenuItem_Click);  
            //   
            // toolStripSeparator  
            //   
            this.toolStripSeparator.Name = "toolStripSeparator";  
            this.toolStripSeparator.Size = new System.Drawing.Size(187, 6);  
            //   
            // 另存为AToolStripMenuItem  
            //   
            this.另存为AToolStripMenuItem.Name = "另存为AToolStripMenuItem";  
            this.另存为AToolStripMenuItem.Size = new System.Drawing.Size(190, 22);  
            this.另存为AToolStripMenuItem.Text = "关闭两文件(&A)";  
            this.另存为AToolStripMenuItem.Click += new System.EventHandler(this.另存为AToolStripMenuItem_Click);  
            //   
            // toolStripSeparator1  
            //   
            this.toolStripSeparator1.Name = "toolStripSeparator1";  
            this.toolStripSeparator1.Size = new System.Drawing.Size(187, 6);  
            //   
            // 打印PToolStripMenuItem  
            //   
            this.打印PToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("打印PToolStripMenuItem.Image")));  
            this.打印PToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.打印PToolStripMenuItem.Name = "打印PToolStripMenuItem";  
            this.打印PToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P)));  
            this.打印PToolStripMenuItem.Size = new System.Drawing.Size(190, 22);  
            this.打印PToolStripMenuItem.Text = "打印(&P)";  
            //   
            // 打印预览VToolStripMenuItem  
            //   
            this.打印预览VToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("打印预览VToolStripMenuItem.Image")));  
            this.打印预览VToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.打印预览VToolStripMenuItem.Name = "打印预览VToolStripMenuItem";  
            this.打印预览VToolStripMenuItem.Size = new System.Drawing.Size(190, 22);  
            this.打印预览VToolStripMenuItem.Text = "打印预览(&V)";  
            //   
            // toolStripSeparator2  
            //   
            this.toolStripSeparator2.Name = "toolStripSeparator2";  
            this.toolStripSeparator2.Size = new System.Drawing.Size(187, 6);  
            //   
            // 退出XToolStripMenuItem  
            //   
            this.退出XToolStripMenuItem.Name = "退出XToolStripMenuItem";  
            this.退出XToolStripMenuItem.Size = new System.Drawing.Size(190, 22);  
            this.退出XToolStripMenuItem.Text = "退出(&X)";  
            //   
            // 编辑EToolStripMenuItem  
            //   
            this.编辑EToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {  
            this.撤消UToolStripMenuItem,  
            this.重复RToolStripMenuItem,  
            this.toolStripSeparator3,  
            this.剪切TToolStripMenuItem,  
            this.复制CToolStripMenuItem,  
            this.粘贴PToolStripMenuItem,  
            this.toolStripSeparator4,  
            this.全选AToolStripMenuItem});  
            this.编辑EToolStripMenuItem.Name = "编辑EToolStripMenuItem";  
            this.编辑EToolStripMenuItem.Size = new System.Drawing.Size(60, 20);  
            this.编辑EToolStripMenuItem.Text = "编辑(&E)";  
            //   
            // 撤消UToolStripMenuItem  
            //   
            this.撤消UToolStripMenuItem.Name = "撤消UToolStripMenuItem";  
            this.撤消UToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z)));  
            this.撤消UToolStripMenuItem.Size = new System.Drawing.Size(156, 22);  
            this.撤消UToolStripMenuItem.Text = "撤消(&U)";  
            //   
            // 重复RToolStripMenuItem  
            //   
            this.重复RToolStripMenuItem.Name = "重复RToolStripMenuItem";  
            this.重复RToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y)));  
            this.重复RToolStripMenuItem.Size = new System.Drawing.Size(156, 22);  
            this.重复RToolStripMenuItem.Text = "重复(&R)";  
            //   
            // toolStripSeparator3  
            //   
            this.toolStripSeparator3.Name = "toolStripSeparator3";  
            this.toolStripSeparator3.Size = new System.Drawing.Size(153, 6);  
            //   
            // 剪切TToolStripMenuItem  
            //   
            this.剪切TToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("剪切TToolStripMenuItem.Image")));  
            this.剪切TToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.剪切TToolStripMenuItem.Name = "剪切TToolStripMenuItem";  
            this.剪切TToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));  
            this.剪切TToolStripMenuItem.Size = new System.Drawing.Size(156, 22);  
            this.剪切TToolStripMenuItem.Text = "剪切(&T)";  
            //   
            // 复制CToolStripMenuItem  
            //   
            this.复制CToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("复制CToolStripMenuItem.Image")));  
            this.复制CToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.复制CToolStripMenuItem.Name = "复制CToolStripMenuItem";  
            this.复制CToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));  
            this.复制CToolStripMenuItem.Size = new System.Drawing.Size(156, 22);  
            this.复制CToolStripMenuItem.Text = "复制(&C)";  
            //   
            // 粘贴PToolStripMenuItem  
            //   
            this.粘贴PToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("粘贴PToolStripMenuItem.Image")));  
            this.粘贴PToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.粘贴PToolStripMenuItem.Name = "粘贴PToolStripMenuItem";  
            this.粘贴PToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));  
            this.粘贴PToolStripMenuItem.Size = new System.Drawing.Size(156, 22);  
            this.粘贴PToolStripMenuItem.Text = "粘贴(&P)";  
            //   
            // toolStripSeparator4  
            //   
            this.toolStripSeparator4.Name = "toolStripSeparator4";  
            this.toolStripSeparator4.Size = new System.Drawing.Size(153, 6);  
            //   
            // 全选AToolStripMenuItem  
            //   
            this.全选AToolStripMenuItem.Name = "全选AToolStripMenuItem";  
            this.全选AToolStripMenuItem.Size = new System.Drawing.Size(156, 22);  
            this.全选AToolStripMenuItem.Text = "全选(&A)";  
            //   
            // 工具TToolStripMenuItem  
            //   
            this.工具TToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {  
            this.自定义CToolStripMenuItem,  
            this.选项OToolStripMenuItem});  
            this.工具TToolStripMenuItem.Name = "工具TToolStripMenuItem";  
            this.工具TToolStripMenuItem.Size = new System.Drawing.Size(61, 20);  
            this.工具TToolStripMenuItem.Text = "工具(&T)";  
            //   
            // 自定义CToolStripMenuItem  
            //   
            this.自定义CToolStripMenuItem.Name = "自定义CToolStripMenuItem";  
            this.自定义CToolStripMenuItem.Size = new System.Drawing.Size(117, 22);  
            this.自定义CToolStripMenuItem.Text = "比较(&C)";  
            this.自定义CToolStripMenuItem.Click += new System.EventHandler(this.自定义CToolStripMenuItem_Click);  
            //   
            // 选项OToolStripMenuItem  
            //   
            this.选项OToolStripMenuItem.Name = "选项OToolStripMenuItem";  
            this.选项OToolStripMenuItem.Size = new System.Drawing.Size(117, 22);  
            this.选项OToolStripMenuItem.Text = "选项(&O)";  
            //   
            // 帮助HToolStripMenuItem  
            //   
            this.帮助HToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {  
            this.内容CToolStripMenuItem,  
            this.索引IToolStripMenuItem,  
            this.搜索SToolStripMenuItem,  
            this.toolStripSeparator5,  
            this.关于AToolStripMenuItem});  
            this.帮助HToolStripMenuItem.Name = "帮助HToolStripMenuItem";  
            this.帮助HToolStripMenuItem.Size = new System.Drawing.Size(61, 20);  
            this.帮助HToolStripMenuItem.Text = "帮助(&H)";  
            //   
            // 内容CToolStripMenuItem  
            //   
            this.内容CToolStripMenuItem.Name = "内容CToolStripMenuItem";  
            this.内容CToolStripMenuItem.Size = new System.Drawing.Size(128, 22);  
            this.内容CToolStripMenuItem.Text = "内容(&C)";  
            //   
            // 索引IToolStripMenuItem  
            //   
            this.索引IToolStripMenuItem.Name = "索引IToolStripMenuItem";  
            this.索引IToolStripMenuItem.Size = new System.Drawing.Size(128, 22);  
            this.索引IToolStripMenuItem.Text = "索引(&I)";  
            //   
            // 搜索SToolStripMenuItem  
            //   
            this.搜索SToolStripMenuItem.Name = "搜索SToolStripMenuItem";  
            this.搜索SToolStripMenuItem.Size = new System.Drawing.Size(128, 22);  
            this.搜索SToolStripMenuItem.Text = "搜索(&S)";  
            //   
            // toolStripSeparator5  
            //   
            this.toolStripSeparator5.Name = "toolStripSeparator5";  
            this.toolStripSeparator5.Size = new System.Drawing.Size(125, 6);  
            //   
            // 关于AToolStripMenuItem  
            //   
            this.关于AToolStripMenuItem.Name = "关于AToolStripMenuItem";  
            this.关于AToolStripMenuItem.Size = new System.Drawing.Size(128, 22);  
            this.关于AToolStripMenuItem.Text = "关于(&A)...";  
            //   
            // splitContainer1  
            //   
            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;  
            this.splitContainer1.Location = new System.Drawing.Point(0, 24);  
            this.splitContainer1.Name = "splitContainer1";  
            //   
            // splitContainer1.Panel1  
            //   
            this.splitContainer1.Panel1.Controls.Add(this.dataGridView1);  
            //   
            // splitContainer1.Panel2  
            //   
            this.splitContainer1.Panel2.Controls.Add(this.dataGridView2);  
            this.splitContainer1.Size = new System.Drawing.Size(676, 528);  
            this.splitContainer1.SplitterDistance = 326;  
            this.splitContainer1.TabIndex = 1;  
            //   
            // dataGridView1  
            //   
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;  
            this.dataGridView1.Location = new System.Drawing.Point(0, 28);  
            this.dataGridView1.Name = "dataGridView1";  
            this.dataGridView1.RowTemplate.Height = 23;  
            this.dataGridView1.Size = new System.Drawing.Size(326, 500);  
            this.dataGridView1.TabIndex = 0;  
            //   
            // dataGridView2  
            //   
            this.dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;  
            this.dataGridView2.Location = new System.Drawing.Point(0, 28);  
            this.dataGridView2.Name = "dataGridView2";  
            this.dataGridView2.RowTemplate.Height = 23;  
            this.dataGridView2.Size = new System.Drawing.Size(346, 500);  
            this.dataGridView2.TabIndex = 0;  
            //   
            // openFileDialog1  
            //   
            this.openFileDialog1.FileName = "openFileDialog1";  
            //   
            // toolStrip1  
            //   
            this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {  
            this.toolStripButton1});  
            this.toolStrip1.Location = new System.Drawing.Point(0, 24);  
            this.toolStrip1.Name = "toolStrip1";  
            this.toolStrip1.Size = new System.Drawing.Size(676, 25);  
            this.toolStrip1.TabIndex = 2;  
            this.toolStrip1.Text = "toolStrip1";  
            //   
            // toolStripButton1  
            //   
            this.toolStripButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;  
            this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));  
            this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta;  
            this.toolStripButton1.Name = "toolStripButton1";  
            this.toolStripButton1.Size = new System.Drawing.Size(23, 22);  
            this.toolStripButton1.Text = "toolStripButton1";  
            //   
            // Form1  
            //   
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);  
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;  
            this.ClientSize = new System.Drawing.Size(676, 552);  
            this.Controls.Add(this.toolStrip1);  
            this.Controls.Add(this.splitContainer1);  
            this.Controls.Add(this.menuStrip1);  
            this.MainMenuStrip = this.menuStrip1;  
            this.Name = "Form1";  
            this.Text = "Form1";  
            this.menuStrip1.ResumeLayout(false);  
            this.menuStrip1.PerformLayout();  
            this.splitContainer1.Panel1.ResumeLayout(false);  
            this.splitContainer1.Panel2.ResumeLayout(false);  
            this.splitContainer1.ResumeLayout(false);  
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();  
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).EndInit();  
            this.toolStrip1.ResumeLayout(false);  
            this.toolStrip1.PerformLayout();  
            this.ResumeLayout(false);  
            this.PerformLayout();  
  
        }  
 
        #endregion  
  
        private System.Windows.Forms.MenuStrip menuStrip1;  
        private System.Windows.Forms.ToolStripMenuItem 文件FToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 新建NToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 打开OToolStripMenuItem;  
        private System.Windows.Forms.ToolStripSeparator toolStripSeparator;  
        private System.Windows.Forms.ToolStripMenuItem 保存SToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 另存为AToolStripMenuItem;  
        private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;  
        private System.Windows.Forms.ToolStripMenuItem 打印PToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 打印预览VToolStripMenuItem;  
        private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;  
        private System.Windows.Forms.ToolStripMenuItem 退出XToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 编辑EToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 撤消UToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 重复RToolStripMenuItem;  
        private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;  
        private System.Windows.Forms.ToolStripMenuItem 剪切TToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 复制CToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 粘贴PToolStripMenuItem;  
        private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;  
        private System.Windows.Forms.ToolStripMenuItem 全选AToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 工具TToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 自定义CToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 选项OToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 帮助HToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 内容CToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 索引IToolStripMenuItem;  
        private System.Windows.Forms.ToolStripMenuItem 搜索SToolStripMenuItem;  
        private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;  
        private System.Windows.Forms.ToolStripMenuItem 关于AToolStripMenuItem;  
        private System.Windows.Forms.SplitContainer splitContainer1;  
        private System.Windows.Forms.OpenFileDialog openFileDialog1;  
        private System.Windows.Forms.DataGridView dataGridView1;  
        private System.Windows.Forms.DataGridView dataGridView2;  
        private System.Windows.Forms.ToolStrip toolStrip1;  
        private System.Windows.Forms.ToolStripButton toolStripButton1;    
    }  
}  
========

C# Parsing 类实现的 PDF 文件分析器

https://www.oschina.net/translate/pdf-file-analyzer-with-csharp-parsing-classes-vers

下载示例
下载源代码

1. 介绍

这个项目让你可以去读取并解析一个PDF文件,并将其内部结构展示出来. PDF文件的格式标准文档可以从Adobe那儿获取到. 这个项目基于“PDF指南,第六版,Adobe便携文档格式1.7 2006年11月”. 它是一个恐怕有1310页的大部头. 本文提供了对这份文档的简洁概述. 与此相关的项目定义了用来读取和解析PDF文件的C#类. 为了测试这些类,附带的测试程序PdfFileAnalyzer让你可以去读取一个PDF文件,分析它并展示和保存结果. 程序将PDF文件分割成单独每页的描述,字体,图片和其它对象. 有两种类型的PDF文件不受此程序的支持: 加密文件和多代文件.

这个程序的1.1版本允许世界各地使用点符号作为小数分隔符的程序员来编译和运行程序.

1.2版本则修复了一个有关使用跨多个引用流来读取PDF文档的问题. 1.2之前的版本对此场景只会以一个对象数字重复的错误而终止运行.

如果你对将PDF文件写入器引入你的应用程序,那就请读一读 "PDF 文件写入程序 C# 类库" 这篇文章吧.

PDF格式的文件,借助Adobe Acrobat软件,可以在各种屏幕上显示查看,使用各种打印机打印。但是,如果使用二进制文件编辑器打开PDF文件,你会发现文件的大部分是不可读的,有小部分是可读的,如下:

1 0 obj
<</Lang(en-CA)/MarkInfo<</Marked true>>/Pages 2 0 R
/StructTreeRoot 10 0 R/Type/Catalog>>
endobj
2 0 obj
<</Count 1/Kids[4 0 R]/Type/Pages>>
endobj 
4 0 obj
<</Contents 5 0 R/Group <</CS/DeviceRGB /S/Transparency /Type/Group>>
/MediaBox[0 0 612 792] /Parent 2 0 R
/Resources <</Font <</F1 6 0 R /F2 8 0 R>>
/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>
/StructParents 0/Tabs/S/Type/Page>>
endobj
5 0 obj
<</Filter/FlateDecode/Length 2319>>
stream
. . .
endstream
endobj
看上去,该文件是由嵌套在“n 0 OBJ ”和“ endobj ”关键词之间的对象组成的,术语PDF也就是间接对象的意思。 “obj”前面的数字是对象编号和第几代对象标识, 双尖括号中的内容表示数据字典对象,中括号中的内容表示数组对象, 以斜杠/ 开始的内容表示参数名称 (例如: /Pages)。上例中的第一项 “1 0 obj” 表示文档的目录或者文档的根对象。文档目录的字典对象 “/Pages 2 0 R”,指向定义页码树对象的引用。按照这样推算,编号为2的对象包含指向 “/Kids[4 0 R]”的页面的引用,是一个页面文档。 编号为4的对象是唯一的一个页面定义, 页面大小为612*792点, 换句话说,也就是8.5” * 11” (1” 代表72 点)点。该页面使用了两种字体F1和F2,这两种字体分别在编号为6和8的对象中定义。该页面的内容在编号为5的对象中描述,该对象中包含页面绘图的流信息,示例中的 “. . .”代表这部分流信息。如果使用二进制文件编辑器打开PDF文件,会发现这部分流信息看起来是一长串不可读的随机数,原因是那是压缩数据。流数据采用Zlib方法压缩,压缩方式由字典对象“/Filter /FlateDecode”描述,被压缩流的大小为2319字节。解压这部分流信息,前面几行内容如下所示:

q
37.08 56.424 537.84 679.18 re
W* n
/P <</MCID 0>> BDC 0.753 g
36.6 465.43 537.96 24.84 re
f*
EMC  /P <</MCID 1/Lang (x-none)>> BDC BT
/F1 18 Tf
1 0 0 1 39.6 718.8 Tm
0 g
0 G
[(GRA)29(NOTECH LI)-3(MIT)-4(ED)] TJ
ET
这是页面描述语言的一个小例子。 示例中, “re” 代表矩形,“re” 前面的4个数字代表矩形的位置和大小,依次为:起点横坐标、起点纵坐标、宽度、高度。

这个简单的例子演示了PDF文件内部实现的总体思路。从页面层次结构的根对象开始, 每一页都定义了诸如字体、图片、内容流的资源,内容流由操作符和绘制页面所需要的参数构成。PDF文件分析器会产生一个对象汇总文件,该文件包含非流对象的其他所有对象。每个数据流会被解码并保存为一个单独的文件, 页面描述流保存为文本格式的文件, 图片流保存为.jpg或.bmp格式的文件,字体流保存为.ttf格式的文件,其他二进制流保存为.bin 格式的文件,文本流保存为.txt格式的文件。通过另一个解析过程,晦涩难懂的页面描述会被转换为伪C#代码,如上例中的页面描述被转为:

SaveGraphicsState(); // q
Rectangle(37.08, 56.424, 537.84, 679.18); // re
ClippingPathEvenOddRule(); // W*
NoPaint(); // n
BeginMarkedContentPropList("/P", "<</MCID 0>>"); // BDC
GrayLevelForNonStroking(0.753); // g
Rectangle(36.6, 465.43, 537.96, 24.84); // re
FillEvenOddRule(); // f*
EndMarkedContent(); // EMC
BeginMarkedContentPropList("/P", "<</Lang(x-none)/MCID 1>>"); // BDC
BeginText(); // BT
SelectFontAndSize("/F1", 18); // Tf
TextMatrix(1, 0, 0, 1, 39.6, 718.8); // Tm
GrayLevelForNonStroking(0); // g
GrayLevelForStroking(0); // G
ShowTextWithGlyphPos("[(GRA)29(NOTECH LI)-3(MIT)-4(ED)]"); // TJ
EndTextObject(); // ET
文章接下来的部分将对PDF文件的结构和解析过程进行更为详细的描述,接下来的章节包括:对象定义,文件结构,文件解析,文件读取,以及使用PDF文件分析器编程。

3. 免责声明

pdf 文件分析器能处理大量的文件,这是我在自己的系统上扫描众多PDF文件的经验。不过,该程序不支持加密文件或者多个代文件(在对象不为零之前的第二个数字)。在PDF规格文件之中可用功能的数量是非常显著的。这并不可能为一个单的个开发者系统地测试所有的功能。如果在整个文件分析期间该程序抛出一个异常,将显示一条错误信息,该信息显示源代码模块名和行号。

4.对象定义

PDF文件生成多个对象。在PDF文件分析器项目中每个PDF对象都有一个对应的类。所有这些对象类都派生于PDFbase类。对象类定义源代码是BasicObjects.cs.确却地PDF对象定义在Adobe pdf文件 规格第三章之中是有用的

Boolean对象是靠PdfBoolean类来实现的. Boolean在PDF上的定义同C#上的是相同的.

Integer 对象是靠PdfInt类来实现的. PDF上的定义同C#上Int32的定义是相同的.

实数对象是靠PdfReal类来实现的. PDF上的定义同C#上的Single定义相同.

String 对象是靠PdfStr类来实现的. PDF上的定义同C#相比有所不同. String 是用字节构造出来的,而不是字符. 它被包在圆括号()里面. PdfFileAnalyzer会把包含在圆括号中的C#字符串保存成PDF的字符串. PDF的字符串对于ASCII编码非常有用.

十六进制字符串独享是靠PdfHex类来实现的. 它是由每字节两个十六进制数定义,并包在尖括号里面的字符串. PdfFileAnalyzer 将包含在尖括号中的C#字符串保存成PDF十六进制字符串. 对于 PDF 读取器,字符串和十六进制字符串对象可用于同种目的. 字符串 (AB) 等同于<4142>. PDF 十六进制字符串对于任意编码的场景非常有用.

Name 对象是靠PdfName类来实现的. Name 对象是由打头的正斜杠后面跟着一些字符组成的. 例如 /Width. Named 对象用作参数名称. PdfFileAnalyzer 将正斜杠开头的C#字符串保存成Name对象.

Null 对象是靠PdfNull类来实现的. PDF 对于null的定义基本上同C#中的是一样的.

4.2. 复合的对象

Array 对象是靠 PdfArray 类来实现的. PDF 数组是一个封装在一堆中括号中的对象的集合. 一个数组的对象可以是除了流之外的任何对象.PdfFileAnalyzer 将一个C#数组中的对象保存成PdfBase类

. 因为所有的对象都继承自PdfBase,所有在这个数组中保存多种类型的对象没有啥问题. 当数组对象被转换成一个字符串时(使用ToString()方法), 程序会在首位添加中括号. 数组可以是空的. 下面是一个有六个对象的数组示例: [120 9.56 true null (string) <414243>].

Dictionary 对象是靠PdfDict类实现的. PDF 字典是一组被包入一对双尖括号中的键值对集合. Dictionary 的键是一个对象的名称,而值则可以是除了流之外的任何对象.  PdfFileAnalyzer 将一个键值对保存到PdfPair类中. 键是一个C#字符串,而值则是一个PdfBase.PdfDict 类有一个PdfPair类的数组. Dictionary 可以用键来访问. 因而键值对的顺序没有啥意义. PdfFileAnalyzer 用键来对键值对进行排序. 下面是一个有三个键值对的字典: <</CropBox [0 0 612 792] /Rotate 0 /Type /Page>>.

Stream 对象是靠PdfStream来实现的. Streams 被用来处理面熟语言,图形和字体. PDF Stream 由一个字典和一个字节流组成. 字典中定义了流的参数. 比如流对象中字典的一个键值对 /Filter. PDF 文档定义了10种类型的过滤器. PdfFileAnalyzer 支持了4种. 这是我发现在实际场景中只会被用到那4种. 压缩过滤器 FlateDecode 是现在的PDF写入器最长被用到的过滤器. FlateDecode支持ZLib解压缩. LZWDecode 压缩过滤器在过去些年用的比较多. 为了能读取比较老的PDF文件, 我们的程序支持这个过滤器. ASCII85Decode 过滤器将可被打印的ASCII转换成二进制位. DCTDecode 用于JPEG图像的压缩.PdfFileAnalyzer 为前三种实现了解压缩. DCTDecode 流则以文件扩展名.jpg保存. 它是一个可以被展示的图片文件.

Object 流在PDF 1.5中被引入. 它是一个包含多个间接对象(在下面会描述道)的流. 上面描述的Stream 对象一次只压缩一个流. Object 流会将所有包含进来的流压缩到一个压缩域中.

多引用流在PDF 1.5中被引入. 它是一个包含多引用表格的流,下文会描述到.

内联图片对象是靠 PdfInlineImage来实现的. 它是一个带有一个流的流. 内联图片是页面描述语言的一部分. 它由BI-开头图形, ID-图形数据和EI-结尾图形这三个操作符组成. BI 和 ID 之间的区域是一个图形字典,而ID 和 EI 之间的区域则包含图形数据.

4.3. 间接对象

间接对象是靠 PdfIndirectObject实现的. 它是一个PDF文档的主要构造块. 间接对象是任何被包在 “n 0 obj” 和 “endobj”之间的对象. 其它对象可以通过设定“n 0 R”来引用间接对象. “n”代表对象编号. “0”代表生成编号. 这个程序不支持0之外的生成编号. PDF 规范允许其它的编号. 多代生成的理念允许PDF的修改操作是在保留原有文件的基础上追加变更.

对象引用时一种引用间接对象的方法. 例如 /Pages 2 0 R 是目录对象中的字典里的一项. 它是一个指向 /Pages 对象的指针. pages对象是编号为2的间接对象.

4.4. 操作符和关键词

操作符和关键词不被认为是PDF对象. 而PdfFileAnalyzer 程序有一个PdfOp 和一个PdfKeyword 类可以从中得到 PdfBase 的类. 在转换过程中,转换器为每一个可用的字符序列创建了一个 PdfOp 或者PdfKeyword . Pdf文件规范的附录A-操作符总结中列出了所有的操作符. 列表中有73个操作符. 下面是一些操作符的示例: BT-打头的文本对象, G-用于做记号的设置灰度操作, m-移动到, re-矩形和Tc-设置字符间距. 下面是关键词的示例: stream, obj, endobj, xref.

5. 文件结构

PDF文件由四个部分构成: 头部Header , 主体body, 多引用cross-reference 和附带签名 trailer signature.

Header: 头部是文件的签名. 它必须是 %PDF-1.x , x 从 0 到 7.

Body: 主体区域包含所有的间接对象.

Cross-reference: 多引用是一个指向所有间接对象的文件位置指针列表. 有两种类型的多引用表格. 原始的类型有ASCII字符组成. 新式的是一个包含一个间接对象的流. 信息以二进制数字编码. 在多引用表格的结束部分有一个附件字典. 一个文件可以有超过一个的多引用区域.

Trailer signature: 附带签名由关键词“startxref”, 最后一个多引用表格的偏移位, 和结束签名 %%EOF 组成. 请注意: 附带签名是多引用区域的一部分.

6. 文件转换

PDF 文件是一个字节的序列. 一些字节有特殊的意义.

空格被定义成: null, tab, 换行, 换页, 回车和间隔.

分隔符被定义成: (, ), <, >, [, ], {, }, /, %, 以及空格字符.

文件转换是由PdfParser 类来完成的. 开始进行转换过程是,程序会设置文件需要被转换区域的位置. ParseNextItem() 是提取下一个对象的方法.

解析器跳过空格符和注释。如果下一个字节是“(”,判断对象为一个字符串。如果下一个字节是“[”,判断对象是一个数组。如果接下来的两个字节是“<<”,判断对象是一个字典。如果下一个字节是“<”,判断对象是一个十六进制字符串。如果下一个字节是“/”,判断对象是一个名称。如果下一个字节不是上述任何一种,解析器会采集随后的字节直到发现定界符。定界符不是当前标记符的一部分。标记符可以是整数,实数,操作符或关键词。在整数的情况下,程序将进一步搜索对象引用“n 0 R”或间接对象“n 0 obj”中 n 为该整数的对象。从 ParseNextItem() 返回的值是第4节“对象的定义”中所述的适当对象。对象的类作为 PdfBase 类返回。

在数组或字典的情况下,程序将执行递归调用 ParseNextItem() 来解析数组或字典的内部对象。

7. 文件读取

PdfDocument 类是 PDF 文件分析的主要类。入口方法是 ReadPdfFile(String FileName)。程序以二进制读取的方式打开 PDF 文件(一次一个字节)。

文件分析开始于检查头部签名 %PDF-1.x(x为0到7)和结尾签名%%EOF。有人会认为,所有的 PDF 生成器会把头部签名放在文件的零位置,结尾签名放在文件的最后。不幸的是,实际并非如此。程序必须在文件的两端搜索这两个签名。如果头部签名不在零位置,所有间接对象的文件位置的指针也必须调整。

就在结尾签名的前面有一个指向最后一个交叉引用表开始位置的指针。
========

Windows下的开源二进制文件编辑器HexEdit

http://blog.okbase.net/haobao/archive/65.html
 
作者:Andrew Phillips
 
[译者按]HexEdit是一个伟大的软件,多少年来一直未伴随着我们,如今作者释放出全部源代码,真的让我们感激万分。本文摘录翻译了部分,原文请参见http://www.codeproject.com/Articles/135474/HexEdit-Window-Binary-File-Editor
  
介绍
我在去年公测后发布了hexedit 4.0正式版。测试版工作得很好,所以我并没有急于释放正式版,有些小BUG需要修复。
 
HexEdit用C++编写,需要VS2008(带功能包)、VS2012或后续版本和MFC的支持。你很容易编译生成它,如果有问题请参阅“生成HexEdit 4.0”章节,现在也有一个工程文件是针对VS2012的。
 
HexEdit(1999年)的第一个版本是开源的,但后来的版本是共享软件(虽然我一直坚持在做一个免费的版本)。hexedit的2.0开放源代码,因为它使用了一些BCG商业库。(BCG库是一个很好的MFC扩展库,所以我不后悔使用它。)幸运的是,几年前,微软买了BCG代码,并把它纳入MFC。所以,现在hexedit的4.0是第一次开源(见 http://www.hexedit.com);也有一个共享软件版本,可用于那些想为它支付的朋友(见 http://www.hexeditpro.com),增加了一些小功能。
 
要生成hexedit 4.0中,您只需要Visual Studio,加上一些开放的源代码和库(其中大部分来自CodeProject)。您可以使用程序或任何的源代码,不管出于什么目的,你认为合适的,只要你遵守的相关许可要求(见下文)或任何包含第三方代码的具体要求。
 
开发历史
 
我在1997-1998写的HexEdit,当时工作中需要用到,而那时正缺少十六进制编辑器。
hexedit被设计为易于使用和用户熟悉的Windows软件,就像MS Word和Visual Studio。事实上,它借鉴了一些常见的Windows程序的很多思路。
 
代码文件
HexEdit.h - CHexEditApp 类是应用程序类。
Stdafx.h - 预编译头文件
resource.h - 资源 IDs,用于 HexEdit.rc 和C++代码
 
MainFrm.h - 主程序窗口MFC类
ChildFrm.h - 处理每个文件的窗口类
HexEditDoc.h - CHexEditDoc 类 (参阅 HexEditDoc.cpp, DocData.cpp, Template.cpp, BGSearch.cpp, BGAerial.cpp).
HexEditView.h - CHexEditView 类(参阅 HexEditView.cpp 和 Printer.cpp)
ScrView.h - CScrView 提供了可滚屏的视图 (CHexEditView的基类)
DataFormatView.h - CDataFormatView 处理模板显示 (参阅 Template.cpp)
AerialView.h - CAerialView class - 显示 aerial 视图 (参阅 BGAerial.cpp)
 
Prop.h - 属性对话框类 (property sheet, property pages and controls)
BookMarkDlg.h - CBookMarkDlg 对话框用于显示、添加书签(参见bookmark.h) 
FindDlg.h - 查找对话框对应类 (property sheet and pages) 
Explorer.h - HexEdit 浏览对话框 (dialog and control classes) 
CalcDlg.h - CCalcDlg 计算器对话框类 (see also CalcEdit.h below)
 
Options.h - 选项对话框的属性页
DFFD*.h - 模板编辑对话框 
TParseDlg.h - 模板编辑时使用的C/C++分析对话框 (参见TParse.h)
NewFile.h - “新文件”和“插入块”对话框
OpenSpecialDlg.h - 磁盘编辑打开特殊对话框 (参见SpecialList.h) 
RecentFileDlg.h - 显示最近使用的文件对话框 (参见HexFileList.h) 
CopyCSrc.h - CCopyCSrc对话框,用于 "Copy As C Source" 
Algorithm.h - CAlgorithm 类用于加密算法对话框
Password.h - CPassword 类用于密码加密对话框
CompressDlg.h - zlib压缩对话框
EmailDlg.h - 邮件对话框
Tipdlg.h - 显示每日技巧
Dialog.h - 在宏中使用的对话框 (GetStr CMacroMessage CSaveMessage CMultiplay
- 还有CFileDialog 派生类,包括 CHexFileDialog)
HexPrintDialog.h - 自定义打印对话框 (重载 MFC CPrintDialog 
SaveDffd.h - 模板没有保存时的提示对话框 (save/save as/cancel) 
NewScheme.h - small dialog used when creating a new color scheme 
BookmarkFind.h - used by Find dialog when bookmarking found occurrences 
DirDialog.h - directory selection dialog (see below)
 
Splasher.h - CSplashWnd for splash screen (see below) 
TipWnd.h - CWnd derived class to show a small "tip" window (see below) 
TransparentListBox.h, TransparentStatic2.h - transparent controls (see below) 
CCalcEdit.h - CCalcEdit class which handles calculator edit box 
control.h - various text and combo controls used in dialogs and on toolbars
 
GenDockablePane.h - dockable window used to makes Calculator, Find dialog etc dockable 
ResizeCtrl.h - CResizeCtrl (see below) 
BCGMisc.h - a few classes derived from BCG (now MFC) classes 
UserTool.h - CHexEditUserTool is derived from CUserToolto allow command line substition for user tools 
SimpleSplitter.h - CSimpleSplitter is used in Explorer dialog for the split between folder/file sections 
HexEditSplitter.h - CHexEditSplitter allows showing aerial/template views in a split window 
TabView.h - CHexTabView (derived from CTabView allows showing aerial/template views in tabs 
CoordAp.h - CPointAp CSizeAp CRectAp (see below) for 64-bit (vertically) coordinate system
 
TParser.h - 用于TParseDlg的C/C++代码分析器 (参阅下面的TParseDlg.h) 
HexEditMacro.h - handles recording and playback of Keystroke macros 
HexFileList.h - stores global list of all recent files 
SpecialList.h - stores info about that volumes and raw disks in the system 
Bookmark.h - CBookmarkList class for global storage for bookmarks 
Scheme.h - CScheme stores all color schemes 
NavManager.h - global storage of navigation points 
SystemSound.h - CSystemSound contains static method for getting, setting, playing sounds (see below) 
Timer.h - timer class can time events (see below)
 
UpdateChecker.h - 通过Internet检测HexEdit的最新版本
Xmltree.h - 封装了MS XML SDK
BigInter.h - BigInteger 类用于处理大于64位的数字
CFile64.h - CFile64 类用于64位文件处理 
crypto.h - CCrypto 类封装了 Crypto API
Boyer.h - boyer类用于搜索
range_set.h - template class for set with ranges (see below) 
Expr.h - expr_eval class handles C-like expressions (used in templates etc) 
IntelHex.h - CReadIntelHexand CWriteIntelHex (see below) 
SRecord.h - CReadSRecordand CWriteSRecord (see below)
 
misc.h - 杂项全局函数
md5.h - routines for generating an MD5 checksum
ntapi.h - declarations for direct access to NT API (bypassing Windows) for disk editor 
w2k_def.h - more NT (not 9X) info - included by ntapi.h 
optypes.h - defines unary and binary operations (for Calculator and Operations menu)
SVNRevisionTemplate.h - used by SVN uitlity to create SVNRevision.hSVNRevision.h - just stores 
 
相关内容
下载源代码:http://www.okbase.net/file/item/19711
更多内容请参见http://www.codeproject.com/Articles/135474/HexEdit-Window-Binary-File-Editor
========

C#二进制文件编程实践相关推荐

  1. c# 二进制文件编程实践

    转载连接:http://blog.csdn.net/bcbobo21cn/article/details/69571692?locationNum=11&fps=1#t0 C读写二进制文件 C ...

  2. 【组队学习】【29期】1. 编程实践(数据可视化)

    1. 编程实践(数据可视化) 航路开辟者:杨剑砺.杨煜.耿远昊.李运佳.居凤霞 领航员:范佳慧 航海士:杨剑砺.伊雪.肖桐.李晴晴.蔡婧旎 基本信息 开源内容:https://github.com/d ...

  3. 【组队学习】【26期】编程实践(Python办公自动化)

    编程实践(Python办公自动化) 论坛版块: http://datawhale.club/c/team-learning/29-category/29 开源内容: https://github.co ...

  4. 【组队学习】【26期】编程实践(Django网站开发)

    编程实践(Django网站开发) 论坛版块: http://datawhale.club/c/team-learning/28-category/28 开源内容: https://github.com ...

  5. 【组队学习】【23期】Datawhale编程实践(区块链)

    编程实践(区块链) 开源内容:https://github.com/datawhalechina/team-learning-program/tree/master/Blockchain 基本信息 贡 ...

  6. [Java 并发] Java并发编程实践 思维导图 - 第一章 简单介绍

    阅读<Java并发编程实践>一书后整理的思维导图.

  7. 《Java并发编程实践》学习笔记之一:基础知识

    <Java并发编程实践>学习笔记之一:基础知识 1.程序与进程 1.1 程序与进程的概念 (1)程序:一组有序的静态指令,是一种静态概念:  (2)进程:是一种活动,它是由一个动作序列组成 ...

  8. 郑捷《机器学习算法原理与编程实践》学习笔记(第七章 预测技术与哲学)7.1 线性系统的预测...

    7.1.1 回归与现代预测 7.1.2 最小二乘法 7.1.3 代码实现 (1)导入数据 def loadDataSet(self,filename): #加载数据集X = [];Y = []fr = ...

  9. 《深入理解大数据:大数据处理与编程实践》一一3.3 HDFS文件存储组织与读写...

    本节书摘来自华章计算机<深入理解大数据:大数据处理与编程实践>一书中的第3章,第3.3节,作者 主 编:黄宜华(南京大学)副主编:苗凯翔(英特尔公司),更多章节内容可以访问云栖社区&quo ...

最新文章

  1. python中with的用法
  2. jquery中ajax格式
  3. python中的set和dict_Python中dict和set的用法讲解
  4. 走进5G | 腾讯技术工程5G技术沙龙开启报名啦!
  5. SpringCloud版本名字
  6. hdl四位二进制计数器_四位二进制加法计数器
  7. OpenCV--罗德里格斯(Rodrigues)变换
  8. 材料的构成 —— 塑料
  9. 计算机一级考试wps教程视频教程,全国计算机等级考试一级WPS Office教程(2008年版)...
  10. android 换机 备份,Android QQ同步助手3.7:资料备份让换机刷机无忧
  11. y=asin(wx+φ)的对称中心_y=asin(wx+φ)怎么求
  12. ai面试的优缺点_AI面试是什么?有哪些特点呢?
  13. android mapping文件作用,Android打包代码混淆后的Mapping文件路径
  14. ubuntu下比较好用的msn聊天工具
  15. 北京地铁计价模型分析及计价系统设计
  16. 英剧推荐【IT狂人】
  17. 浏览器被360劫持怎么办
  18. 计算机硬件——显示器原理
  19. 快看快看,这款免费的低代码平台绝绝子
  20. 神经管理学告诉你:学了管理学就能运筹帷幄吗?

热门文章

  1. mysql数据库可以升级吗_[数据库]MySQL升级
  2. python字典的数据结构_Python数据结构之三——dict(字典)
  3. 动态代理(JDK的动态代理)
  4. 取 1~100之间的随机整数
  5. Bugku 杂项 隐写2 Welcome_.jpg
  6. Jquery中替换节点的方法replaceWith()和replaceAll()
  7. IntelliJ IDEA绑定Github报Error 403: Not Authorized没有授权问题解决方法
  8. Python 图像处理篇-利用opencv库和numpy库读取包含中文路径下的本地图片实例演示
  9. STM32F103CUBE学习笔记 一 环境安装
  10. DOSbox汇编环境配置