golang读写ISO9660磁盘镜像文件插件库iso9660的使用

golang读写ISO9660磁盘镜像文件插件库iso9660的使用

简介

iso9660 是一个用于读取和创建ISO9660格式磁盘镜像的Go语言库。需要注意的是,该库不支持Joliet扩展,但正在实验性地支持读取Rock Ridge扩展。如果遇到问题,可以使用v0.3版本,它会忽略Rock Ridge扩展。

基本使用示例

提取ISO镜像内容

package main

import (
  "log"
  "os"

  "github.com/kdomanski/iso9660/util"
)

func main() {
  f, err := os.Open("/home/user/myImage.iso")
  if err != nil {
    log.Fatalf("failed to open file: %s", err)
  }
  defer f.Close()

  if err = util.ExtractImageToDirectory(f, "/home/user/target_dir"); err != nil {
    log.Fatalf("failed to extract image: %s", err)
  }
}

创建ISO镜像

package main

import (
  "log"
  "os"

  "github.com/kdomanski/iso9660"
)

func main() {
  writer, err := iso9660.NewWriter()
  if err != nil {
    log.Fatalf("failed to create writer: %s", err)
  }
  defer writer.Cleanup()

  f, err := os.Open("/home/user/myFile.txt")
  if err != nil {
    log.Fatalf("failed to open file: %s", err)
  }
  defer f.Close()

  err = writer.AddFile(f, "folder/MYFILE.TXT")
  if err != nil {
    log.Fatalf("failed to add file: %s", err)
  }

  outputFile, err := os.OpenFile("/home/user/output.iso", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
  if err != nil {
    log.Fatalf("failed to create file: %s", err)
  }

  err = writer.WriteTo(outputFile, "testvol")
  if err != nil {
    log.Fatalf("failed to write ISO image: %s", err)
  }

  err = outputFile.Close()
  if err != nil {
    log.Fatalf("failed to close output file: %s", err)
  }
}

递归地从目录创建ISO镜像

package main

import (
  "fmt"
  "log"
  "os"
  "path/filepath"
  "strings"

  "github.com/kdomanski/iso9660"
)

func main() {
  writer, err := iso9660.NewWriter()
  if err != nil {
    log.Fatalf("failed to create writer: %s", err)
  }
  defer writer.Cleanup()

  isoFile, err := os.OpenFile("C:/output.iso", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
  if err != nil {
    log.Fatalf("failed to create file: %s", err)
  }
  defer isoFile.Close()

  prefix := "F:\\" // 输出ISO文件中要去除的前缀
  sourceFolders := []string{"F:\\test1", "F:\\test2"} // 要创建ISO文件的目录

  for _, folderName := range sourceFolders {
    folderPath := strings.Join([]string{prefix, folderName}, "/")

    walk_err := filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error {
      if err != nil {
        log.Fatalf("walk: %s", err)
        return err
      }
      if info.IsDir() {
        return nil
      }
      outputPath := strings.TrimPrefix(path, prefix) // 移除源驱动器名称
      fmt.Printf("Adding file: %s\n", outputPath)

      fileToAdd, err := os.Open(path)
      if err != nil {
        log.Fatalf("failed to open file: %s", err)
      }
      defer fileToAdd.Close()

      err = writer.AddFile(fileToAdd, outputPath)
      if err != nil {
        log.Fatalf("failed to add file: %s", err)
      }
      return nil
    })
    if walk_err != nil {
      log.Fatalf("%s", walk_err)
    }
  }

  err = writer.WriteTo(isoFile, "Test")
  if err != nil {
    log.Fatalf("failed to write ISO image: %s", err)
  }
}

注意事项

  1. 该库不支持Joliet扩展
  2. Rock Ridge扩展支持是实验性的,如果遇到问题可以使用v0.3版本
  3. 创建ISO时需要注意文件名格式,ISO9660标准对文件名有限制(如大写字母、长度等)

更多关于golang读写ISO9660磁盘镜像文件插件库iso9660的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang读写ISO9660磁盘镜像文件插件库iso9660的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 读写 ISO9660 磁盘镜像文件的 iso9660 库使用指南

ISO9660 是 CD-ROM 文件系统的标准格式,在 Go 中可以使用 github.com/kdomanski/iso9660 这个第三方库来处理 ISO9660 镜像文件。

安装 iso9660 库

首先需要安装这个库:

go get github.com/kdomanski/iso9660

读取 ISO9660 镜像文件

1. 打开 ISO 文件并读取内容

package main

import (
	"fmt"
	"log"
	"os"
	
	"github.com/kdomanski/iso9660"
)

func main() {
	// 打开 ISO 文件
	f, err := os.Open("example.iso")
	if err != nil {
		log.Fatalf("Failed to open ISO file: %v", err)
	}
	defer f.Close()

	// 读取 ISO 内容
	image, err := iso9660.OpenImage(f)
	if err != nil {
		log.Fatalf("Failed to read ISO image: %v", err)
	}

	// 获取根目录
	root, err := image.RootDir()
	if err != nil {
		log.Fatalf("Failed to get root directory: %v", err)
	}

	// 遍历文件系统
	err = iso9660.WalkDir(root, func(d *iso9660.File, path string) error {
		fmt.Printf("Found: %s (size: %d bytes)\n", path, d.Size())
		return nil
	})
	
	if err != nil {
		log.Fatalf("Failed to walk directory: %v", err)
	}
}

2. 提取 ISO 中的文件

func extractFileFromISO(isoPath, filePath, outputPath string) error {
	// 打开 ISO 文件
	f, err := os.Open(isoPath)
	if err != nil {
		return fmt.Errorf("failed to open ISO file: %v", err)
	}
	defer f.Close()

	// 读取 ISO 内容
	image, err := iso9660.OpenImage(f)
	if err != nil {
		return fmt.Errorf("failed to read ISO image: %v", err)
	}

	// 获取根目录
	root, err := image.RootDir()
	if err != nil {
		return fmt.Errorf("failed to get root directory: %v", err)
	}

	// 查找指定文件
	file, err := root.GetEntry(filePath)
	if err != nil {
		return fmt.Errorf("failed to find file %s: %v", filePath, err)
	}

	// 创建输出文件
	outFile, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("failed to create output file: %v", err)
	}
	defer outFile.Close()

	// 复制文件内容
	_, err = file.CopyTo(outFile)
	if err != nil {
		return fmt.Errorf("failed to extract file: %v", err)
	}

	return nil
}

创建 ISO9660 镜像文件

1. 创建简单的 ISO 文件

func createSimpleISO(outputPath string) error {
	// 创建临时目录结构
	tmpDir, err := os.MkdirTemp("", "iso-example")
	if err != nil {
		return fmt.Errorf("failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	// 在临时目录中创建一些文件
	file1 := filepath.Join(tmpDir, "README.txt")
	if err := os.WriteFile(file1, []byte("This is a test ISO file"), 0644); err != nil {
		return fmt.Errorf("failed to create test file: %v", err)
	}

	subDir := filepath.Join(tmpDir, "docs")
	if err := os.Mkdir(subDir, 0755); err != nil {
		return fmt.Errorf("failed to create subdirectory: %v", err)
	}

	file2 := filepath.Join(subDir, "notes.txt")
	if err := os.WriteFile(file2, []byte("Some important notes"), 0644); err != nil {
		return fmt.Errorf("failed to create notes file: %v", err)
	}

	// 创建输出文件
	outFile, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("failed to create output file: %v", err)
	}
	defer outFile.Close()

	// 创建 ISO 写入器
	writer, err := iso9660.NewWriter()
	if err != nil {
		return fmt.Errorf("failed to create ISO writer: %v", err)
	}
	defer writer.Cleanup()

	// 添加目录内容
	if err := writer.AddDirectory(tmpDir); err != nil {
		return fmt.Errorf("failed to add directory to ISO: %v", err)
	}

	// 写入 ISO 文件
	if err := writer.WriteTo(outFile, "MY_ISO"); err != nil {
		return fmt.Errorf("failed to write ISO image: %v", err)
	}

	return nil
}

2. 高级选项创建 ISO

func createAdvancedISO(outputPath string) error {
	// 创建写入器并设置选项
	writer, err := iso9660.NewWriterWithOptions(iso9660.WriterConfig{
		RockRidge:    true,  // 启用 Rock Ridge 扩展
		VolumeID:     "MY_DATA_DISC",
		Publisher:    "My Company",
		DataPreparer: "Go ISO Creator",
	})
	if err != nil {
		return fmt.Errorf("failed to create ISO writer: %v", err)
	}
	defer writer.Cleanup()

	// 手动添加文件
	if err := writer.AddFile("README.txt", strings.NewReader("Important information")); err != nil {
		return fmt.Errorf("failed to add file: %v", err)
	}

	// 添加目录
	if err := writer.AddDirectory("docs/"); err != nil {
		return fmt.Errorf("failed to add directory: %v", err)
	}

	// 创建输出文件
	outFile, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("failed to create output file: %v", err)
	}
	defer outFile.Close()

	// 写入 ISO
	if err := writer.WriteTo(outFile, "ADVANCED_ISO"); err != nil {
		return fmt.Errorf("failed to write ISO image: %v", err)
	}

	return nil
}

注意事项

  1. 权限问题:ISO9660 有严格的权限限制,创建文件时需要注意
  2. 文件名限制:标准 ISO9660 文件名限制为 8.3 格式(8字符名+3字符扩展名)
  3. 扩展支持:可以通过 Rock Ridge 或 Joliet 扩展支持长文件名
  4. 大文件支持:标准 ISO9660 限制单个文件最大 4GB

总结

github.com/kdomanski/iso9660 库提供了简单易用的 API 来读写 ISO9660 镜像文件。通过这个库,你可以:

  • 提取 ISO 镜像中的文件和目录
  • 创建新的 ISO 镜像文件
  • 自定义 ISO 卷标和元数据
  • 支持 Rock Ridge 扩展

以上示例代码涵盖了最常见的用例,你可以根据需要进一步扩展功能。

回到顶部