【问题标题】:Reading specific parts of a binary file in Java在 Java 中读取二进制文件的特定部分
【发布时间】:2015-01-26 14:27:14
【问题描述】:

我已经构建了一个简单的 Java 程序来从 FRX 属性文件中读取数据。然而,我遇到的问题是我需要能够只从文件中读取二进制文件的特定部分。更具体地说,我需要从与给定十六进制值对应的值开始从文件中读取,并在给定文本字符串的 ASCII 字符停止处结束读取。

我可以使用以下程序在 C# 中做到这一点:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

    public class GetFromFRX
    {
        public static void Main()
        {
            StringBuilder buffer = new StringBuilder();
            using (BinaryReader b = new BinaryReader(File.Open("frmResidency.frx", FileMode.Open)))
            {
                try
                {
                    b.BaseStream.Seek(641, SeekOrigin.Begin);
                    int length = b.ReadInt32();

                    for (int i = 0; i < length; i++)
                    {
                        buffer.Append(b.ReadChar());
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine( "Error obtaining resource\n" + e.Message);
                }

            }
            Console.WriteLine(buffer);
        }
    }

这是我的 Java 程序,我相信我可以使用 DataInputStream 来做我需要的事情,但是我不确定如何使用它的方法来寻找一个十六进制位置来开始读取字节并正确设置长度.如果我运行这个当前代码,我的新文本文件中没有输出,我希望输出超过前 10 个字节,所以我想我不理解 ReadInt()skipBytes 正确:

  import java.io.*;
  import java.util.*;

  public class Tester3 {
    public static void main(String[] args) throws IOException {

        FileInputStream in = null;
        FileOutputStream out = null;
        DataInputStream din = null;
        DataOutputStream dout = null;

        try {
            in = new FileInputStream("frmResidency.frx");
            din = new DataInputStream(in);
            out = new FileOutputStream("disisworkinlikeacharm.txt");
            dout = new DataOutputStream(out);
            din.skipBytes(10);
            int length = din.readInt();
            int c;

            for(c = 0 ; c < length; c++){
                out.write(c);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
            if (dout != null) {
                dout.close();
            }
            if (din != null) {
                din.close();
            }
        }
    }
}

我的问题是,有没有一种简单的方法可以在我的代码中实现寻找某个十六进制位置并将二进制文件读取到一定长度,或者我应该使用类似 RandomAccessFile 完成这个...

【问题讨论】:

    标签: java c# binary-data fileinputstream datainputstream


    【解决方案1】:

    好吧,我看到了一个问题:您正在编写 for 循环的索引变量,而不是文件中的下一个字节。您至少应该将 out.write(c) 切换为 out.write(din.)。您希望写入接下来的 10 个整数还是接下来的 10 个字节?假设您要写入接下来的十个字节,以下对我有用:

    import java.io.DataInputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Test {
    
        public static void main(String[] args) throws IOException {
    
            FileInputStream in = null;
            FileOutputStream out = null;
            try {
                in = new FileInputStream("c:\\tmp\\test.txt");
                DataInputStream din = new DataInputStream(in);
                out = new FileOutputStream("c:\\tmp\\test.out");
                DataOutputStream dout = new DataOutputStream(out);
    
                din.skipBytes(10);
                int length = din.readInt();
                System.out.println(length);
                int c;
    
                for (c = 0; c < length; c++) {
                    // TODO: first read byte and check for EOF
                    out.write(din.read());
                }
            } finally {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            }
        }
    }
    

    如果您可以使用 Java 7,则使用 try-with-resources 循环的代码要少得多。此代码适用于 Java 6。我只关闭文件输入/输出流,因为它们应该是维护文件句柄的。当然,为了安全起见,您可以关闭其他流。

    【讨论】:

    • 我应该删除try,因为它没有使用catchfinally?此外,我认为您的代码中有一些括号错误。不过,我正在尝试实现您的逻辑。
    • 不,没有错误。括号是 try-with-resources 的一部分。如果您使用的是 Java 6,请告诉我,我将重写示例。
    • 是的,是的,对不起,我使用的是 Java 6,忽略了这一点。
    • 抱歉,我结束了这个问题,因为我觉得你的回答充分回答了我最初的问题,但我有一个轻微的后续问题。如果我在我的程序中打印出length,我会得到一个非常大的负值。此外,我无法将任何内容打印到我的文本文件中。但是,如果我将c &lt; length 替换为小于某个任意字节数的 c,则我没有该问题并实际打印出字节。您知道为什么会发生这种情况吗?
    • 这与skipBytes有关,我已经确定。不完全确定为什么。
    【解决方案2】:

    使用 din.skipBytes(pos) 移动到输入中所需的偏移量。

    【讨论】:

    • 您没有在 for 循环中读取任何内容。您错过了对 din.readByte() 或其他读取函数的调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 2019-02-09
    • 1970-01-01
    • 2015-07-27
    • 2021-07-26
    相关资源
    最近更新 更多